Projekt

Allgemein

Profil

Herunterladen (9,71 KB) Statistiken
| Zweig: | Markierung: | Revision:
2504ebe1 Sven Schöling
package SL::Presenter::Part;

use strict;

2477c498 Moritz Bunkus
use SL::DB::Part;
65d2537d Martin Helmling
use SL::DB::PartClassification;
use SL::Locale::String qw(t8);
0e5e3501 Sven Schöling
use SL::Presenter::EscapedText qw(escape is_escaped);
use SL::Presenter::Tag qw(input_tag html_tag name_to_id select_tag);
2477c498 Moritz Bunkus
2504ebe1 Sven Schöling
use Exporter qw(import);
0e5e3501 Sven Schöling
our @EXPORT_OK = qw(
part_picker part select_classification classification_abbreviation
type_abbreviation separate_abbreviation typeclass_abbreviation
);
our %EXPORT_TAGS = (ALL => \@EXPORT_OK);
f33995ff Geoffrey Richardson
use Carp;

sub part {
0e5e3501 Sven Schöling
my ($part, %params) = @_;
f33995ff Geoffrey Richardson
$params{display} ||= 'inline';

croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;

my $text = join '', (
0e5e3501 Sven Schöling
$params{no_link} ? '' : '<a href="controller.pl?action=Part/edit&part.id=' . escape($part->id) . '">',
escape($part->partnumber),
f33995ff Geoffrey Richardson
$params{no_link} ? '' : '</a>',
);
0e5e3501 Sven Schöling
is_escaped($text);
f33995ff Geoffrey Richardson
}
2504ebe1 Sven Schöling
sub part_picker {
0e5e3501 Sven Schöling
my ($name, $value, %params) = @_;
2504ebe1 Sven Schöling
20576aac Sven Schöling
$value = SL::DB::Manager::Part->find_by(id => $value) if $value && !ref $value;
0e5e3501 Sven Schöling
my $id = $params{id} || name_to_id($name);
ee74ea82 Sven Schöling
my @classes = $params{class} ? ($params{class}) : ();
push @classes, 'part_autocomplete';
2504ebe1 Sven Schöling
my $ret =
0e5e3501 Sven Schöling
input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id,
426a5bf3 Sven Schöling
'data-part-picker-data' => JSON::to_json(\%params),
) .
0e5e3501 Sven Schöling
input_tag("", ref $value ? $value->displayable_name : '', id => "${id}_name", %params);
2504ebe1 Sven Schöling
5aec18fe Sven Schöling
$::request->layout->add_javascripts('kivi.Part.js');
3ac83c61 Moritz Bunkus
$::request->presenter->need_reinit_widgets($id);

0e5e3501 Sven Schöling
html_tag('span', $ret, class => 'part_picker');
2504ebe1 Sven Schöling
}

0e5e3501 Sven Schöling
sub picker { goto &part_picker }

65d2537d Martin Helmling
#
# shortcut for article type
#
sub type_abbreviation {
0e5e3501 Sven Schöling
my ($part_type) = @_;
0ca195cd Bernd Bleßmann
return '' if !$part_type;
65d2537d Martin Helmling
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 {
0e5e3501 Sven Schöling
my ($id) = @_;
0ca195cd Bernd Bleßmann
return '' if !$id;

65d2537d Martin Helmling
SL::DB::Manager::PartClassification->cache_all();
my $obj = SL::DB::PartClassification->load_cached($id);
$obj && $obj->abbreviation ? t8($obj->abbreviation) : '';
}

ea1c5dfb Martin Helmling
sub typeclass_abbreviation {
0e5e3501 Sven Schöling
my ($part) = @_;
ea1c5dfb Martin Helmling
return '' if !$part || !$part->isa('SL::DB::Part');
0e5e3501 Sven Schöling
return type_abbreviation($part->part_type) . classification_abbreviation($part->classification_id);
ea1c5dfb Martin Helmling
}

219d88ab Martin Helmling
#
# shortcut for article type
#
sub separate_abbreviation {
0e5e3501 Sven Schöling
my ($id) = @_;
0ca195cd Bernd Bleßmann
return '' if !$id;

219d88ab Martin Helmling
SL::DB::Manager::PartClassification->cache_all();
my $obj = SL::DB::PartClassification->load_cached($id);
$obj && $obj->abbreviation && $obj->report_separate ? t8($obj->abbreviation) : '';
}

65d2537d Martin Helmling
#
# generate selection tag
#
sub select_classification {
0e5e3501 Sven Schöling
my ($name, %attributes) = @_;
ce904bd6 Geoffrey Richardson
65d2537d Martin Helmling
$attributes{value_key} = 'id';
$attributes{title_key} = 'description';
ce904bd6 Geoffrey Richardson
my $classification_type_filter = delete $attributes{type} // [];

my $collection = SL::DB::Manager::PartClassification->get_all_sorted( where => $classification_type_filter );
65d2537d Martin Helmling
$_->description($::locale->text($_->description)) for @{ $collection };
0e5e3501 Sven Schöling
select_tag( $name, $collection, %attributes );
65d2537d Martin Helmling
}

2504ebe1 Sven Schöling
1;
9aaadfdc Sven Schöling
__END__

=encoding utf-8

=head1 NAME

f33995ff Geoffrey Richardson
SL::Presenter::Part - Part related presenter stuff
9aaadfdc Sven Schöling
=head1 SYNOPSIS

f33995ff Geoffrey Richardson
# Create an html link for editing/opening a part/service/assembly
5eb16622 Geoffrey Richardson
my $object = SL::DB::Manager::Part->get_first;
f33995ff Geoffrey Richardson
my $html = SL::Presenter->get->part($object, display => 'inline');

see also L<SL::Presenter>
9aaadfdc Sven Schöling
=head1 DESCRIPTION

see L<SL::Presenter>

=head1 FUNCTIONS

f33995ff Geoffrey Richardson
=over 2

=item C<part, $object, %params>

Returns a rendered version (actually an instance of
L<SL::Presenter::EscapedText>) of the part object C<$object>

C<%params> can include:

9aaadfdc Sven Schöling
=over 4

f33995ff Geoffrey Richardson
=item * display

Either C<inline> (the default) or C<table-cell>. At the moment both
representations are identical and produce the part's name linked
to the corresponding 'edit' action.

=back

2f6a11fb Bernd Bleßmann
=back
f33995ff Geoffrey Richardson
=over 2

65d2537d Martin Helmling
=item C<classification_abbreviation $classification_id>

Returns the shortcut of the classification

=back

=over 2

219d88ab Martin Helmling
=item C<separate_abbreviation $classification_id>

5eb16622 Geoffrey Richardson
Returns the shortcut of the classification if the classification has the separate flag set.
219d88ab Martin Helmling
=back

=over 2

65d2537d Martin Helmling
=item C<select_classification $name,%params>

5eb16622 Geoffrey Richardson
Returns an HTML select tag with all available classifications.
65d2537d Martin Helmling
C<%params> can include:

=over 4

=item * default

5eb16622 Geoffrey Richardson
The id of the selected item.
65d2537d Martin Helmling
=back

=back

=over 2

9e278d06 Moritz Bunkus
=item C<part_picker $name, $value, %params>
9aaadfdc Sven Schöling
9e278d06 Moritz Bunkus
All-in-one picker widget for parts. The name will be both id and name
of the resulting hidden C<id> input field (but the ID can be
overwritten with C<$params{id}>).
9aaadfdc Sven Schöling
9e278d06 Moritz Bunkus
An additional dummy input will be generated which is used to find
976b1ddf Geoffrey Richardson
parts. For a detailed description of its behaviour, see section
9e278d06 Moritz Bunkus
C<PART PICKER SPECIFICATION>.
9aaadfdc Sven Schöling
9e278d06 Moritz Bunkus
C<$value> can be a parts id or a C<Rose::DB:Object> instance.
9aaadfdc Sven Schöling
862bc8ce Geoffrey Richardson
If C<%params> contains C<part_type> only parts of this type will be used
9e278d06 Moritz Bunkus
for autocompletion. You may comma separate multiple types as in
C<part,assembly>.
9aaadfdc Sven Schöling
2de6b963 Bernd Bleßmann
If C<%params> contains C<status> only parts of this status will be used
for autocompletion. C<status> can be one of the following strings:
C<active>, C<obsolete> or C<all>. C<active> is the default if C<status> is
not given.

880a2e9f Moritz Bunkus
If C<%params> contains C<unit> only parts with this unit will be used
for autocompletion. You may comma separate multiple units as in
C<h,min>.
9aaadfdc Sven Schöling
df33875f Moritz Bunkus
If C<%params> contains C<convertible_unit> only parts with a unit
that's convertible to unit will be used for autocompletion.
9aaadfdc Sven Schöling
976b1ddf Geoffrey Richardson
Obsolete parts will by default not be displayed for selection. However they are
58e12eca Sven Schöling
accepted as default values and can persist during updates. As with other
5c48c74b Sven Schöling
selectors though, they are not selectable once overridden.
58e12eca Sven Schöling
c89986ac Sven Schöling
C<part_picker> will register it's javascript for inclusion in the next header
5162c8cc Sven Schöling
rendering. If you write a standard controller that only calls C<render> once, it
will just work. In case the header is generated in a different render call
5aa4c453 Bernd Bleßmann
(multiple blocks, ajax, old C<bin/mozilla> style controllers) you need to
5aec18fe Sven Schöling
include C<kivi.Part.js> yourself.
9aaadfdc Sven Schöling
5162c8cc Sven Schöling
On pressing <enter> the picker will try to commit the current selection,
resulting in one of the following events, whose corresponding callbacks can be
set in C<params.actions>:

=over 4

=item * C<commit_one>

5eb16622 Geoffrey Richardson
If exactly one element matches the input, the internal id will be set to this
id, the internal state will be set to C<PICKED> and the C<change> event on the
picker will be fired. Additionally, if C<params> contains C<fat_set_item> a
special event C<set_item:PartPicker> will be fired which is guaranteed to
5162c8cc Sven Schöling
contain a complete JSON representation of the part.

After that the action C<commit_one> will be executed, which defaults to
clicking a button with id C<update_button> for backward compatibility reasons.

=item * C<commit_many>

If more than one element matches the input, the internal state will be set to
undefined.

After that the action C<commit_one> will be executed, which defaults to
5eb16622 Geoffrey Richardson
opening a popup dialog for graphical interaction. If C<params> contains
5162c8cc Sven Schöling
C<multiple> an alternative popup will be opened, allowing multiple items to be
selected. Note however that this requires an additional callback
C<set_multi_items> to work.

=item * C<commit_none>

If no element matches the input, the internal state will be set to undefined.

If an action for C<commit_none> exists, it will be called with the picker
object and current term. The caller can then implement creation of new parts.

=back

9aaadfdc Sven Schöling
=back

81e4602d Sven Schöling
=head1 PART PICKER SPECIFICATION

The following list of design goals were applied:

=over 4

=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 *

976b1ddf Geoffrey Richardson
Should not be constrained to exact matches
81e4602d Sven Schöling
5162c8cc Sven Schöling
=item *

Must be atomic

=item *

Action should be overridable

81e4602d Sven Schöling
=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.

=item 5

976b1ddf Geoffrey Richardson
An internal status of the part picker, indicating whether id input and dummy
81e4602d Sven Schöling
input are consistent. After leaving the dummy input the part picker must
place itself in a consistent status.

=item 6

A clickable icon (popup trigger) attached to the dummy input, which triggers the popup layer.

=back

9aaadfdc Sven Schöling
=head1 BUGS

686cf1ec Sven Schöling
None atm :)
9aaadfdc Sven Schöling
=head1 AUTHOR

Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>

65d2537d Martin Helmling
Martin Helmling E<lt>martin.helmling@opendynamic.deE<gt>

9aaadfdc Sven Schöling
=cut