Revision e6af833d
Von Tamino Steinert vor 12 Tagen hinzugefügt
- ID e6af833dc4ff65761a67a176c6ebfc04132bdaa6
- Vorgänger efc07572
SL/Controller/EmailJournal.pm | ||
---|---|---|
4 | 4 |
|
5 | 5 |
use parent qw(SL::Controller::Base); |
6 | 6 |
|
7 |
use SL::ReportGenerator; |
|
8 |
use SL::Controller::Helper::ReportGenerator; |
|
7 | 9 |
use SL::ZUGFeRD; |
8 | 10 |
use SL::Controller::ZUGFeRD; |
9 | 11 |
use SL::Controller::Helper::GetModels; |
... | ... | |
11 | 13 |
use SL::DB::EmailJournal; |
12 | 14 |
use SL::DB::EmailJournalAttachment; |
13 | 15 |
use SL::Presenter::EmailJournal; |
16 |
use SL::Presenter::Filter::EmailJournal; |
|
14 | 17 |
use SL::Presenter::Record qw(grouped_record_list); |
15 | 18 |
use SL::Presenter::Tag qw(html_tag div_tag button_tag); |
16 | 19 |
use SL::Helper::Flash; |
... | ... | |
222 | 225 |
my ($self) = @_; |
223 | 226 |
|
224 | 227 |
$::auth->assert('email_journal'); |
225 |
# default filter |
|
226 |
$::form->{filter} ||= {"obsolete:eq_ignore_empty" => 0}; |
|
227 | 228 |
|
228 | 229 |
if ( $::instance_conf->get_email_journal == 0 ) { |
229 |
flash('info', $::locale->text('Storing the emails in the journal is currently disabled in the client configuration.'));
|
|
230 |
flash('info', t8('Storing the emails in the journal is currently disabled in the client configuration.'));
|
|
230 | 231 |
} |
232 |
|
|
233 |
$::form->{filter} ||= { |
|
234 |
'obsolete:eq_ignore_empty' => 0, |
|
235 |
}; |
|
236 |
|
|
231 | 237 |
$self->setup_list_action_bar; |
232 |
my @record_types_with_info = $self->get_record_types_with_info(); |
|
233 |
my %record_types_to_text = $self->get_record_types_to_text(); |
|
234 |
$self->render('email_journal/list', |
|
235 |
title => $::locale->text('Email journal'), |
|
236 |
ENTRIES => $self->models->get, |
|
237 |
MODELS => $self->models, |
|
238 |
RECORD_TYPES_WITH_INFO => \@record_types_with_info, |
|
239 |
RECORD_TYPES_TO_TEXT => \%record_types_to_text, |
|
240 |
); |
|
238 |
my $report = $self->prepare_report; |
|
239 |
$self->report_generator_list_objects( |
|
240 |
report => $report, |
|
241 |
objects => $self->models->get, |
|
242 |
); |
|
241 | 243 |
} |
242 | 244 |
|
243 | 245 |
sub action_show { |
... | ... | |
778 | 780 |
return $customer_vendor; |
779 | 781 |
} |
780 | 782 |
|
783 |
sub prepare_report { |
|
784 |
my ($self) = @_; |
|
785 |
|
|
786 |
my %record_types_to_text = $self->get_record_types_to_text(); |
|
787 |
my @record_types_with_info = $self->get_record_types_with_info(); |
|
788 |
|
|
789 |
my $report = SL::ReportGenerator->new(\%::myconfig, $::form); |
|
790 |
|
|
791 |
my $callback = $self->models->get_callback; |
|
792 |
|
|
793 |
my @columns_order = qw( |
|
794 |
id |
|
795 |
sender |
|
796 |
from |
|
797 |
recipients |
|
798 |
subject |
|
799 |
sent_on |
|
800 |
attachment_names |
|
801 |
has_unprocessed_attachments |
|
802 |
unprocessed_attachment_names |
|
803 |
status |
|
804 |
extended_status |
|
805 |
record_type |
|
806 |
linked_to |
|
807 |
obsolete |
|
808 |
); |
|
809 |
|
|
810 |
my @default_columns = qw( |
|
811 |
from |
|
812 |
recipients |
|
813 |
subject |
|
814 |
sent_on |
|
815 |
); |
|
816 |
|
|
817 |
my %column_defs = ( |
|
818 |
id => { |
|
819 |
obj_link => sub {$self->url_for( |
|
820 |
action => 'show', id => $_[0]->id, callback => $callback |
|
821 |
)}, |
|
822 |
sub => sub { $_[0]->id }, |
|
823 |
}, |
|
824 |
sender => { |
|
825 |
sub => sub { $_[0]->sender ? $_[0]->sender->name : '' }, |
|
826 |
}, |
|
827 |
from => { |
|
828 |
obj_link => sub {$self->url_for( |
|
829 |
action => 'show', id => $_[0]->id, callback => $callback |
|
830 |
)}, |
|
831 |
sub => sub { $_[0]->from }, |
|
832 |
}, |
|
833 |
recipients => { |
|
834 |
obj_link => sub {$self->url_for( |
|
835 |
action => 'show', id => $_[0]->id, callback => $callback |
|
836 |
)}, |
|
837 |
sub => sub { $_[0]->recipients }, |
|
838 |
}, |
|
839 |
subject => { |
|
840 |
obj_link => sub {$self->url_for( |
|
841 |
action => 'show', id => $_[0]->id, callback => $callback |
|
842 |
)}, |
|
843 |
sub => sub { $_[0]->subject }, |
|
844 |
}, |
|
845 |
sent_on => { |
|
846 |
obj_link => sub {$self->url_for( |
|
847 |
action => 'show', id => $_[0]->id, callback => $callback |
|
848 |
)}, |
|
849 |
sub => sub { $_[0]->sent_on->to_kivitendo(precision => 'minute') }, |
|
850 |
}, |
|
851 |
attachment_names => { |
|
852 |
sub => sub {join(', ', |
|
853 |
map {$_->name} |
|
854 |
sort {$a->position <=> $b->position} |
|
855 |
@{$_[0]->attachments} |
|
856 |
)}, |
|
857 |
}, |
|
858 |
has_unprocessed_attachments => { |
|
859 |
sub => sub { $_[0]->has_unprocessed_attachments } |
|
860 |
}, |
|
861 |
unprocessed_attachment_names => { |
|
862 |
sub => sub {join(', ', |
|
863 |
map {$_->name} |
|
864 |
sort {$a->position <=> $b->position} |
|
865 |
grep {$_->processed == 0} |
|
866 |
@{$_[0]->attachments} |
|
867 |
)}, |
|
868 |
}, |
|
869 |
status => { |
|
870 |
sub => sub { SL::Presenter::EmailJournal::entry_status($_[0]) }, |
|
871 |
}, |
|
872 |
extended_status => { |
|
873 |
sub => sub { $_[0]->extended_status }, |
|
874 |
}, |
|
875 |
record_type => { |
|
876 |
sub => sub { $record_types_to_text{$_[0]->record_type} }, |
|
877 |
}, |
|
878 |
linked_to => { |
|
879 |
raw_data => sub { |
|
880 |
SL::Presenter::Record::simple_grouped_record_list($_[0]->linked_records) |
|
881 |
} |
|
882 |
}, |
|
883 |
obsolete => { |
|
884 |
sub => sub { $_[0]->obsolete_as_bool_yn } |
|
885 |
}, |
|
886 |
); |
|
887 |
$column_defs{$_}->{text} ||= |
|
888 |
t8( $self->models->get_sort_spec->{$_}->{title} || $_ ) |
|
889 |
for keys %column_defs; |
|
890 |
|
|
891 |
# make all sortable |
|
892 |
my @sortable = keys %column_defs; |
|
893 |
|
|
894 |
unless ($::form->{active_in_report}) { |
|
895 |
$::form->{active_in_report}->{$_} = 1 foreach @default_columns; |
|
896 |
} |
|
897 |
|
|
898 |
$column_defs{$_}->{visible} = $::form->{active_in_report}->{"$_"} || 0 |
|
899 |
foreach keys %column_defs; |
|
900 |
|
|
901 |
my $filter_html = SL::Presenter::Filter::EmailJournal::filter( |
|
902 |
$::form->{filter}, |
|
903 |
active_in_report => $::form->{active_in_report}, |
|
904 |
record_types_with_info => \@record_types_with_info, |
|
905 |
); |
|
906 |
|
|
907 |
$self->models->disable_plugin('paginated') |
|
908 |
if $report->{options}{output_format} =~ /^(pdf|csv)$/i; |
|
909 |
$self->models->add_additional_url_params( |
|
910 |
active_in_report => $::form->{active_in_report} |
|
911 |
); |
|
912 |
$self->models->finalize; # for filter laundering |
|
913 |
|
|
914 |
$report->set_options( |
|
915 |
std_column_visibility => 1, |
|
916 |
controller_class => 'EmailJournal', |
|
917 |
output_format => 'HTML', |
|
918 |
raw_top_info_text => $self->render( |
|
919 |
'email_journal/_report_top', |
|
920 |
{ output => 0 }, |
|
921 |
FILTER_HTML => $filter_html, |
|
922 |
), |
|
923 |
raw_bottom_info_text => $self->render( |
|
924 |
'email_journal/_report_bottom', |
|
925 |
{ output => 0 }, |
|
926 |
models => $self->models |
|
927 |
), |
|
928 |
title => t8('Email journal'), |
|
929 |
allow_pdf_export => 1, |
|
930 |
allow_csv_export => 1, |
|
931 |
); |
|
932 |
$report->set_columns(%column_defs); |
|
933 |
$report->set_column_order(@columns_order); |
|
934 |
$report->set_export_options('list', qw(filter active_in_report)); |
|
935 |
$report->set_options_from_form; |
|
936 |
|
|
937 |
$self->models->set_report_generator_sort_options( |
|
938 |
report => $report, |
|
939 |
sortable_columns => \@sortable |
|
940 |
); |
|
941 |
|
|
942 |
return $report; |
|
943 |
} |
|
944 |
|
|
781 | 945 |
sub add_js { |
782 | 946 |
$::request->{layout}->use_javascript("${_}.js") for qw( |
783 | 947 |
kivi.EmailJournal |
... | ... | |
797 | 961 |
query => \@where, |
798 | 962 |
with_objects => [ 'sender' ], |
799 | 963 |
sorted => { |
964 |
_default => { |
|
965 |
by => 'sent_on', |
|
966 |
dir => 0, |
|
967 |
}, |
|
800 | 968 |
sender => t8('Sender'), |
801 | 969 |
from => t8('From'), |
802 | 970 |
recipients => t8('Recipients'), |
803 | 971 |
subject => t8('Subject'), |
804 |
attachments => t8('Attachments'), |
|
972 |
attachment_names => t8('Attachments'), |
|
973 |
has_unprocessed_attachments => t8('Has unprocessed attachments'), |
|
974 |
unprocessed_attachment_names => t8('Unprocessed Attachments'), |
|
805 | 975 |
sent_on => t8('Sent on'), |
806 | 976 |
status => t8('Status'), |
807 | 977 |
extended_status => t8('Extended status'), |
808 | 978 |
record_type => t8('Record Type'), |
809 | 979 |
obsolete => t8('Obsolete'), |
810 | 980 |
linked_to => t8('Linked to'), |
811 |
has_unprocessed_attachments => t8('Has unprocessed attachments'), |
|
812 | 981 |
}, |
813 | 982 |
); |
814 | 983 |
} |
SL/DB/Manager/EmailJournal.pm | ||
---|---|---|
33 | 33 |
) |
34 | 34 |
)} => \'TRUE'; |
35 | 35 |
}, |
36 |
unprocessed_attachment_names => sub { |
|
37 |
my ($key, $value, $prefix) = @_; |
|
38 |
return ( |
|
39 |
and => [ |
|
40 |
'attachments.name' => $value, |
|
41 |
'attachments.processed' => 0, |
|
42 |
], |
|
43 |
'attachments' |
|
44 |
) |
|
45 |
}, |
|
36 | 46 |
has_unprocessed_attachments => sub { |
37 | 47 |
my ($key, $value, $prefix) = @_; |
38 | 48 |
|
... | ... | |
68 | 78 |
AND record_links.to_id = email_journal.id |
69 | 79 |
) |
70 | 80 |
)}, |
71 |
attachment => qq{( |
|
81 |
attachment_names => qq{( |
|
82 |
SELECT STRING_AGG( |
|
83 |
email_journal_attachments.name, |
|
84 |
', ' |
|
85 |
ORDER BY email_journal_attachments.position ASC |
|
86 |
) |
|
87 |
FROM email_journal_attachments |
|
88 |
WHERE |
|
89 |
email_journal_attachments.email_journal_id = email_journal.id |
|
90 |
)}, |
|
91 |
unprocessed_attachment_names => qq{( |
|
72 | 92 |
SELECT STRING_AGG( |
73 | 93 |
email_journal_attachments.name, |
74 | 94 |
', ' |
... | ... | |
77 | 97 |
FROM email_journal_attachments |
78 | 98 |
WHERE |
79 | 99 |
email_journal_attachments.email_journal_id = email_journal.id |
100 |
AND email_journal_attachments.processed = FALSE |
|
80 | 101 |
)}, |
81 | 102 |
has_unprocessed_attachments => qq{( |
82 | 103 |
SELECT count(*) |
SL/Presenter/Filter/EmailJournal.pm | ||
---|---|---|
1 |
package SL::Presenter::Filter::EmailJournal; |
|
2 |
|
|
3 |
use parent SL::Presenter::Filter; |
|
4 |
|
|
5 |
use strict; |
|
6 |
|
|
7 |
use SL::Locale::String qw(t8); |
|
8 |
|
|
9 |
use Params::Validate qw(:all); |
|
10 |
|
|
11 |
sub get_default_filter_elements { |
|
12 |
my ($filter) = shift @_; |
|
13 |
my %params = validate_with( |
|
14 |
params => \@_, |
|
15 |
spec => { |
|
16 |
record_types_with_info => { |
|
17 |
type => ARRAYREF |
|
18 |
}, |
|
19 |
}, |
|
20 |
); |
|
21 |
|
|
22 |
my %default_filter_elements = ( # {{{ |
|
23 |
id => { |
|
24 |
'position' => 1, |
|
25 |
'text' => t8("ID"), |
|
26 |
'input_type' => 'input_tag', |
|
27 |
'input_name' => 'filter.id:number', |
|
28 |
'input_default' => $filter->{'id:number'}, |
|
29 |
'report_id' => 'id', |
|
30 |
'active' => 0, |
|
31 |
}, |
|
32 |
sender => { |
|
33 |
'position' => 2, |
|
34 |
'text' => t8("Sender"), |
|
35 |
'input_type' => 'input_tag', |
|
36 |
'input_name' => 'filter.sender.name:substr::ilike', |
|
37 |
'input_default' => $filter->{sender}->{'name:substr::ilike'}, |
|
38 |
'report_id' => 'sender', |
|
39 |
'active' => $::auth->assert('email_employee_readall', 1), |
|
40 |
}, |
|
41 |
from => { |
|
42 |
'position' => 3, |
|
43 |
'text' => t8("From"), |
|
44 |
'input_type' => 'input_tag', |
|
45 |
'input_name' => 'filter.from:substr::ilike', |
|
46 |
'input_default' => $filter->{'from:substr::ilike'}, |
|
47 |
'report_id' => 'from', |
|
48 |
'active' => 1, |
|
49 |
}, |
|
50 |
recipients => { |
|
51 |
'position' => 4, |
|
52 |
'text' => t8("Recipients"), |
|
53 |
'input_type' => 'input_tag', |
|
54 |
'input_name' => 'filter.recipients:substr::ilike', |
|
55 |
'input_default' => $filter->{'recipients:substr::ilike'}, |
|
56 |
'report_id' => 'recipients', |
|
57 |
'active' => 1, |
|
58 |
}, |
|
59 |
subject => { |
|
60 |
'position' => 5, |
|
61 |
'text' => t8("Subject"), |
|
62 |
'input_type' => 'input_tag', |
|
63 |
'input_name' => 'filter.subject:substr::ilike', |
|
64 |
'input_default' => $filter->{'subject:substr::ilike'}, |
|
65 |
'report_id' => 'subject', |
|
66 |
'active' => 1, |
|
67 |
}, |
|
68 |
sent_on => { |
|
69 |
'position' => 6, |
|
70 |
'text' => t8("Sent on"), |
|
71 |
'input_type' => 'date_tag', |
|
72 |
'input_name' => 'sent_on', |
|
73 |
'input_default_ge' => $filter->{'sent_on' . ':date::ge'}, |
|
74 |
'input_default_le' => $filter->{'sent_on' . ':date::le'}, |
|
75 |
'report_id' => 'sent_on', |
|
76 |
'active' => 1, |
|
77 |
}, |
|
78 |
attachment_names => { |
|
79 |
'position' => 7, |
|
80 |
'text' => t8("Attachments"), |
|
81 |
'input_type' => 'input_tag', |
|
82 |
'input_name' => 'filter.attachments.name:substr::ilike', |
|
83 |
'input_default' => $filter->{attachments}->{'name:substr::ilike'}, |
|
84 |
'report_id' => 'attachment_names', |
|
85 |
'active' => 1, |
|
86 |
}, |
|
87 |
'has_unprocessed_attachments' => { |
|
88 |
'position' => 8, |
|
89 |
'text' => t8("Has unprocessed attachments"), |
|
90 |
'input_type' => 'yes_no_tag', |
|
91 |
'input_name' => 'filter.has_unprocessed_attachments:eq_ignore_empty', |
|
92 |
'input_default' => $filter->{'has_unprocessed_attachments:eq_ignore_empty'}, |
|
93 |
'report_id' => 'has_unprocessed_attachments', |
|
94 |
'active' => 1, |
|
95 |
}, |
|
96 |
unprocessed_attachment_names => { |
|
97 |
'position' => 9, |
|
98 |
'text' => t8("Unprocessed Attachments"), |
|
99 |
'input_type' => 'input_tag', |
|
100 |
'input_name' => 'filter.unprocessed_attachment_names:substr::ilike', |
|
101 |
'input_default' => $filter->{'unprocessed_attachment_names:substr::ilike'}, |
|
102 |
'report_id' => 'unprocessed_attachment_names', |
|
103 |
'active' => 1, |
|
104 |
}, |
|
105 |
status => { |
|
106 |
'position' => 10, |
|
107 |
'text' => t8("Status"), |
|
108 |
'input_type' => 'select_tag', |
|
109 |
'input_values' => [ |
|
110 |
[ "", "" ], |
|
111 |
[ "send_failed", t8("send failed") ], |
|
112 |
[ "sent", t8("sent") ], |
|
113 |
[ "imported", t8("imported") ] |
|
114 |
], |
|
115 |
'input_name' => 'filter.status', |
|
116 |
'input_default' => $filter->{'status'}, |
|
117 |
'report_id' => 'status', |
|
118 |
'active' => 1, |
|
119 |
}, |
|
120 |
extended_status => { |
|
121 |
'position' => 11, |
|
122 |
'text' => t8("Extended status"), |
|
123 |
'input_type' => 'input_tag', |
|
124 |
'input_name' => 'filter.extended_status:substr::ilike', |
|
125 |
'input_default' => $filter->{'extended_status:substr::ilike'}, |
|
126 |
'report_id' => 'extended_status', |
|
127 |
'active' => 1, |
|
128 |
}, |
|
129 |
record_type => { |
|
130 |
'position' => 12, |
|
131 |
'text' => t8("Record Type"), |
|
132 |
'input_type' => 'select_tag', |
|
133 |
'input_values' => [ |
|
134 |
map {[ |
|
135 |
$_->{record_type} => $_->{text}, |
|
136 |
]} |
|
137 |
grep {!$_->{is_template}} |
|
138 |
{}, |
|
139 |
{text=> t8("Catch-all"), record_type => 'catch_all'}, |
|
140 |
@{$params{record_types_with_info}} |
|
141 |
], |
|
142 |
'input_name' => 'filter.record_type:eq_ignore_empty', |
|
143 |
'input_default' => $filter->{'record_type:eq_ignore_empty'}, |
|
144 |
'report_id' => 'record_type', |
|
145 |
'active' => 1, |
|
146 |
}, |
|
147 |
'linked' => { |
|
148 |
'position' => 13, |
|
149 |
'text' => t8("Linked"), |
|
150 |
'input_type' => 'yes_no_tag', |
|
151 |
'input_name' => 'filter.linked_to:eq_ignore_empty', |
|
152 |
'input_default' => $filter->{'linked_to:eq_ignore_empty'}, |
|
153 |
'report_id' => 'linked_to', |
|
154 |
'active' => 1, |
|
155 |
}, |
|
156 |
'obsolete' => { |
|
157 |
'position' => 14, |
|
158 |
'text' => t8("Obsolete"), |
|
159 |
'input_type' => 'yes_no_tag', |
|
160 |
'input_name' => 'filter.obsolete:eq_ignore_empty', |
|
161 |
'input_default' => $filter->{'obsolete:eq_ignore_empty'}, |
|
162 |
'report_id' => 'obsolete', |
|
163 |
'active' => 1, |
|
164 |
}, |
|
165 |
); # }}} |
|
166 |
return \%default_filter_elements; |
|
167 |
} |
|
168 |
|
|
169 |
sub filter { |
|
170 |
my $filter = shift @_ || {}; |
|
171 |
die "filter has to be a hash ref" if ref $filter ne 'HASH'; |
|
172 |
my %params = validate_with( |
|
173 |
params => \@_, |
|
174 |
spec => { |
|
175 |
record_types_with_info => { |
|
176 |
type => ARRAYREF |
|
177 |
}, |
|
178 |
}, |
|
179 |
allow_extra => 1, |
|
180 |
); |
|
181 |
|
|
182 |
my $filter_elements = get_default_filter_elements($filter, |
|
183 |
record_types_with_info => delete $params{record_types_with_info}, |
|
184 |
); |
|
185 |
|
|
186 |
return SL::Presenter::Filter::create_filter($filter_elements, %params); |
|
187 |
} |
|
188 |
|
|
189 |
1; |
|
190 |
|
|
191 |
__END__ |
|
192 |
|
|
193 |
=pod |
|
194 |
|
|
195 |
=encoding utf8 |
|
196 |
|
|
197 |
=head1 NAME |
|
198 |
|
|
199 |
SL::Presenter::Filter::EmailJournal - Presenter module for a generic filter on |
|
200 |
EmailJournal. |
|
201 |
|
|
202 |
=head1 SYNOPSIS |
|
203 |
|
|
204 |
# in EmailJournal Controller |
|
205 |
my $filter_html = SL::Presenter::Filter::EmailJournal::filter( |
|
206 |
$::form->{filter}, |
|
207 |
active_in_report => $::form->{active_in_report} |
|
208 |
record_types_with_info => \@record_types_with_info, |
|
209 |
); |
|
210 |
|
|
211 |
|
|
212 |
=head1 FUNCTIONS |
|
213 |
|
|
214 |
=over 4 |
|
215 |
|
|
216 |
=item C<filter $filter, %params> |
|
217 |
|
|
218 |
Returns a rendered version (actually an instance of |
|
219 |
L<SL::Presenter::EscapedText>) of a filter form for email journal. |
|
220 |
|
|
221 |
C<$filter> should be the C<filter> value of the last C<$::form>. This is used to |
|
222 |
get the previous values of the input fields. |
|
223 |
|
|
224 |
C<%params> can include: |
|
225 |
|
|
226 |
=over 2 |
|
227 |
|
|
228 |
|
|
229 |
= item * record_types_with_info |
|
230 |
|
|
231 |
Is used to set the drop down for record type. |
|
232 |
|
|
233 |
=back |
|
234 |
|
|
235 |
Other C<%params> fields get forwarded to |
|
236 |
C<SL::Presenter::Filter::create_filter>. |
|
237 |
|
|
238 |
=back |
|
239 |
|
|
240 |
=head1 BUGS |
|
241 |
|
|
242 |
Nothing here yet. |
|
243 |
|
|
244 |
=head1 AUTHOR |
|
245 |
|
|
246 |
Tamino Steinert E<lt>tamino.steinert@tamino.stE<gt> |
|
247 |
|
|
248 |
=cut |
locale/de/all | ||
---|---|---|
4378 | 4378 |
'There are mulitple vendors selected' => 'Es sind mehrere Lieferanten ausgewählt', |
4379 | 4379 |
'There are no documents in the WebDAV directory at the moment.' => 'Es befinden sich im WebDAV-Verzeichnis momentan keine Dokumente.', |
4380 | 4380 |
'There are no entries in the background job history.' => 'Es gibt keine Einträge im Hintergrund-Job-Verlauf.', |
4381 |
'There are no entries that match the filter.' => 'Es gibt keine Einträge, auf die der Filter zutrifft.', |
|
4382 | 4381 |
'There are no items in stock.' => 'Dieser Artikel ist nicht eingelagert.', |
4383 | 4382 |
'There are no items on your TODO list at the moment.' => 'Ihre Aufgabenliste enthält momentan keine Einträge.', |
4384 | 4383 |
'There are no items selected' => 'Es wurden keine Positionen ausgewählt', |
... | ... | |
4669 | 4668 |
'Unlink bank transactions' => 'Bankverbuchung(en) rückgängig machen', |
4670 | 4669 |
'Unlock System' => 'System entsperren', |
4671 | 4670 |
'Unprocessed' => 'Nicht verarbeitet', |
4671 |
'Unprocessed Attachments' => 'Nicht verarbeitete Anhänge', |
|
4672 | 4672 |
'Unsuccessfully executed:\n' => 'Erfolglos ausgeführt:', |
4673 | 4673 |
'Unsupported image type (supported types: #1)' => 'Nicht unterstützter Bildtyp (unterstützte Typen: #1)', |
4674 | 4674 |
'Until' => 'Bis', |
locale/en/all | ||
---|---|---|
4376 | 4376 |
'There are mulitple vendors selected' => '', |
4377 | 4377 |
'There are no documents in the WebDAV directory at the moment.' => '', |
4378 | 4378 |
'There are no entries in the background job history.' => '', |
4379 |
'There are no entries that match the filter.' => '', |
|
4380 | 4379 |
'There are no items in stock.' => '', |
4381 | 4380 |
'There are no items on your TODO list at the moment.' => '', |
4382 | 4381 |
'There are no items selected' => '', |
... | ... | |
4667 | 4666 |
'Unlink bank transactions' => '', |
4668 | 4667 |
'Unlock System' => '', |
4669 | 4668 |
'Unprocessed' => '', |
4669 |
'Unprocessed Attachments' => '', |
|
4670 | 4670 |
'Unsuccessfully executed:\n' => '', |
4671 | 4671 |
'Unsupported image type (supported types: #1)' => '', |
4672 | 4672 |
'Until' => '', |
templates/design40_webpages/email_journal/_filter.html | ||
---|---|---|
1 |
[% USE L %] |
|
2 |
[% USE LxERP %] |
|
3 |
[% USE HTML %] |
|
4 |
|
|
5 |
[% BLOCK filter_toggle_panel %] |
|
6 |
<table id="filter_table" class="tbl-horizontal"> |
|
7 |
<tbody> |
|
8 |
<tr> |
|
9 |
<th>[% LxERP.t8("From") %]</th> |
|
10 |
<td>[% L.input_tag("filter.from:substr::ilike", filter.from_substr__ilike, size = 20) %] |
|
11 |
</td> |
|
12 |
</tr> |
|
13 |
<tr> |
|
14 |
<th>[% LxERP.t8("Recipients") %]</th> |
|
15 |
<td>[% L.input_tag("filter.recipients:substr::ilike", filter.recipients_substr__ilike, size = 20) %] |
|
16 |
</td> |
|
17 |
</tr> |
|
18 |
<tr> |
|
19 |
<th>[% LxERP.t8("Sent on") %]</th> |
|
20 |
<td>[% L.date_tag("filter.sent_on:date::ge", filter.sent_on_date__ge) %] [% LxERP.t8("To Date") %] [% L.date_tag("filter.sent_on:date::le", filter.sent_on_date__le) %] |
|
21 |
</td> |
|
22 |
</tr> |
|
23 |
<tr> |
|
24 |
<th>[% LxERP.t8("Status") %]</th> |
|
25 |
<td>[% L.select_tag("filter.status:eq_ignore_empty", [ |
|
26 |
[ "", "" ], |
|
27 |
[ "send_failed", LxERP.t8("send failed") ], |
|
28 |
[ "sent", LxERP.t8("sent") ], |
|
29 |
[ "imported", LxERP.t8("imported") ] |
|
30 |
], default=filter.status_eq_ignore_empty) %] |
|
31 |
</td> |
|
32 |
</tr> |
|
33 |
<tr> |
|
34 |
<th>[% LxERP.t8("Record Type") %]</th> |
|
35 |
<td> |
|
36 |
[% |
|
37 |
SET record_type_options = []; |
|
38 |
record_type_options.push({text=LxERP.t8("Catch-all"), record_type='catch_all'}); |
|
39 |
FOREACH record_info = RECORD_TYPES_WITH_INFO; |
|
40 |
IF (!record_info.is_template); |
|
41 |
record_type_options.push(record_info); |
|
42 |
END; |
|
43 |
END; |
|
44 |
%] |
|
45 |
[% L.select_tag("filter.record_type:eq_ignore_empty", |
|
46 |
record_type_options, |
|
47 |
title_key = 'text', value_key = 'record_type', |
|
48 |
with_empty=1, default=filter.record_type_eq_ignore_empty) %] |
|
49 |
</td> |
|
50 |
</tr> |
|
51 |
<tr> |
|
52 |
<th>[% LxERP.t8("Obsolete") %]</th> |
|
53 |
<td>[% L.yes_no_tag("filter.obsolete:eq_ignore_empty", |
|
54 |
filter.obsolete, with_empty=1, |
|
55 |
default=filter.obsolete_eq_ignore_empty |
|
56 |
) %] |
|
57 |
</td> |
|
58 |
</tr> |
|
59 |
<tr> |
|
60 |
<th>[% LxERP.t8("Linked") %]</th> |
|
61 |
<td>[% L.yes_no_tag("filter.linked_to:eq_ignore_empty", |
|
62 |
filter.linked_to, with_empty=1, |
|
63 |
default=filter.linked_to_eq_ignore_empty |
|
64 |
) %] |
|
65 |
</td> |
|
66 |
</tr> |
|
67 |
<tr> |
|
68 |
<th>[% LxERP.t8("Has unprocessed attachments") %]</th> |
|
69 |
<td>[% L.yes_no_tag("filter.has_unprocessed_attachments:eq_ignore_empty", |
|
70 |
filter.has_unprocessed_attachments, with_empty=1, |
|
71 |
default=filter.has_unprocessed_attachments_eq_ignore_empty |
|
72 |
) %] |
|
73 |
</td> |
|
74 |
</tr> |
|
75 |
</tbody> |
|
76 |
</table> |
|
77 |
[% L.hidden_tag("sort_by", FORM.sort_by) %] |
|
78 |
[% L.hidden_tag("sort_dir", FORM.sort_dir) %] |
|
79 |
[% L.hidden_tag("page", FORM.page) %] |
|
80 |
<div class="buttons">[% L.button_tag('$("#filter_form").resetForm()', LxERP.t8('Reset')) %]</div> |
|
81 |
[% END %] |
|
82 |
|
|
83 |
<div class="wrapper"> |
|
84 |
<form action="controller.pl" method="post" id="filter_form"> |
|
85 |
|
|
86 |
[% INCLUDE common/toggle_panel.html %] |
|
87 |
|
|
88 |
|
|
89 |
|
|
90 |
</div> |
|
91 |
|
|
92 |
</form> |
|
93 |
</div> |
templates/design40_webpages/email_journal/_report_bottom.html | ||
---|---|---|
1 |
[% USE L %] |
|
2 |
[%- L.paginate_controls(models=models) %] |
templates/design40_webpages/email_journal/_report_top.html | ||
---|---|---|
1 |
[% USE L %] |
|
2 |
|
|
3 |
[% BLOCK filter_toggle_panel %] |
|
4 |
[%- FILTER_HTML %] |
|
5 |
[% END %] |
|
6 |
|
|
7 |
<div class="wrapper"> |
|
8 |
[% SET display_status = 'open' %] |
|
9 |
[% INCLUDE 'common/toggle_panel.html' %] |
|
10 |
</div><!-- /.wrapper --> |
templates/design40_webpages/email_journal/list.html | ||
---|---|---|
1 |
[% USE HTML %] |
|
2 |
[% USE L %] |
|
3 |
[% USE P %] |
|
4 |
[% USE LxERP %] |
|
5 |
|
|
6 |
<h1>[% FORM.title %]</h1> |
|
7 |
|
|
8 |
[% INCLUDE 'common/flash.html' %] |
|
9 |
[% PROCESS 'email_journal/_filter.html' filter=SELF.models.filtered.laundered %] |
|
10 |
|
|
11 |
[% IF !ENTRIES.size %] |
|
12 |
<p>[% LxERP.t8('There are no entries that match the filter.') %]</p> |
|
13 |
|
|
14 |
[% ELSE %] |
|
15 |
|
|
16 |
<table id="email_journal_list" class="tbl-list wi-moderate"> |
|
17 |
<thead> |
|
18 |
<tr> |
|
19 |
[% IF SELF.can_view_all %] |
|
20 |
<th>[% L.sortable_table_header("sender") %]</th> |
|
21 |
[% END %] |
|
22 |
<th>[% L.sortable_table_header("from") %]</th> |
|
23 |
<th>[% L.sortable_table_header("recipients") %]</th> |
|
24 |
<th>[% L.sortable_table_header("subject") %]</th> |
|
25 |
<th>[% L.sortable_table_header("sent_on") %]</th> |
|
26 |
<th>[% L.sortable_table_header("attachments") %]</th> |
|
27 |
<th>[% L.sortable_table_header("status") %]</th> |
|
28 |
<th>[% L.sortable_table_header("extended_status") %]</th> |
|
29 |
<th>[% L.sortable_table_header("record_type") %]</th> |
|
30 |
<th>[% L.sortable_table_header("obsolete") %]</th> |
|
31 |
<th>[% L.sortable_table_header("linked_to") %]</th> |
|
32 |
<th>[% L.sortable_table_header("has_unprocessed_attachments") %]</th> |
|
33 |
</tr> |
|
34 |
</thead> |
|
35 |
<tbody> |
|
36 |
[% FOREACH entry = ENTRIES %] |
|
37 |
<tr id="email_journal_id_[% entry.id %]" [% IF entry.status == 'send_failed' %] class="listrow_error" [% END %]> |
|
38 |
[% IF SELF.can_view_all %] |
|
39 |
<td>[% IF entry.sender %] [% HTML.escape(entry.sender.name) %] [% ELSE %] [% LxERP.t8("kivitendo") %] [% END %]</td> |
|
40 |
[% END %] |
|
41 |
[% action_show_link = SELF.url_for( |
|
42 |
action => 'show', id => entry.id, |
|
43 |
back_to => SELF.models.get_callback(), |
|
44 |
) %] |
|
45 |
<td><a href="[% action_show_link %]"> [% HTML.escape(entry.from) %] </a></td> |
|
46 |
<td>[% HTML.escape(entry.recipients) %]</td> |
|
47 |
<td><a href="[% action_show_link %]"> [% HTML.escape(entry.subject) %] </a></td> |
|
48 |
<td>[% HTML.escape(entry.sent_on.to_lxoffice('precision' => 'second')) %]</td> |
|
49 |
<td> |
|
50 |
[% FOREACH attachment = entry.attachments %] |
|
51 |
<span>[% HTML.escape(attachment.name) %]</span> |
|
52 |
[% END %] |
|
53 |
</td> |
|
54 |
<td> [% P.email_journal.entry_status(entry) %] </td> |
|
55 |
<td>[% HTML.escape(entry.extended_status) %]</td> |
|
56 |
<td>[% HTML.escape(RECORD_TYPES_TO_TEXT.${entry.record_type}) %]</td> |
|
57 |
<td>[% HTML.escape(entry.obsolete_as_bool_yn) %]</td> |
|
58 |
<td> |
|
59 |
[% P.record.simple_grouped_record_list(entry.linked_records) %] |
|
60 |
</td> |
|
61 |
<td>[% HTML.escape(entry.has_unprocessed_attachments) %]</td> |
|
62 |
</tr> |
|
63 |
[% END %] |
|
64 |
</tbody> |
|
65 |
</table> |
|
66 |
|
|
67 |
[% END %] |
|
68 |
|
|
69 |
[% L.paginate_controls %] |
templates/webpages/email_journal/_filter.html | ||
---|---|---|
1 |
[%- USE L %][%- USE LxERP %][%- USE HTML %] |
|
2 |
<form action="controller.pl" method="post" id="filter_form"> |
|
3 |
<div class="filter_toggle"> |
|
4 |
<a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Show Filter') %]</a> |
|
5 |
[% IF SELF.filter_summary %]([% LxERP.t8("Current filter") %]: [% SELF.filter_summary %])[% END %] |
|
6 |
</div> |
|
7 |
|
|
8 |
<div class="filter_toggle" style="display:none"> |
|
9 |
<a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Hide Filter') %]</a> |
|
10 |
<table id="filter_table"> |
|
11 |
<tr> |
|
12 |
<th align="right">[% LxERP.t8("From") %]</th> |
|
13 |
<td>[% L.input_tag("filter.from:substr::ilike", filter.from_substr__ilike, size = 20) %]</td> |
|
14 |
</tr> |
|
15 |
<tr> |
|
16 |
<th align="right">[% LxERP.t8("Recipients") %]</th> |
|
17 |
<td>[% L.input_tag("filter.recipients:substr::ilike", filter.recipients_substr__ilike, size = 20) %]</td> |
|
18 |
</tr> |
|
19 |
<tr> |
|
20 |
<th align="right">[% LxERP.t8("Sent on") %]</th> |
|
21 |
<td> |
|
22 |
[% L.date_tag("filter.sent_on:date::ge", filter.sent_on_date__ge) %] |
|
23 |
[% LxERP.t8("To Date") %] |
|
24 |
[% L.date_tag("filter.sent_on:date::le", filter.sent_on_date__le) %] |
|
25 |
</td> |
|
26 |
</tr> |
|
27 |
<tr> |
|
28 |
<th align="right">[% LxERP.t8("Status") %]</th> |
|
29 |
<td>[% L.select_tag("filter.status:eq_ignore_empty", [ |
|
30 |
[ "", "" ], |
|
31 |
[ "send_failed", LxERP.t8("send failed") ], |
|
32 |
[ "sent", LxERP.t8("sent") ], |
|
33 |
[ "imported", LxERP.t8("imported") ] |
|
34 |
], default=filter.status_eq_ignore_empty) %]</td> |
|
35 |
</tr> |
|
36 |
<tr> |
|
37 |
<th align="right">[% LxERP.t8("Record Type") %]</th> |
|
38 |
<td> |
|
39 |
[% |
|
40 |
SET record_type_options = []; |
|
41 |
record_type_options.push({text=LxERP.t8("Catch-all"), record_type='catch_all'}); |
|
42 |
FOREACH record_info = RECORD_TYPES_WITH_INFO; |
|
43 |
IF (!record_info.is_template); |
|
44 |
record_type_options.push(record_info); |
|
45 |
END; |
|
46 |
END; |
|
47 |
%] |
|
48 |
[% L.select_tag("filter.record_type:eq_ignore_empty", |
|
49 |
record_type_options, |
|
50 |
title_key = 'text', value_key = 'record_type', |
|
51 |
with_empty=1, default=filter.record_type_eq_ignore_empty) %] |
|
52 |
</td> |
|
53 |
</tr> |
|
54 |
<tr> |
|
55 |
<th align="right">[% LxERP.t8("Obsolete") %]</th> |
|
56 |
<td>[% L.yes_no_tag("filter.obsolete:eq_ignore_empty", |
|
57 |
filter.obsolete, with_empty=1, |
|
58 |
default=filter.obsolete_eq_ignore_empty |
|
59 |
) %] |
|
60 |
</td> |
|
61 |
<tr> |
|
62 |
<th align="right">[% LxERP.t8("Linked") %]</th> |
|
63 |
<td>[% L.yes_no_tag("filter.linked_to:eq_ignore_empty", |
|
64 |
filter.linked_to, with_empty=1, |
|
65 |
default=filter.linked_to_eq_ignore_empty |
|
66 |
) %] |
|
67 |
</td> |
|
68 |
</tr> |
|
69 |
<tr> |
|
70 |
<th>[% LxERP.t8("Has unprocessed attachments") %]</th> |
|
71 |
<td>[% L.yes_no_tag("filter.has_unprocessed_attachments:eq_ignore_empty", |
|
72 |
filter.has_unprocessed_attachments, with_empty=1, |
|
73 |
default=filter.has_unprocessed_attachments_eq_ignore_empty |
|
74 |
) %] |
|
75 |
</td> |
|
76 |
</tr> |
|
77 |
</table> |
|
78 |
|
|
79 |
[% L.hidden_tag("sort_by", FORM.sort_by) %] |
|
80 |
[% L.hidden_tag("sort_dir", FORM.sort_dir) %] |
|
81 |
[% L.hidden_tag("page", FORM.page) %] |
|
82 |
|
|
83 |
[% L.button_tag('$("#filter_form").resetForm()', LxERP.t8('Reset')) %] |
|
84 |
|
|
85 |
</div> |
|
86 |
|
|
87 |
</form> |
templates/webpages/email_journal/_report_bottom.html | ||
---|---|---|
1 |
[% USE L %] |
|
2 |
[%- L.paginate_controls(models=models) %] |
templates/webpages/email_journal/_report_top.html | ||
---|---|---|
1 |
[% USE L %] |
|
2 |
|
|
3 |
[% FILTER_HTML %] |
templates/webpages/email_journal/list.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE P %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
[%- PROCESS 'email_journal/_filter.html' filter=SELF.models.filtered.laundered %] |
|
8 |
|
|
9 |
[% IF !ENTRIES.size %] |
|
10 |
<p> |
|
11 |
[%- LxERP.t8('There are no entries that match the filter.') %] |
|
12 |
</p> |
|
13 |
|
|
14 |
[%- ELSE %] |
|
15 |
<table id="email_journal_list" width="100%"> |
|
16 |
<thead> |
|
17 |
<tr class="listheading"> |
|
18 |
[% IF SELF.can_view_all %] |
|
19 |
<th>[% L.sortable_table_header("sender") %]</th> |
|
20 |
[% END %] |
|
21 |
<th>[% L.sortable_table_header("from") %]</th> |
|
22 |
<th>[% L.sortable_table_header("recipients") %]</th> |
|
23 |
<th>[% L.sortable_table_header("subject") %]</th> |
|
24 |
<th>[% L.sortable_table_header("sent_on") %]</th> |
|
25 |
<th>[% L.sortable_table_header("attachments") %]</th> |
|
26 |
<th>[% L.sortable_table_header("status") %]</th> |
|
27 |
<th>[% L.sortable_table_header("extended_status") %]</th> |
|
28 |
<th>[% L.sortable_table_header("record_type") %]</th> |
|
29 |
<th>[% L.sortable_table_header("obsolete") %]</th> |
|
30 |
<th>[% L.sortable_table_header("linked_to") %]</th> |
|
31 |
<th>[% L.sortable_table_header("has_unprocessed_attachments") %]</th> |
|
32 |
</tr> |
|
33 |
</thead> |
|
34 |
|
|
35 |
<tbody> |
|
36 |
[%- FOREACH entry = ENTRIES %] |
|
37 |
<tr class="listrow[% IF entry.status == 'send_failed' %]_error[% END %]" id="email_journal_id_[% entry.id %]"> |
|
38 |
[% IF SELF.can_view_all %] |
|
39 |
<td> |
|
40 |
[% IF entry.sender %] |
|
41 |
[% HTML.escape(entry.sender.name) %] |
|
42 |
[% ELSE %] |
|
43 |
[% LxERP.t8("kivitendo") %] |
|
44 |
[% END %] |
|
45 |
</td> |
|
46 |
[% END %] |
|
47 |
[% action_show_link = SELF.url_for( |
|
48 |
action => 'show', id => entry.id, |
|
49 |
back_to => SELF.models.get_callback(), |
|
50 |
) %] |
|
51 |
<td><a href="[% action_show_link %]">[%- HTML.escape(entry.from) %]</a></td> |
|
52 |
<td>[%- HTML.escape(entry.recipients) %]</td> |
|
53 |
<td><a href="[% action_show_link %]">[%- HTML.escape(entry.subject) %]</a></td> |
|
54 |
<td>[%- HTML.escape(entry.sent_on.to_lxoffice('precision' => 'second')) %]</td> |
|
55 |
<td> |
|
56 |
[% FOREACH attachment = entry.attachments %] |
|
57 |
<span>[% HTML.escape(attachment.name) %]</span> |
|
58 |
[% END %] |
|
59 |
</td> |
|
60 |
<td> [% P.email_journal.entry_status(entry) %] </td> |
|
61 |
<td>[%- HTML.escape(entry.extended_status) %]</td> |
|
62 |
<td>[% HTML.escape(RECORD_TYPES_TO_TEXT.${entry.record_type}) %]</td> |
|
63 |
<td>[% HTML.escape(entry.obsolete_as_bool_yn) %]</td> |
|
64 |
<td> |
|
65 |
[% P.record.simple_grouped_record_list(entry.linked_records) %] |
|
66 |
</td> |
|
67 |
<td>[% HTML.escape(entry.has_unprocessed_attachments) %]</td> |
|
68 |
</tr> |
|
69 |
[%- END %] |
|
70 |
</tbody> |
|
71 |
</table> |
|
72 |
[%- END %] |
|
73 |
|
|
74 |
[% L.paginate_controls %] |
Auch abrufbar als: Unified diff
EmailJournal: Komplexer Bericht mit komplexen Filter