X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FPresenter%2FPart.pm;h=8131eff14ad590e4aea643e14845780ccaf0b060;hb=c18a652e2cd4409fce9c8383a9fbcc0e31e6a83f;hp=5ec55503a0d7911c0d3b95dea3d292a3350a7a7a;hpb=862bc8ce30cd40b67d2856ac7f1d11d5e4322f09;p=kivitendo-erp.git diff --git a/SL/Presenter/Part.pm b/SL/Presenter/Part.pm index 5ec55503a..8131eff14 100644 --- a/SL/Presenter/Part.pm +++ b/SL/Presenter/Part.pm @@ -3,47 +3,125 @@ package SL::Presenter::Part; use strict; use SL::DB::Part; +use SL::DB::PartClassification; +use SL::Locale::String qw(t8); +use SL::Presenter::EscapedText qw(escape is_escaped); +use SL::Presenter::Tag qw(input_tag html_tag name_to_id select_tag); use Exporter qw(import); -our @EXPORT = qw(part_picker part); +our @EXPORT_OK = qw( + part_picker part select_classification classification_abbreviation + type_abbreviation separate_abbreviation typeclass_abbreviation +); +our %EXPORT_TAGS = (ALL => \@EXPORT_OK); use Carp; sub part { - my ($self, $part, %params) = @_; + my ($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} ? '' : '', + escape($part->partnumber), $params{no_link} ? '' : '', ); - return $self->escaped_text($text); + + is_escaped($text); } sub part_picker { - my ($self, $name, $value, %params) = @_; + my ($name, $value, %params) = @_; $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 $id = $params{id} || name_to_id($name); 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 => "@classes", type => 'hidden', id => $id) . - join('', map { $params{$_} ? $self->input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(part_type unit convertible_unit)) . - $self->input_tag("", ref $value ? $value->displayable_name : '', id => "${id}_name", %params); + input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id, + 'data-part-picker-data' => JSON::to_json(\%params), + ) . + input_tag("", ref $value ? $value->displayable_name : '', id => "${id}_name", %params); - $::request->layout->add_javascripts('autocomplete_part.js'); + $::request->layout->add_javascripts('kivi.Part.js'); $::request->presenter->need_reinit_widgets($id); - $self->html_tag('span', $ret, class => 'part_picker'); + html_tag('span', $ret, class => 'part_picker'); +} + +sub picker { goto &part_picker } + +# +# shortcut for article type +# +sub type_abbreviation { + my ($part_type) = @_; + return $::locale->text('Assembly (typeabbreviation)') if $part_type eq 'assembly'; + return $::locale->text('Part (typeabbreviation)') if $part_type eq 'part'; + return $::locale->text('Assortment (typeabbreviation)') if $part_type eq 'assortment'; + return $::locale->text('Service (typeabbreviation)'); +} + +# +# Translations for Abbreviations: +# +# $::locale->text('None (typeabbreviation)') +# $::locale->text('Purchase (typeabbreviation)') +# $::locale->text('Sales (typeabbreviation)') +# $::locale->text('Merchandise (typeabbreviation)') +# $::locale->text('Production (typeabbreviation)') +# +# and for descriptions +# $::locale->text('Purchase') +# $::locale->text('Sales') +# $::locale->text('Merchandise') +# $::locale->text('Production') + +# +# shortcut for article type +# +sub classification_abbreviation { + my ($id) = @_; + SL::DB::Manager::PartClassification->cache_all(); + my $obj = SL::DB::PartClassification->load_cached($id); + $obj && $obj->abbreviation ? t8($obj->abbreviation) : ''; +} + +sub typeclass_abbreviation { + my ($part) = @_; + return '' if !$part || !$part->isa('SL::DB::Part'); + return type_abbreviation($part->part_type) . classification_abbreviation($part->classification_id); +} + +# +# shortcut for article type +# +sub separate_abbreviation { + my ($id) = @_; + SL::DB::Manager::PartClassification->cache_all(); + my $obj = SL::DB::PartClassification->load_cached($id); + $obj && $obj->abbreviation && $obj->report_separate ? t8($obj->abbreviation) : ''; +} + +# +# generate selection tag +# +sub select_classification { + my ($name, %attributes) = @_; + + $attributes{value_key} = 'id'; + $attributes{title_key} = 'description'; + + my $classification_type_filter = delete $attributes{type} // []; + + my $collection = SL::DB::Manager::PartClassification->get_all_sorted( where => $classification_type_filter ); + $_->description($::locale->text($_->description)) for @{ $collection }; + select_tag( $name, $collection, %attributes ); } 1; @@ -59,7 +137,7 @@ SL::Presenter::Part - Part related presenter stuff =head1 SYNOPSIS # Create an html link for editing/opening a part/service/assembly - my $object = my $object = SL::DB::Manager::Part->get_first; + my $object = SL::DB::Manager::Part->get_first; my $html = SL::Presenter->get->part($object, display => 'inline'); see also L @@ -93,6 +171,40 @@ to the corresponding 'edit' action. =over 2 +=item C + +Returns the shortcut of the classification + +=back + +=over 2 + +=item C + +Returns the shortcut of the classification if the classification has the separate flag set. + +=back + +=over 2 + +=item C + +Returns an HTML select tag with all available classifications. + +C<%params> can include: + +=over 4 + +=item * default + +The id of the selected item. + +=back + +=back + +=over 2 + =item C All-in-one picker widget for parts. The name will be both id and name @@ -121,10 +233,47 @@ 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 +rendering. If you write a standard controller that only calls 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. +include C yourself. + +On pressing the picker will try to commit the current selection, +resulting in one of the following events, whose corresponding callbacks can be +set in C: + +=over 4 + +=item * C + +If exactly one element matches the input, the internal id will be set to this +id, the internal state will be set to C and the C event on the +picker will be fired. Additionally, if C contains C a +special event C will be fired which is guaranteed to +contain a complete JSON representation of the part. + +After that the action C will be executed, which defaults to +clicking a button with id C for backward compatibility reasons. + +=item * C + +If more than one element matches the input, the internal state will be set to +undefined. + +After that the action C will be executed, which defaults to +opening a popup dialog for graphical interaction. If C contains +C an alternative popup will be opened, allowing multiple items to be +selected. Note however that this requires an additional callback +C to work. + +=item * C + +If no element matches the input, the internal state will be set to undefined. + +If an action for C exists, it will be called with the picker +object and current term. The caller can then implement creation of new parts. + +=back =back @@ -169,6 +318,14 @@ Should not require a feedback/check loop in the common case Should not be constrained to exact matches +=item * + +Must be atomic + +=item * + +Action should be overridable + =back The implementation consists of the following parts which will be referenced later: @@ -214,4 +371,6 @@ None atm :) Sven Schöling Es.schoeling@linet-services.deE +Martin Helmling Emartin.helmling@opendynamic.deE + =cut