1 package SL::Presenter::Chart;
7 use Exporter qw(import);
9 our @EXPORT = qw(chart_picker chart);
14 my ($self, $chart, %params) = @_;
16 $params{display} ||= 'inline';
18 croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
21 $params{no_link} ? '' : '<a href="am.pl?action=edit_account&id=' . $self->escape($chart->id) . '">',
22 $self->escape($chart->accno),
23 $params{no_link} ? '' : '</a>',
25 return $self->escaped_text($text);
29 my ($self, $name, $value, %params) = @_;
31 $value = SL::DB::Manager::Chart->find_by(id => $value) if $value && !ref $value;
32 my $id = delete($params{id}) || $self->name_to_id($name);
33 my $fat_set_item = delete $params{fat_set_item};
35 my @classes = $params{class} ? ($params{class}) : ();
36 push @classes, 'chart_autocomplete';
37 push @classes, 'chartpicker_fat_set_item' if $fat_set_item;
40 $self->input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id) .
41 join('', map { $params{$_} ? $self->input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(type category choose booked)) .
42 $self->input_tag("", (ref $value && $value->can('displayable_name')) ? $value->displayable_name : '', id => "${id}_name", %params);
44 $::request->layout->add_javascripts('autocomplete_chart.js');
45 $::request->presenter->need_reinit_widgets($id);
47 $self->html_tag('span', $ret, class => 'chart_picker');
58 SL::Presenter::Chart - Chart related presenter stuff
62 # Create an html link for editing/opening a chart
63 my $object = SL::DB::Manager::Chart->get_first;
64 my $html = SL::Presenter->get->chart($object, display => 'inline');
66 see also L<SL::Presenter>
76 =item C<chart, $object, %params>
78 Returns a rendered version (actually an instance of
79 L<SL::Presenter::EscapedText>) of the chart object C<$object>
81 C<%params> can include:
87 Either C<inline> (the default) or C<table-cell>. At the moment both
88 representations are identical and produce the chart's name linked
89 to the corresponding 'edit' action.
97 =item C<chart_picker $name, $value, %params>
99 All-in-one picker widget for charts. The code was originally copied and adapted
100 from the part picker. The name will be both id and name of the resulting hidden
101 C<id> input field (but the ID can be overwritten with C<$params{id}>).
103 An additional dummy input will be generated which is used to find
104 chart. For a detailed description of its behaviour, see section
105 C<CHART PICKER SPECIFICATION>.
107 For some examples of usage see the test page at controller.pl?action=Chart/test_page
109 C<$value> can be a chart id or a C<Rose::DB:Object> instance.
111 C<%params> can include:
117 If C<%params> contains C<category> only charts of this category will be
118 available for selection (in the autocompletion and in the popup).
120 You may comma separate multiple categories, e.g C<A,Q,L>.
122 In SL::DB::Manager::Chart there is also a filter called C<selected_category>,
123 which filters the possible charts according to the category checkboxes the user
124 selects in the popup window. This filter may further restrict the results of
125 the filter category, but the user is not able to "break out of" the limits
126 defined by C<category>. In fact if the categories are restricted by C<category>
127 the popup template should only show checkboxes for those categories.
131 If C<%params> contains C<type> only charts of this type will be used for
132 autocompletion, i.e. the selection is filtered. You may comma separate multiple
135 Type is usually a filter for link: C<AR,AR_paid>
137 Type can also be a specially defined type: C<guv>, C<balance>, C<bank>
139 See the type filter in SL::DB::Manager::Chart.
143 If C<%params> is passed with choose=1 the input of the filter field in the
144 popup window is cleared. This is useful if a chart was already selected and we
145 want to choose a new chart and immediately see all options.
149 If C<%params> is passed with fat_set_item=1 the contents of the selected chart
150 object (the elements of the database chart table) are passed back via JSON into
151 the item object. There is an example on the test page.
153 Without fat_set_item only the variables id and name (displayable name) are
158 C<chart_picker> will register its javascript for inclusion in the next header
159 rendering. If you write a standard controller that only calls C<render> once, it
160 will just work. In case the header is generated in a different render call
161 (multiple blocks, ajax, old C<bin/mozilla> style controllers) you need to
162 include C<js/autocomplete_part.js> yourself.
168 For users that don't regularly do bookkeeping and haven't memorised all the
169 account numbers and names there are some filter options inside the popup window
170 to quickly narrow down the possible matches. You can filter by
174 =item * chart accno or description, inside the input field
176 =item * accounts that have already been booked
178 =item * by category (AIELQC)
180 By selecting category checkboxes the list of available charts can be
181 restricted. If all checkboxes are unchecked all possible charts are shown.
185 There are two views in the list of accounts. By default all possible accounts are shown as a long list.
187 But you can also show more information, in this case the resulting list is automatically paginated:
191 =item * the balance of the account (as determined by SL::DB::Chart get_balance, which checks for user rights)
195 =item * the invoice date of the last transaction (may lie in the future)
199 The partpicker also has two views, but whereas the compact block view of the
200 partpicker allows part boxes to be aligned in two columns, the chartpicker
201 block view still only shows one chart per row, because there is more
202 information and the account names can be quite long. This behaviour is
203 determined by css, however, and could be changed (div.cpc_block). The downside
204 of this is that you have to scroll the window to reach the pagination controls.
206 The default view of the display logic is to use block view, so we don't have to
207 pass any parameters in the pagination GET. However, the default view for the
208 user is the list view, so the popup window is opened with the "Hide additional
209 information" select box already ticked.
211 =head1 CHART PICKER SPECIFICATION
213 The following list of design goals were applied:
219 Charts should not be perceived by the user as distinct inputs of chart number and
220 description but as a single object
224 Easy to use without documentation for novice users
228 Fast to use with keyboard for experienced users
232 Possible to use without any keyboard interaction for mouse (or touchscreen)
237 Must not leave the current page in event of ambiguity (cf. current select_item
242 Should not require a feedback/check loop in the common case
246 Should not be constrained to exact matches
250 The implementation consists of the following parts which will be referenced later:
256 A hidden input (id input), used to hold the id of the selected part. The only
257 input that gets submitted
261 An input (dummy input) containing a description of the currently selected chart,
262 also used by the user to search for charts
266 A jquery.autocomplete mechanism attached to the dummy field
270 A popup layer for both feedback and input of additional data in case of
275 An internal status of the chart picker, indicating whether id input and dummy
276 input are consistent. After leaving the dummy input the chart picker must
277 place itself in a consistent status.
281 A clickable icon (popup trigger) attached to the dummy input, which triggers the popup layer.
291 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
293 G. Richardson E<lt>information@kivitendo-premium.deE<gt>