Revision 72f19f83
Von Moritz Bunkus vor mehr als 9 Jahren hinzugefügt
SL/Controller/EmailJournal.pm | ||
---|---|---|
1 |
package SL::Controller::EmailJournal; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::Controller::Base); |
|
6 |
|
|
7 |
use SL::Controller::Helper::GetModels; |
|
8 |
use SL::DB::Employee; |
|
9 |
use SL::DB::EmailJournal; |
|
10 |
use SL::DB::EmailJournalAttachment; |
|
11 |
use SL::Helper::Flash; |
|
12 |
use SL::Locale::String; |
|
13 |
use SL::System::TaskServer; |
|
14 |
|
|
15 |
use Rose::Object::MakeMethods::Generic |
|
16 |
( |
|
17 |
scalar => [ qw(entry) ], |
|
18 |
'scalar --get_set_init' => [ qw(models can_view_all filter_summary) ], |
|
19 |
); |
|
20 |
|
|
21 |
__PACKAGE__->run_before('add_stylesheet'); |
|
22 |
|
|
23 |
# |
|
24 |
# actions |
|
25 |
# |
|
26 |
|
|
27 |
sub action_list { |
|
28 |
my ($self) = @_; |
|
29 |
|
|
30 |
$self->render('email_journal/list', |
|
31 |
title => $::locale->text('Email journal'), |
|
32 |
ENTRIES => $self->models->get, |
|
33 |
MODELS => $self->models); |
|
34 |
} |
|
35 |
|
|
36 |
sub action_show { |
|
37 |
my ($self) = @_; |
|
38 |
|
|
39 |
my $back_to = $::form->{back_to} || $self->url_for(action => 'list'); |
|
40 |
|
|
41 |
$self->entry(SL::DB::EmailJournal->new(id => $::form->{id})->load); |
|
42 |
|
|
43 |
if (!$self->can_view_all && ($self->entry->sender_id != SL::DB::Manager::Emplyee->current->id)) { |
|
44 |
$::form->error(t8('You do not have permission to access this entry.')); |
|
45 |
} |
|
46 |
|
|
47 |
$self->render('email_journal/show', |
|
48 |
title => $::locale->text('View sent email'), |
|
49 |
back_to => $back_to); |
|
50 |
} |
|
51 |
|
|
52 |
sub action_download_attachment { |
|
53 |
my ($self) = @_; |
|
54 |
|
|
55 |
my $attachment = SL::DB::EmailJournalAttachment->new(id => $::form->{id})->load; |
|
56 |
|
|
57 |
if (!$self->can_view_all && ($attachment->email_journal->sender_id != SL::DB::Manager::Emplyee->current->id)) { |
|
58 |
$::form->error(t8('You do not have permission to access this entry.')); |
|
59 |
} |
|
60 |
|
|
61 |
$self->send_file(\$attachment->content, name => $attachment->name, type => $attachment->mime_type); |
|
62 |
} |
|
63 |
|
|
64 |
# |
|
65 |
# filters |
|
66 |
# |
|
67 |
|
|
68 |
sub add_stylesheet { |
|
69 |
$::request->{layout}->use_stylesheet('email_journal.css'); |
|
70 |
} |
|
71 |
|
|
72 |
# |
|
73 |
# helpers |
|
74 |
# |
|
75 |
|
|
76 |
sub init_can_view_all { $::auth->assert('admin', 1) } |
|
77 |
|
|
78 |
sub init_models { |
|
79 |
my ($self) = @_; |
|
80 |
|
|
81 |
my @where; |
|
82 |
push @where, (sender_id => SL::DB::Manager::Employee->current->id) if !$self->can_view_all; |
|
83 |
|
|
84 |
SL::Controller::Helper::GetModels->new( |
|
85 |
controller => $self, |
|
86 |
query => \@where, |
|
87 |
with_objects => [ 'sender' ], |
|
88 |
sorted => { |
|
89 |
sender => t8('Sender'), |
|
90 |
from => t8('From'), |
|
91 |
recipients => t8('Recipients'), |
|
92 |
subject => t8('Subject'), |
|
93 |
sent_on => t8('Sent on'), |
|
94 |
status => t8('Status'), |
|
95 |
extended_status => t8('Extended status'), |
|
96 |
}, |
|
97 |
); |
|
98 |
} |
|
99 |
|
|
100 |
sub init_filter_summary { |
|
101 |
my ($self) = @_; |
|
102 |
|
|
103 |
my $filter = $::form->{filter} || {}; |
|
104 |
my @filters = ( |
|
105 |
[ "from:substr::ilike", $::locale->text('From') ], |
|
106 |
[ "recipients:substr::ilike", $::locale->text('Recipients') ], |
|
107 |
[ "sent_on:date::ge", $::locale->text('Sent on') . " " . $::locale->text('From Date') ], |
|
108 |
[ "sent_on:date::le", $::locale->text('Sent on') . " " . $::locale->text('To Date') ], |
|
109 |
); |
|
110 |
|
|
111 |
my @filter_strings = grep { $_ } |
|
112 |
map { $filter->{ $_->[0] } ? $_->[1] . ' ' . $filter->{ $_->[0] } : undef } |
|
113 |
@filters; |
|
114 |
|
|
115 |
my %status = ( |
|
116 |
failed => $::locale->text('failed'), |
|
117 |
ok => $::locale->text('succeeded'), |
|
118 |
); |
|
119 |
push @filter_strings, $status{ $filter->{'status:eq_ignore_empty'} } if $filter->{'status:eq_ignore_empty'}; |
|
120 |
|
|
121 |
return join ', ', @filter_strings; |
|
122 |
} |
|
123 |
|
|
124 |
1; |
SL/DB/EmailJournal.pm | ||
---|---|---|
4 | 4 |
|
5 | 5 |
use SL::DB::MetaSetup::EmailJournal; |
6 | 6 |
use SL::DB::Manager::EmailJournal; |
7 |
use SL::DB::Helper::AttrSorted; |
|
7 | 8 |
|
8 | 9 |
__PACKAGE__->meta->add_relationship( |
9 | 10 |
attachments => { |
... | ... | |
15 | 16 |
|
16 | 17 |
__PACKAGE__->meta->initialize; |
17 | 18 |
|
19 |
__PACKAGE__->attr_sorted('attachments'); |
|
20 |
|
|
18 | 21 |
1; |
SL/DB/Manager/EmailJournal.pm | ||
---|---|---|
4 | 4 |
|
5 | 5 |
use parent qw(SL::DB::Helper::Manager); |
6 | 6 |
|
7 |
use SL::DB::Helper::Paginated; |
|
8 |
use SL::DB::Helper::Sorted; |
|
9 |
|
|
7 | 10 |
sub object_class { 'SL::DB::EmailJournal' } |
8 | 11 |
|
9 | 12 |
__PACKAGE__->make_manager_methods; |
10 | 13 |
|
14 |
sub _sort_spec { |
|
15 |
return ( |
|
16 |
default => [ 'sent_on', 1 ], |
|
17 |
columns => { |
|
18 |
SIMPLE => 'ALL', |
|
19 |
sender => 'sender.name', |
|
20 |
}, |
|
21 |
); |
|
22 |
} |
|
23 |
|
|
11 | 24 |
1; |
css/email_journal.css | ||
---|---|---|
1 |
/* E-Mail-Journal */ |
|
2 |
.email_journal_details tbody pre { |
|
3 |
margin: 0px; |
|
4 |
} |
|
5 |
|
|
6 |
.email_journal_details tbody th { |
|
7 |
text-align: right; |
|
8 |
vertical-align: top; |
|
9 |
} |
|
10 |
|
|
11 |
.email_journal_details tbody td { |
|
12 |
vertical-align: top; |
|
13 |
} |
locale/de/all | ||
---|---|---|
302 | 302 |
'Attach PDF:' => 'PDF anhängen', |
303 | 303 |
'Attachment' => 'als Anhang', |
304 | 304 |
'Attachment name' => 'Name des Anhangs', |
305 |
'Attachments' => 'Dateianhänge', |
|
305 | 306 |
'Attempt to call an undefined sub named \'%s\'' => 'Es wurde versucht, eine nicht definierte Unterfunktion namens \'%s\' aufzurufen.', |
306 | 307 |
'Audit Control' => 'Bücherkontrolle', |
307 | 308 |
'Aug' => 'Aug', |
... | ... | |
1074 | 1075 |
'Editable' => 'Bearbeitbar', |
1075 | 1076 |
'Either there are no open invoices, or you have already initiated bank transfers with the open amounts for those that are still open.' => 'Entweder gibt es keine offenen Rechnungen, oder es wurden bereits Überweisungen über die offenen Beträge aller offenen Rechnungen erstellt.', |
1076 | 1077 |
'Element disabled' => 'Element deaktiviert', |
1078 |
'Email journal' => 'E-Mail-Journal', |
|
1077 | 1079 |
'Employee' => 'Bearbeiter', |
1078 | 1080 |
'Employee #1 saved!' => 'Benutzer #1 gespeichert!', |
1079 | 1081 |
'Employee (database ID)' => 'Bearbeiter (Datenbank-ID)', |
... | ... | |
1184 | 1186 |
'Export date to' => 'Exportdatum bis', |
1185 | 1187 |
'Extend automatically by n months' => 'Automatische Verlängerung um x Monate', |
1186 | 1188 |
'Extended' => 'Gesamt', |
1189 |
'Extended status' => 'Erweiterter Status', |
|
1187 | 1190 |
'Extension Of Time' => 'Dauerfristverlängerung', |
1188 | 1191 |
'Factor' => 'Faktor', |
1189 | 1192 |
'Factor missing!' => 'Der Faktor fehlt.', |
... | ... | |
1292 | 1295 |
'Hardcopy' => 'Seite drucken', |
1293 | 1296 |
'Has item type' => 'Hat Regeltypen', |
1294 | 1297 |
'Has serial number' => 'Hat eine Serienummer', |
1298 |
'Headers' => 'Kopfzeilen', |
|
1295 | 1299 |
'Heading' => 'Überschrift', |
1296 | 1300 |
'Help Template Variables' => 'Hilfe zu Dokumenten-Variablen', |
1297 | 1301 |
'Help on column names' => 'Hilfe zu Spaltennamen', |
... | ... | |
2125 | 2129 |
'Receipt, payment, reconciliation' => 'Zahlungseingang, Zahlungsausgang, Kontenabgleich', |
2126 | 2130 |
'Receipts' => 'Zahlungseingänge', |
2127 | 2131 |
'Receivables' => 'Forderungen', |
2132 |
'Recipients' => 'EmpfängerInnen', |
|
2128 | 2133 |
'Reconcile' => 'Abgleichen', |
2129 | 2134 |
'Reconciliation' => 'Kontenabgleich', |
2130 | 2135 |
'Reconciliation with bank' => 'Kontenabgleich mit Bank', |
... | ... | |
2344 | 2349 |
'Sellprice for price group \'#1\'' => 'Verkaufspreis für Preisgruppe \'#1\'', |
2345 | 2350 |
'Sellprice significant places' => 'Verkaufspreis: Nachkommastellen', |
2346 | 2351 |
'Semicolon' => 'Semikolon', |
2352 |
'Send PDF to support contract\'s contact person' => 'PDFs an Ansprechpersonen der Wartungsverträge schicken', |
|
2353 |
'Sender' => 'AbsenderIn', |
|
2354 |
'Sent on' => 'Verschickt am', |
|
2347 | 2355 |
'Sep' => 'Sep', |
2348 | 2356 |
'Separator' => 'Trennzeichen', |
2349 | 2357 |
'Separator chararacter' => 'Feldtrennzeichen', |
... | ... | |
2428 | 2436 |
'Since bin is not enforced in the parts data, please specify a bin where goods without a specified bin will be put.' => 'Da Lagerplätze kein Pflichtfeld sind, geben Sie bitte einen Lagerplatz an, in dem Waren ohne spezifizierten Lagerplatz eingelagert werden sollen.', |
2429 | 2437 |
'Single quotes' => 'Einfache Anführungszeichen', |
2430 | 2438 |
'Single values in item mode, cumulated values in invoice mode' => 'Einzelwerte im Artikelmodus, kumulierte Werte im Rechnungsmodus', |
2439 |
'Size' => 'Größe', |
|
2431 | 2440 |
'Sketch' => 'Skizze', |
2432 | 2441 |
'Skip' => 'Überspringen', |
2433 | 2442 |
'Skip entry' => 'Eintrag überspringen', |
... | ... | |
2874 | 2883 |
'There are invalid transactions in your database.' => 'Sie haben ungültige Buchungen in Ihrer Datenbank.', |
2875 | 2884 |
'There are invoices which could not be paid by bank transaction #1 (Account number: #2, bank code: #3)!' => 'Einige Rechnungen konnten nicht durch die Bankbewegung #1 (Kontonummer: #2, Bankleitzahl: #3) bezahlt werden!', |
2876 | 2885 |
'There are no entries in the background job history.' => 'Es gibt keine Einträge im Hintergrund-Job-Verlauf.', |
2886 |
'There are no entries that match the filter.' => 'Es gibt keine Einträge, auf die der Filter zutrifft.', |
|
2877 | 2887 |
'There are no items in stock.' => 'Dieser Artikel ist nicht eingelagert.', |
2878 | 2888 |
'There are no items on your TODO list at the moment.' => 'Ihre Aufgabenliste enthält momentan keine Einträge.', |
2879 | 2889 |
'There are several options you can handle this problem, please select one:' => 'Bitte wählen Sie eine der folgenden Optionen, um mit dem Problem umzugehen:', |
... | ... | |
3131 | 3141 |
'View background job execution result' => 'Verlauf der Hintergrund-Job-Ausführungen anzeigen', |
3132 | 3142 |
'View background job history' => 'Hintergrund-Job-Verlauf anzeigen', |
3133 | 3143 |
'View background jobs' => 'Hintergrund-Jobs anzeigen', |
3144 |
'View sent email' => 'Verschickte E-Mail anzeigen', |
|
3134 | 3145 |
'View warehouse content' => 'Lagerbestand ansehen', |
3135 | 3146 |
'View/edit all employees sales documents' => 'Bearbeiten/ansehen der Verkaufsdokumente aller Mitarbeiter', |
3136 | 3147 |
'Von Konto: ' => 'von Konto: ', |
... | ... | |
3196 | 3207 |
'You cannot create an invoice for delivery orders from different vendors.' => 'Sie können keine Rechnung aus Lieferscheinen von verschiedenen Lieferanten erstellen.', |
3197 | 3208 |
'You cannot modify individual assigments from additional articles to line items.' => 'Eine individuelle Zuordnung der zusätzlichen Artikel zu Positionen kann nicht vorgenommen werden.', |
3198 | 3209 |
'You cannot paste function blocks or sub function blocks if there is no section.' => 'Sie können keine Funktionsblöcke oder Unterfunktionsblöcke einfügen, wenn es noch keinen Abschnitt gibt.', |
3210 |
'You do not have permission to access this entry.' => 'Sie verfügen nicht über die Berechtigung, auf diesen Eintrag zuzugreifen.', |
|
3199 | 3211 |
'You do not have the permissions to access this function.' => 'Sie verfügen nicht über die notwendigen Rechte, um auf diese Funktion zuzugreifen.', |
3200 | 3212 |
'You have entered or selected the following shipping address for this customer:' => 'Sie haben die folgende Lieferadresse eingegeben oder ausgewählt:', |
3201 | 3213 |
'You have never worked with currencies.' => 'Sie haben noch nie mit Währungen gearbeitet.', |
menus/user/00-erp.yaml | ||
---|---|---|
966 | 966 |
module: fu.pl |
967 | 967 |
params: |
968 | 968 |
action: search |
969 |
- parent: productivity_reports |
|
970 |
id: productivity_reports_email_journal |
|
971 |
name: Email journal |
|
972 |
order: 200 |
|
973 |
module: controller.pl |
|
974 |
params: |
|
975 |
action: EmailJournal/list |
|
969 | 976 |
- id: system |
970 | 977 |
name: System |
971 | 978 |
icon: system |
templates/webpages/email_journal/_filter.html | ||
---|---|---|
1 |
[%- USE L %][%- USE LxERP %][%- USE HTML %] |
|
2 |
<form action="controller.pl" method="post"> |
|
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", [ [ "", "" ], [ "failed", LxERP.t8("failed") ], [ "ok", LxERP.t8("succeeded") ] ], default=filter.status_eq_ignore_empty) %]</td> |
|
30 |
</tr> |
|
31 |
</table> |
|
32 |
|
|
33 |
[% L.hidden_tag("action", "EmailJournal/dispatch") %] |
|
34 |
[% L.hidden_tag("sort_by", FORM.sort_by) %] |
|
35 |
[% L.hidden_tag("sort_dir", FORM.sort_dir) %] |
|
36 |
[% L.hidden_tag("page", FORM.page) %] |
|
37 |
[% L.submit_tag("action_list", LxERP.t8("Continue"))%] |
|
38 |
|
|
39 |
<a href="#" onClick="javascript:$('#filter_table input,#filter_table select').val("");">[% LxERP.t8("Reset") %]</a> |
|
40 |
|
|
41 |
</div> |
|
42 |
|
|
43 |
</form> |
templates/webpages/email_journal/list.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% 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("status") %]</th> |
|
26 |
<th>[% L.sortable_table_header("extended_status") %]</th> |
|
27 |
</tr> |
|
28 |
</thead> |
|
29 |
|
|
30 |
<tbody> |
|
31 |
[%- FOREACH entry = ENTRIES %] |
|
32 |
<tr class="listrow[% IF entry.status != 'ok' %]_error[% END %]" id="email_journal_id_[% entry.id %]"> |
|
33 |
[% IF SELF.can_view_all %] |
|
34 |
<td> |
|
35 |
[% IF entry.sender %] |
|
36 |
[% HTML.escape(entry.sender.name) %] |
|
37 |
[% ELSE %] |
|
38 |
[% LxERP.t8("kivitendo") %] |
|
39 |
[% END %] |
|
40 |
</td> |
|
41 |
[% END %] |
|
42 |
<td> |
|
43 |
<a href="[% SELF.url_for(action => 'show', id => entry.id, back_to => SELF.get_callback) %]"> |
|
44 |
[%- HTML.escape(entry.from) %] |
|
45 |
</a> |
|
46 |
</td> |
|
47 |
<td>[%- HTML.escape(entry.recipients) %]</td> |
|
48 |
<td> |
|
49 |
<a href="[% SELF.url_for(action => 'show', id => entry.id, back_to => SELF.get_callback) %]"> |
|
50 |
[%- HTML.escape(entry.subject) %] |
|
51 |
</a> |
|
52 |
</td> |
|
53 |
<td>[%- HTML.escape(entry.sent_on.to_lxoffice('precision' => 'second')) %]</td> |
|
54 |
<td> |
|
55 |
[%- IF entry.status == 'ok' %] |
|
56 |
[%- LxERP.t8('succeeded') %] |
|
57 |
[% ELSE %] |
|
58 |
[%- LxERP.t8('failed') %] |
|
59 |
[%- END %] |
|
60 |
</td> |
|
61 |
<td>[%- HTML.escape(entry.extended_status) %]</td> |
|
62 |
</tr> |
|
63 |
[%- END %] |
|
64 |
</tbody> |
|
65 |
</table> |
|
66 |
[%- END %] |
|
67 |
|
|
68 |
[% L.paginate_controls %] |
templates/webpages/email_journal/show.html | ||
---|---|---|
1 |
[% USE HTML %][% USE L %][% USE LxERP %] |
|
2 |
|
|
3 |
<h1>[% FORM.title %]</h1> |
|
4 |
|
|
5 |
[%- INCLUDE 'common/flash.html' %] |
|
6 |
|
|
7 |
<table id="email_journal_details" class="email_journal_details"> |
|
8 |
<tbody> |
|
9 |
<tr class="listrow"> |
|
10 |
<th>[%- LxERP.t8("From") %]</th> |
|
11 |
<td>[%- HTML.escape(SELF.entry.from) %]</td> |
|
12 |
</tr> |
|
13 |
|
|
14 |
<tr class="listrow"> |
|
15 |
<th>[%- LxERP.t8("Recipients") %]</th> |
|
16 |
<td>[%- HTML.escape(SELF.entry.recipients) %]</td> |
|
17 |
</tr> |
|
18 |
|
|
19 |
<tr class="listrow"> |
|
20 |
<th>[%- LxERP.t8("Subject") %]</th> |
|
21 |
<td>[%- HTML.escape(SELF.entry.subject) %]</td> |
|
22 |
</tr> |
|
23 |
|
|
24 |
<tr class="listrow"> |
|
25 |
<th>[%- LxERP.t8("Sent on") %]</th> |
|
26 |
<td>[%- HTML.escape(SELF.entry.sent_on.to_lxoffice("precision" => "second")) %]</td> |
|
27 |
</tr> |
|
28 |
|
|
29 |
<tr class="listrow"> |
|
30 |
<th>[%- LxERP.t8("Status") %]</th> |
|
31 |
<td> |
|
32 |
[%- IF SELF.entry.status == "ok" %] |
|
33 |
[%- LxERP.t8("succeeded") %] |
|
34 |
[%- ELSE %] |
|
35 |
[%- LxERP.t8("failed") %] |
|
36 |
[%- END %] |
|
37 |
</td> |
|
38 |
</tr> |
|
39 |
|
|
40 |
<tr class="listrow"> |
|
41 |
<th>[%- LxERP.t8("Extended status") %]</th> |
|
42 |
<td><pre>[%- HTML.escape(SELF.entry.extended_status) %]</pre></td> |
|
43 |
</tr> |
|
44 |
|
|
45 |
<tr class="listrow"> |
|
46 |
<th>[%- LxERP.t8("Headers") %]</th> |
|
47 |
<td><pre>[% HTML.escape(SELF.entry.headers) %]</pre></td> |
|
48 |
</tr> |
|
49 |
|
|
50 |
<tr class="listrow"> |
|
51 |
<th>[%- LxERP.t8("Body") %]</th> |
|
52 |
<td><pre>[% HTML.escape(SELF.entry.body) %]</pre></td> |
|
53 |
</tr> |
|
54 |
</table> |
|
55 |
|
|
56 |
[% SET attachments = SELF.entry.attachments_sorted %] |
|
57 |
[% IF attachments.size %] |
|
58 |
<h2>[% LxERP.t8("Attachments") %]</h2> |
|
59 |
|
|
60 |
<table id="email_journal_details" class="email_journal_details"> |
|
61 |
<thead> |
|
62 |
<tr> |
|
63 |
<th>[% LxERP.t8("Attachment name") %]</th> |
|
64 |
<th>[% LxERP.t8("MIME type") %]</th> |
|
65 |
<th>[% LxERP.t8("Size") %]</th> |
|
66 |
</tr> |
|
67 |
</thead> |
|
68 |
|
|
69 |
<tbody> |
|
70 |
[% FOREACH attachment = attachments %] |
|
71 |
<tr class="listrow"> |
|
72 |
<td>[% L.link(SELF.url_for(action="download_attachment", id=attachment.id), attachment.name) %]</td> |
|
73 |
<td>[% HTML.escape(attachment.mime_type) %]</td> |
|
74 |
<td>[% HTML.escape(LxERP.format_amount(attachment.content.length, 0)) %]</td> |
|
75 |
</tr> |
|
76 |
[% END %] |
|
77 |
</tbody> |
|
78 |
</table> |
|
79 |
[% END %] |
|
80 |
|
|
81 |
<p> |
|
82 |
<a href="[% back_to %]">[%- LxERP.t8("Back") %]</a> |
|
83 |
</p> |
Auch abrufbar als: Unified diff
E-Mail-Journal: Journal anzeigen, Eintrag anzeigen, Anhänge herunterladen