Revision d11ed75b
Von Cem Aydin vor etwa 2 Jahren hinzugefügt
SL/Presenter/ALL.pm | ||
---|---|---|
|
||
use SL::Presenter::Chart;
|
||
use SL::Presenter::CustomerVendor;
|
||
use SL::Presenter::DatePeriod;
|
||
use SL::Presenter::DeliveryOrder;
|
||
use SL::Presenter::Dunning;
|
||
use SL::Presenter::EscapedText;
|
||
... | ... | |
our %presenters = (
|
||
chart => 'SL::Presenter::Chart',
|
||
customer_vendor => 'SL::Presenter::CustomerVendor',
|
||
date_period => 'SL::Presenter::DatePeriod',
|
||
delivery_order => 'SL::Presenter::DeliveryOrder',
|
||
dunning => 'SL::Presenter::Dunning',
|
||
escaped_text => 'SL::Presenter::EscapedText',
|
SL/Presenter/DatePeriod.pm | ||
---|---|---|
package SL::Presenter::DatePeriod;
|
||
|
||
use strict;
|
||
|
||
use Exporter qw(import);
|
||
our @EXPORT_OK = qw(
|
||
date_period_picker
|
||
get_dialog_defaults_from_report_generator
|
||
populate_hidden_variables
|
||
);
|
||
|
||
use SL::Presenter::Tag qw(name_to_id);
|
||
|
||
sub date_period_picker {
|
||
my ($name, $value_from, $value_to, %params) = @_;
|
||
|
||
my $id = name_to_id($name);
|
||
my @classes = $params{class} ? ($params{class}) : ();
|
||
push @classes, 'date_period_picker';
|
||
|
||
my $dialog_defaults = {
|
||
year => $params{dialog_defaults}->{year} // DateTime->today->year,
|
||
type => $params{dialog_defaults}->{type} // 'yearly',
|
||
quarter => $params{dialog_defaults}->{quarter} // 'A',
|
||
month => $params{dialog_defaults}->{month} // '1',
|
||
};
|
||
|
||
my $html = SL::Presenter->get->render(
|
||
'presenter/date_period/date_period_picker',
|
||
id => $id,
|
||
classes => \@classes,
|
||
defaults => {
|
||
report_period_from_date => $value_from || '',
|
||
report_period_to_date => $value_to || '',
|
||
dialog => $dialog_defaults
|
||
},
|
||
years_list => get_years(),
|
||
months_list => get_months(),
|
||
);
|
||
$::request->layout->add_javascripts('kivi.Presenter.DatePeriodPicker.js');
|
||
|
||
return $html;
|
||
}
|
||
|
||
### convenience functions
|
||
|
||
sub get_dialog_defaults_from_report_generator {
|
||
my ($name) = @_;
|
||
|
||
my $id = name_to_id($name);
|
||
|
||
my %fallback_dateperiod_dialog = (
|
||
year => DateTime->today->year,
|
||
type => 'yearly',
|
||
quarter => 'A',
|
||
month => '1',
|
||
);
|
||
my %defaults_dialog;
|
||
for (keys %fallback_dateperiod_dialog) {
|
||
$defaults_dialog{$_} = $::form->{'report_generator_hidden_' . $id . '_selected_preset_' . $_} //
|
||
$fallback_dateperiod_dialog{$_};
|
||
}
|
||
return \%defaults_dialog;
|
||
}
|
||
|
||
sub populate_hidden_variables {
|
||
my ($name, $hidden_variables_ref) = @_;
|
||
|
||
my $id = name_to_id($name);
|
||
|
||
my @vars = qw(
|
||
_from_date
|
||
_to_date
|
||
_selected_preset_year
|
||
_selected_preset_type
|
||
_selected_preset_quarter
|
||
_selected_preset_month
|
||
);
|
||
|
||
push @{ $hidden_variables_ref }, map { $id . $_ } @vars;
|
||
}
|
||
|
||
### helper
|
||
|
||
sub get_months {
|
||
my $dt = DateTime->now;
|
||
my $months = $dt->{locale}->{locale_data}->{month_format_wide};
|
||
my $i = 0;
|
||
[ map { $i++; [ $i, $::locale->text($_) ] } @{ $months } ];
|
||
}
|
||
|
||
sub get_years {
|
||
my $current = DateTime->today->year;
|
||
[ map { [ $current - $_, $current - $_, ] } (0..39) ];
|
||
}
|
||
|
||
sub picker { goto &date_period_picker }
|
||
|
||
1;
|
||
|
||
__END__
|
||
|
||
=encoding utf-8
|
||
|
||
=head1 NAME
|
||
|
||
SL::Presenter::DatePeriod - Date period stuff
|
||
|
||
=head1 SYNOPSIS
|
||
|
||
# use in perl code
|
||
use SL::Presenter::DatePeriod qw(date_period_picker);
|
||
my $html = date_period_picker('my-picker-id', '', '');
|
||
my $html = date_period_picker('my-other-picker-id', $from_date, $to_date);
|
||
|
||
# use in template
|
||
[% P.date_period.picker('my-picker-id', '', '') %]
|
||
[% P.date_period.picker('my-other-picker-id',
|
||
defaults.from_date,
|
||
defaults.to_date,
|
||
dialog_defaults => defaults.dialog) %]
|
||
|
||
see also L<SL::Presenter>
|
||
|
||
=head1 DATE PERIOD PICKER UI DESCRIPTION
|
||
|
||
Two date input fields are shown: 'From' and 'To', to select a date period.
|
||
|
||
Additionally a button is shown: 'Select from preset'.
|
||
|
||
When clicked it shows a dialog that allows the selection of a date period
|
||
from sensible presets.
|
||
|
||
=over 2
|
||
|
||
=item Dialog:
|
||
|
||
The dialog shows a select 'Year', containing the current year plus years up
|
||
to forty years back.
|
||
|
||
A period is selected with a radio button, that is either 'yearly' (default),
|
||
'quarterly' or 'monthly'.
|
||
|
||
For quarterly and monthly there is a select shown containing the respective
|
||
values.
|
||
|
||
=back
|
||
|
||
=head1 FUNCTIONS
|
||
|
||
=over 2
|
||
|
||
=item C<date_period_picker $name, $value_from, $value_to, %params>
|
||
|
||
Renders a date period picker with preset dialog.
|
||
|
||
C<$name> should be a unique name. It is converted to an id for the main
|
||
element. This id is also used as a prefix for all sub-elements that need an id.
|
||
|
||
B<Important:> The selected dates are available from the form elements
|
||
|
||
C<id _ '_from_date'> and C<id _ '_to_date'>.
|
||
|
||
In above example this would be C<'my-picker-id_from_date'> and
|
||
C<'my-picker-id_to_date'>.
|
||
|
||
C<$value_from> and C<$value_to> are used as preset values for the respective
|
||
date fields. This may be useful to keep entered value between page switches.
|
||
|
||
C<$params> Classes in C<class> are forwarded to the main element.
|
||
|
||
If you want to keep the selection over multiple requests this has to be handled
|
||
in the controller.
|
||
|
||
C<$params> can therefor contain a hash called C<dialog_defaults> with the
|
||
key/values:
|
||
|
||
year => DateTime->today->year, # numeric year
|
||
type => 'yearly', # the radio button selection:
|
||
# 'yearly', 'monthly', 'quarterly'
|
||
quarter => 'A', # the quarter as a letter code:
|
||
# 'A', 'B', 'C', 'D' A being 1st quarter etc.
|
||
month => '1', # numeric month
|
||
|
||
The values will be used to pre-select the dialog fields.
|
||
|
||
These values are also set into some hidden fields with the id in the format
|
||
e.g.: C<id _ '_selected_preset_year'>.
|
||
|
||
Convenience functions to handle report generator hidden variables are provided.
|
||
E.g.:
|
||
|
||
use SL::Presenter::DatePeriod qw(get_dialog_defaults_from_report_generator
|
||
populate_hidden_variables);
|
||
|
||
# use values from form, then report generator form, then fallback
|
||
my %fallback = (
|
||
dateperiod_from_date => '',
|
||
dateperiod_to_date => '',
|
||
# other fields e.g.:
|
||
# chart_id => '',
|
||
);
|
||
my %defaults;
|
||
for (keys %fallback) {
|
||
$defaults{$_} = $::form->{$_} // $::form->{'report_generator_hidden_' . $_} // $fallback{$_};
|
||
}
|
||
|
||
# set dialog defaults
|
||
$defaults{dialog} = get_dialog_defaults_from_report_generator('dateperiod');
|
||
|
||
# set hidden fields for the report generator
|
||
my @hidden_variables = qw(chart_id); # e.g.
|
||
populate_hidden_variables('dateperiod', \@hidden_variables);
|
||
|
||
|
||
=item C<get_dialog_defaults_from_report_generator $name>
|
||
|
||
Convenience function to get the dialog defaults from hidden report generator
|
||
fields. (Use in controller.)
|
||
|
||
C<$name> name of the date picker.
|
||
|
||
=item C<populate_hidden_variables $name $hidden_variables_ref>
|
||
|
||
Convenience function Add hidden variables to report a generator.
|
||
(Use in controller.)
|
||
|
||
C<$name> name of the date picker.
|
||
|
||
C<$hidden_variables_ref> reference to the hidden variable array.
|
||
|
||
=back
|
||
|
||
=head1 USE / MOTIVATION / GOAL
|
||
|
||
Use date_period_picker when you want to select a date period with preset
|
||
dialog.
|
||
|
||
Planned use: ListTransactions report settings view (new, replacement for
|
||
ca/list).
|
||
|
||
Possible uses in report settings views for:
|
||
|
||
- rp/erfolgsrechnung (swiss)
|
||
- rp/trial_balance
|
||
- Inventory/stock_usage
|
||
|
||
And possibly more.
|
||
|
||
Current implementations for report periods repeat a lot of template and
|
||
perl code in different places. Hopefully this can be reduced.
|
||
|
||
While this UI may require slightly more clicks than previous / current
|
||
implementations, the interface is much more concise. It is easier on the eyes
|
||
and fits better into the new design 4.0.
|
||
|
||
=head1 LIMITATIONS
|
||
|
||
If multiple date_period_picker elements were to be used on the same page the
|
||
handling of hidden variables becomes ugly.
|
||
|
||
my @hidden_variables = qw(
|
||
dateperiod_from_date
|
||
dateperiod_to_date
|
||
dateperiod_selected_preset_year
|
||
dateperiod_selected_preset_type
|
||
# ... etc.
|
||
);
|
||
|
||
Convenience functions are provided to help handle this. Currently i don't see
|
||
another way of handling this.
|
||
|
||
=head1 BUGS
|
||
|
||
None atm :)
|
||
|
||
=head1 AUTHOR
|
||
|
||
Cem Aydin E<lt>cem.aydin@revamp-it.chE<gt>
|
||
|
||
=cut
|
js/kivi.Presenter.DatePeriodPicker.js | ||
---|---|---|
namespace('kivi.ReportPeriod', function(ns) {
|
||
|
||
ns.open_dialog = function(el) {
|
||
|
||
ns.current_id = el.parentNode.id;
|
||
|
||
ns.current_dialog = $(`#${ ns.current_id }_preset_dialog`).dialog({
|
||
title: kivi.t8('Select from preset'),
|
||
width: 340,
|
||
height: 330,
|
||
modal: true,
|
||
});
|
||
}
|
||
|
||
ns.apply_preset = function() {
|
||
|
||
const year = $(`#${ ns.current_id }_preset_dialog_year`).val();
|
||
const type = $(`input[name="${ ns.current_id }_preset_dialog_type"]:checked`).val();
|
||
const quarter = $(`#${ ns.current_id }_preset_dialog_quarter`).val();
|
||
const month = $(`#${ ns.current_id }_preset_dialog_month`).val();
|
||
|
||
let duetyp = 13; // (yearly)
|
||
if (type === 'quarterly') {
|
||
duetyp = quarter;
|
||
} else if (type === 'monthly') {
|
||
duetyp = month;
|
||
}
|
||
ns.set_from_to(duetyp, year);
|
||
|
||
$(`#${ ns.current_id }_selected_preset_year`).val(year);
|
||
$(`#${ ns.current_id }_selected_preset_type`).val(type);
|
||
$(`#${ ns.current_id }_selected_preset_quarter`).val(quarter);
|
||
$(`#${ ns.current_id }_selected_preset_month`).val(month);
|
||
|
||
ns.current_dialog.dialog('close');
|
||
$(`#${ ns.current_id }_preset_dialog_button`)
|
||
}
|
||
|
||
ns.set_from_to = function (duetyp, year) {
|
||
const date = {
|
||
1: [ 1, 1, 1, 31 ],
|
||
2: [ 2, 1, 2, new Date(year, 1, 29).getMonth() == 1 ? 29 : 28 ],
|
||
3: [ 3, 1, 3, 31 ],
|
||
4: [ 4, 1, 4, 30 ],
|
||
5: [ 5, 1, 5, 31 ],
|
||
6: [ 6, 1, 6, 30 ],
|
||
7: [ 7, 1, 7, 31 ],
|
||
8: [ 8, 1, 8, 31 ],
|
||
9: [ 9, 1, 9, 30 ],
|
||
10: [ 10, 1, 10, 31 ],
|
||
11: [ 11, 1, 11, 30 ],
|
||
12: [ 12, 1, 12, 31 ],
|
||
13: [ 1, 1, 12, 31 ],
|
||
'A': [ 1, 1, 3, 31 ],
|
||
'B': [ 4, 1, 6, 30 ],
|
||
'C': [ 7, 1, 9, 30 ],
|
||
'D': [ 10, 1, 12, 31 ]
|
||
}[duetyp];
|
||
|
||
$(`#${ ns.current_id }_from_date`).val(kivi.format_date(new Date(year, date[0]-1, date[1])));
|
||
$(`#${ ns.current_id }_to_date`).val(kivi.format_date(new Date(year, date[2]-1, date[3])));
|
||
}
|
||
});
|
js/locale/de.js | ||
---|---|---|
"Save":"Speichern",
|
||
"Save and keep open":"Speichern und geöffnet lassen",
|
||
"Section/Function block actions":"Abschnitts-/Funktionsblockaktionen",
|
||
"Select from preset":"Aus Voreinstellung wählen",
|
||
"Select template to paste":"Einzufügende Vorlage auswählen",
|
||
"Send email":"E-Mail verschicken",
|
||
"Sep":"Sep",
|
js/locale/en.js | ||
---|---|---|
"Save":"",
|
||
"Save and keep open":"",
|
||
"Section/Function block actions":"",
|
||
"Select from preset":"",
|
||
"Select template to paste":"",
|
||
"Send email":"",
|
||
"Sep":"",
|
locale/de/all | ||
---|---|---|
'Select federal state...' => 'Bundesland auswählen...',
|
||
'Select file to upload' => 'Datei zum Hochladen auswählen',
|
||
'Select from one of the items below' => 'Wählen Sie einen der untenstehenden Einträge',
|
||
'Select from preset' => 'Aus Voreinstellung wählen',
|
||
'Select postscript or PDF!' => 'Postscript oder PDF auswählen!',
|
||
'Select tax office...' => 'Finanzamt auswählen...',
|
||
'Select template to paste' => 'Einzufügende Vorlage auswählen',
|
locale/en/all | ||
---|---|---|
'Select federal state...' => '',
|
||
'Select file to upload' => '',
|
||
'Select from one of the items below' => '',
|
||
'Select from preset' => '',
|
||
'Select postscript or PDF!' => '',
|
||
'Select tax office...' => '',
|
||
'Select template to paste' => '',
|
templates/design40_webpages/presenter/date_period/date_period_picker.html | ||
---|---|---|
[% USE HTML %]
|
||
[% USE LxERP %]
|
||
[% USE L %]
|
||
[% USE P %]
|
||
[% USE T8 %]
|
||
|
||
<div id="[% id %]" class="[% classes.join(' ') %]">
|
||
[% 'From' | $T8 %] [% L.date_tag(id _ '_from_date',
|
||
defaults.report_period_from_date) %]
|
||
|
||
[% 'To' | $T8 %] [% L.date_tag(id _ '_to_date',
|
||
defaults.report_period_to_date) %]
|
||
|
||
[% P.button_tag('kivi.ReportPeriod.open_dialog(event.target)',
|
||
LxERP.t8('Select from preset'),
|
||
id => id _ '_preset_dialog_button',
|
||
class => 'neutral') %]
|
||
|
||
<div id="[% id _ '_preset_dialog' %]" style="display: none;">
|
||
<h3>[% 'Year' | $T8 %]</h3>
|
||
<p>[% L.select_tag(id _ '_preset_dialog_year', years_list, default = defaults.dialog.year) %]</p>
|
||
<h3>[% 'Period' | $T8 %]</h3>
|
||
<table class="tbl-horizontal">
|
||
<colgroup>
|
||
<col class="wi-mediumsmall">
|
||
<col class="wi-mediumsmall">
|
||
</colgroup>
|
||
<tbody>
|
||
<tr>
|
||
<th>[% L.radio_button_tag(id _ '_preset_dialog_type',
|
||
value => 'yearly',
|
||
checked => defaults.dialog.type == 'yearly' ? 1 : 0,
|
||
label => LxERP.t8('Yearly')) %]</th>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<th>[% L.radio_button_tag(id _ '_preset_dialog_type',
|
||
value => 'quarterly',
|
||
checked => defaults.dialog.type == 'quarterly' ? 1 : 0,
|
||
label => LxERP.t8('Quarterly')) %]</th>
|
||
<td>[% L.select_tag(id _ '_preset_dialog_quarter',
|
||
[
|
||
[ 'A', LxERP.t8('1. Quarter') ],
|
||
[ 'B', LxERP.t8('2. Quarter') ],
|
||
[ 'C', LxERP.t8('3. Quarter') ],
|
||
[ 'D', LxERP.t8('4. Quarter') ],
|
||
], default => defaults.dialog.quarter) %]</td>
|
||
</tr>
|
||
<tr>
|
||
<th>[% L.radio_button_tag(id _ '_preset_dialog_type',
|
||
value => 'monthly',
|
||
checked => defaults.dialog.type == 'monthly' ? 1 : 0,
|
||
label => LxERP.t8('Monthly')) %]</th>
|
||
<td>[% L.select_tag(id _ '_preset_dialog_month', months_list,
|
||
default => defaults.dialog.month) %]</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>[% P.button_tag('kivi.ReportPeriod.apply_preset()',
|
||
LxERP.t8('Apply')) %]</p>
|
||
</div>
|
||
[% L.hidden_tag(id _ '_selected_preset_year', defaults.dialog.year) %]
|
||
[% L.hidden_tag(id _ '_selected_preset_type', defaults.dialog.type) %]
|
||
[% L.hidden_tag(id _ '_selected_preset_quarter', defaults.dialog.quarter) %]
|
||
[% L.hidden_tag(id _ '_selected_preset_month', defaults.dialog.month) %]
|
||
</div>
|
templates/webpages/presenter/date_period/date_period_picker.html | ||
---|---|---|
[% USE HTML %]
|
||
[% USE LxERP %]
|
||
[% USE L %]
|
||
[% USE P %]
|
||
[% USE T8 %]
|
||
|
||
<div id="[% id %]" class="[% classes.join(' ') %]">
|
||
[% 'From' | $T8 %] [% L.date_tag(id _ '_from_date',
|
||
defaults.report_period_from_date) %]
|
||
|
||
[% 'To' | $T8 %] [% L.date_tag(id _ '_to_date',
|
||
defaults.report_period_to_date) %]
|
||
|
||
[% P.button_tag('kivi.ReportPeriod.open_dialog(event.target)',
|
||
LxERP.t8('Select from preset'),
|
||
id => id _ '_preset_dialog_button',
|
||
class => 'neutral') %]
|
||
|
||
<div id="[% id _ '_preset_dialog' %]" style="display: none;">
|
||
<h4>[% 'Year' | $T8 %]</h4>
|
||
<p>[% L.select_tag(id _ '_preset_dialog_year', years_list, default = defaults.dialog.year) %]</p>
|
||
<h4>[% 'Period' | $T8 %]</h4>
|
||
<table class="tbl-horizontal">
|
||
<tbody>
|
||
<tr>
|
||
<th align="left">[% L.radio_button_tag(id _ '_preset_dialog_type',
|
||
value => 'yearly',
|
||
checked => defaults.dialog.type == 'yearly' ? 1 : 0,
|
||
label => LxERP.t8('Yearly')) %]</th>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<th align="left">[% L.radio_button_tag(id _ '_preset_dialog_type',
|
||
value => 'quarterly',
|
||
checked => defaults.dialog.type == 'quarterly' ? 1 : 0,
|
||
label => LxERP.t8('Quarterly')) %]</th>
|
||
<td>[% L.select_tag(id _ '_preset_dialog_quarter',
|
||
[
|
||
[ 'A', LxERP.t8('1. Quarter') ],
|
||
[ 'B', LxERP.t8('2. Quarter') ],
|
||
[ 'C', LxERP.t8('3. Quarter') ],
|
||
[ 'D', LxERP.t8('4. Quarter') ],
|
||
], default => defaults.dialog.quarter) %]</td>
|
||
</tr>
|
||
<tr>
|
||
<th align="left">[% L.radio_button_tag(id _ '_preset_dialog_type',
|
||
value => 'monthly',
|
||
checked => defaults.dialog.type == 'monthly' ? 1 : 0,
|
||
label => LxERP.t8('Monthly')) %]</th>
|
||
<td>[% L.select_tag(id _ '_preset_dialog_month', months_list,
|
||
default => defaults.dialog.month) %]</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>[% P.button_tag('kivi.ReportPeriod.apply_preset()',
|
||
LxERP.t8('Apply')) %]</p>
|
||
</div>
|
||
[% L.hidden_tag(id _ '_selected_preset_year', defaults.dialog.year) %]
|
||
[% L.hidden_tag(id _ '_selected_preset_type', defaults.dialog.type) %]
|
||
[% L.hidden_tag(id _ '_selected_preset_quarter', defaults.dialog.quarter) %]
|
||
[% L.hidden_tag(id _ '_selected_preset_month', defaults.dialog.month) %]
|
||
</div>
|
Auch abrufbar als: Unified diff
Neuer Presenter: SL::Presenter::DatePeriod
Liefert Element P.date_period.picker zum Auswählen eines Zeitraums
mit optionaler Vorauswahl
Enthält zwei Datumsfelder plus ein Button/PopUp-Dialog mit
Vorgewählten Zeiträumen.
Geplante Verwendung in neuer Ansicht Buchungsliste (ersetzt
ca/list).
Mögliche weitere Verwendungen u.a.:
Siehe auch perldoc SL/Presenter/DatePeriod.pm