1 package SL::Presenter::Chart;
7 use Exporter qw(import);
8 our @EXPORT_OK = qw(chart_picker chart);
12 use SL::Presenter::EscapedText qw(escape is_escaped);
13 use SL::Presenter::Tag qw(input_tag name_to_id html_tag);
16 my ($chart, %params) = @_;
18 $params{display} ||= 'inline';
20 croak "Unknown display type '$params{display}'" unless $params{display} =~ m/^(?:inline|table-cell)$/;
23 $params{no_link} ? '' : '<a href="am.pl?action=edit_account&id=' . escape($chart->id) . '">',
24 escape($chart->accno),
25 $params{no_link} ? '' : '</a>',
31 my ($name, $value, %params) = @_;
33 $value = SL::DB::Manager::Chart->find_by(id => $value) if $value && !ref $value;
34 my $id = delete($params{id}) || name_to_id($name);
35 my $fat_set_item = delete $params{fat_set_item};
37 my @classes = $params{class} ? ($params{class}) : ();
38 push @classes, 'chart_autocomplete';
39 push @classes, 'chartpicker_fat_set_item' if $fat_set_item;
42 input_tag($name, (ref $value && $value->can('id') ? $value->id : ''), class => "@classes", type => 'hidden', id => $id) .
43 join('', map { $params{$_} ? input_tag("", delete $params{$_}, id => "${id}_${_}", type => 'hidden') : '' } qw(type category choose booked)) .
44 input_tag("", (ref $value && $value->can('displayable_name')) ? $value->displayable_name : '', id => "${id}_name", %params);
46 $::request->layout->add_javascripts('autocomplete_chart.js');
47 $::request->presenter->need_reinit_widgets($id);
49 html_tag('span', $ret, class => 'chart_picker');
52 sub picker { goto &chart_picker }
62 SL::Presenter::Chart - Chart related presenter stuff
66 # Create an html link for editing/opening a chart
67 my $object = SL::DB::Manager::Chart->get_first;
68 my $html = SL::Presenter::Chart::chart($object, display => 'inline');
70 see also L<SL::Presenter>
80 =item C<chart, $object, %params>
82 Returns a rendered version (actually an instance of
83 L<SL::Presenter::EscapedText>) of the chart object C<$object>
85 C<%params> can include:
91 Either C<inline> (the default) or C<table-cell>. At the moment both
92 representations are identical and produce the chart's name linked
93 to the corresponding 'edit' action.
101 =item C<chart_picker $name, $value, %params>
103 All-in-one picker widget for charts. The code was originally copied and adapted
104 from the part picker. The name will be both id and name of the resulting hidden
105 C<id> input field (but the ID can be overwritten with C<$params{id}>).
107 An additional dummy input will be generated which is used to find
108 chart. For a detailed description of its behaviour, see section
109 C<CHART PICKER SPECIFICATION>.
111 For some examples of usage see the test page at controller.pl?action=Chart/test_page
113 C<$value> can be a chart id or a C<Rose::DB:Object> instance.
115 C<%params> can include:
121 If C<%params> contains C<category> only charts of this category will be
122 available for selection (in the autocompletion and in the popup).
124 You may comma separate multiple categories, e.g C<A,Q,L>.
126 In SL::DB::Manager::Chart there is also a filter called C<selected_category>,
127 which filters the possible charts according to the category checkboxes the user
128 selects in the popup window. This filter may further restrict the results of
129 the filter category, but the user is not able to "break out of" the limits
130 defined by C<category>. In fact if the categories are restricted by C<category>
131 the popup template should only show checkboxes for those categories.
135 If C<%params> contains C<type> only charts of this type will be used for
136 autocompletion, i.e. the selection is filtered. You may comma separate multiple
139 Type is usually a filter for link: C<AR,AR_paid>
141 Type can also be a specially defined type: C<guv>, C<balance>, C<bank>
143 See the type filter in SL::DB::Manager::Chart.
147 If C<%params> is passed with choose=1 the input of the filter field in the
148 popup window is cleared. This is useful if a chart was already selected and we
149 want to choose a new chart and immediately see all options.
153 If C<%params> is passed with fat_set_item=1 the contents of the selected chart
154 object (the elements of the database chart table) are passed back via JSON into
155 the item object. There is an example on the test page.
157 Without fat_set_item only the variables id and name (displayable name) are
162 C<chart_picker> will register its javascript for inclusion in the next header
163 rendering. If you write a standard controller that only calls C<render> once, it
164 will just work. In case the header is generated in a different render call
165 (multiple blocks, ajax, old C<bin/mozilla> style controllers) you need to
166 include C<js/autocomplete_chart.js> yourself.
172 For users that don't regularly do bookkeeping and haven't memorised all the
173 account numbers and names there are some filter options inside the popup window
174 to quickly narrow down the possible matches. You can filter by
178 =item * chart accno or description, inside the input field
180 =item * accounts that have already been booked
182 =item * by category (AIELQC)
184 By selecting category checkboxes the list of available charts can be
185 restricted. If all checkboxes are unchecked all possible charts are shown.
189 There are two views in the list of accounts. By default all possible accounts are shown as a long list.
191 But you can also show more information, in this case the resulting list is automatically paginated:
195 =item * the balance of the account (as determined by SL::DB::Chart get_balance, which checks for user rights)
199 =item * the invoice date of the last transaction (may lie in the future)
203 The partpicker also has two views, but whereas the compact block view of the
204 partpicker allows part boxes to be aligned in two columns, the chartpicker
205 block view still only shows one chart per row, because there is more
206 information and the account names can be quite long. This behaviour is
207 determined by css, however, and could be changed (div.cpc_block). The downside
208 of this is that you have to scroll the window to reach the pagination controls.
210 The default view of the display logic is to use block view, so we don't have to
211 pass any parameters in the pagination GET. However, the default view for the
212 user is the list view, so the popup window is opened with the "Hide additional
213 information" select box already ticked.
215 =head1 CHART PICKER SPECIFICATION
217 The following list of design goals were applied:
223 Charts should not be perceived by the user as distinct inputs of chart number and
224 description but as a single object
228 Easy to use without documentation for novice users
232 Fast to use with keyboard for experienced users
236 Possible to use without any keyboard interaction for mouse (or touchscreen)
241 Must not leave the current page in event of ambiguity (cf. current select_item
246 Should not require a feedback/check loop in the common case
250 Should not be constrained to exact matches
254 The implementation consists of the following parts which will be referenced later:
260 A hidden input (id input), used to hold the id of the selected part. The only
261 input that gets submitted
265 An input (dummy input) containing a description of the currently selected chart,
266 also used by the user to search for charts
270 A jquery.autocomplete mechanism attached to the dummy field
274 A popup layer for both feedback and input of additional data in case of
279 An internal status of the chart picker, indicating whether id input and dummy
280 input are consistent. After leaving the dummy input the chart picker must
281 place itself in a consistent status.
285 A clickable icon (popup trigger) attached to the dummy input, which triggers the popup layer.
295 Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
297 G. Richardson E<lt>information@kivitendo-premium.deE<gt>