X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FPresenter%2FPart.pm;h=3088eaa31c1f18db464c3af420252b6d44bf39f4;hb=f143a10a13313bca78b97e107bd3b870e5db7d98;hp=bef55a35f2f0623ed574e47728de85aa89cd346a;hpb=7a6466811399cba50ab3a55f18665b5663f6d3a5;p=kivitendo-erp.git
diff --git a/SL/Presenter/Part.pm b/SL/Presenter/Part.pm
index bef55a35f..3088eaa31 100644
--- a/SL/Presenter/Part.pm
+++ b/SL/Presenter/Part.pm
@@ -2,18 +2,46 @@ package SL::Presenter::Part;
use strict;
+use SL::DB::Part;
+
use Exporter qw(import);
-our @EXPORT = qw(part_picker);
+our @EXPORT = qw(part_picker part);
+
+use Carp;
+
+sub part {
+ my ($self, $part, %params) = @_;
+
+ $params{display} ||= 'inline';
+
+ croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
+
+ my $text = join '', (
+ $params{no_link} ? '' : '',
+ $self->escape($part->partnumber),
+ $params{no_link} ? '' : '',
+ );
+ return $self->escaped_text($text);
+}
sub part_picker {
my ($self, $name, $value, %params) = @_;
- my $name_e = $self->escape($name);
+
+ $value = SL::DB::Manager::Part->find_by(id => $value) if $value && !ref $value;
+ my $id = delete($params{id}) || $self->name_to_id($name);
+ my $fat_set_item = delete $params{fat_set_item};
+
+ my @classes = $params{class} ? ($params{class}) : ();
+ push @classes, 'part_autocomplete';
+ push @classes, 'partpicker_fat_set_item' if $fat_set_item;
my $ret =
- $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => 'part_autocomplete', type => 'hidden') .
- $self->input_tag("", delete $params{type}, id => $self->name_to_id("$name_e\_type"), type => 'hidden') .
- $self->input_tag("", (ref $value && $value->can('description')) ? $value->description : '', id => $self->name_to_id("$name_e\_name"), %params) .
- $self->input_tag("", delete $params{column}, id => $self->name_to_id("$name_e\_column"), type => 'hidden');
+ $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id) .
+ join('', map { $params{$_} ? $self->input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(type unit convertible_unit)) .
+ $self->input_tag("", ref $value ? $value->displayable_name : '', id => "${id}_name", %params);
+
+ $::request->layout->add_javascripts('autocomplete_part.js');
+ $::request->presenter->need_reinit_widgets($id);
$self->html_tag('span', $ret, class => 'part_picker');
}
@@ -26,11 +54,15 @@ __END__
=head1 NAME
-SL::Presenter::Part - Part lelated presenter stuff
+SL::Presenter::Part - Part related presenter stuff
=head1 SYNOPSIS
-see L
+ # Create an html link for editing/opening a part/service/assembly
+ my $object = my $object = SL::DB::Manager::Part->get_first;
+ my $html = SL::Presenter->get->part($object, display => 'inline');
+
+see also L
=head1 DESCRIPTION
@@ -38,27 +70,145 @@ see L
=head1 FUNCTIONS
+=over 2
+
+=item C
+
+Returns a rendered version (actually an instance of
+L) of the part object C<$object>
+
+C<%params> can include:
+
+=over 4
+
+=item * display
+
+Either C (the default) or C. At the moment both
+representations are identical and produce the part's name linked
+to the corresponding 'edit' action.
+
+=back
+
+=back
+
+=over 2
+
+=item C
+
+All-in-one picker widget for parts. The name will be both id and name
+of the resulting hidden C input field (but the ID can be
+overwritten with C<$params{id}>).
+
+An additional dummy input will be generated which is used to find
+parts. For a detailed description of its behaviour, see section
+C.
+
+C<$value> can be a parts id or a C instance.
+
+If C<%params> contains C only parts of this type will be used
+for autocompletion. You may comma separate multiple types as in
+C.
+
+If C<%params> contains C only parts with this unit will be used
+for autocompletion. You may comma separate multiple units as in
+C.
+
+If C<%params> contains C only parts with a unit
+that's convertible to unit will be used for autocompletion.
+
+Obsolete parts will by default not be displayed for selection. However they are
+accepted as default values and can persist during updates. As with other
+selectors though, they are not selectable once overridden.
+
+C will register it's javascript for inclusion in the next header
+rendering. If you write a standard controller that only call C once, it
+will just work. In case the header is generated in a different render call
+(multiple blocks, ajax, old C style controllers) you need to
+include C yourself.
+
+=back
+
+=head1 PART PICKER SPECIFICATION
+
+The following list of design goals were applied:
+
=over 4
-=item C
+=item *
+
+Parts should not be perceived by the user as distinct inputs of partnumber and
+description but as a single object
+
+=item *
+
+Easy to use without documentation for novice users
+
+=item *
+
+Fast to use with keyboard for experienced users
+
+=item *
+
+Possible to use without any keyboard interaction for mouse (or touchscreen)
+users
+
+=item *
+
+Must not leave the current page in event of ambiguity (cf. current select_item
+mechanism)
+
+=item *
+
+Should be useable with hand scanners or similar alternative keyboard devices
+
+=item *
+
+Should not require a feedback/check loop in the common case
+
+=item *
+
+Should not be constrained to exact matches
+
+=back
+
+The implementation consists of the following parts which will be referenced later:
+
+=over 4
+
+=item 1
+
+A hidden input (id input), used to hold the id of the selected part. The only
+input that gets submitted
+
+=item 2
+
+An input (dummy input) containing a description of the currently selected part,
+also used by the user to search for parts
+
+=item 3
+
+A jquery.autocomplete mechanism attached to the dummy field
+
+=item 4
+
+A popup layer for both feedback and input of additional data in case of
+ambiguity.
-All-in-one picker widget for parts. The name will be both id and name of the
-resulting hidden C input field. An additional dummy input will be generated
-which is used to find parts. For a detailed description of it's behaviour, see
-section C.
+=item 5
-C can be an id or C instance.
+An internal status of the part picker, indicating whether id input and dummy
+input are consistent. After leaving the dummy input the part picker must
+place itself in a consistent status.
-If C contains C only parts of this type will be used for autocompletion.
+=item 6
-Obsolete parts will by default not displayed for selection. However they are
-accepted as default values and can persist during updates.
+A clickable icon (popup trigger) attached to the dummy input, which triggers the popup layer.
=back
=head1 BUGS
-None yet :)
+None atm :)
=head1 AUTHOR