diff options
author | Mark Wells <mark@freeside.biz> | 2014-06-11 13:53:25 -0700 |
---|---|---|
committer | Mark Wells <mark@freeside.biz> | 2014-06-11 13:53:25 -0700 |
commit | c16ef0145a0049c3f20377e2c5076087e999cde0 (patch) | |
tree | 698c7c51c74e33ab84876b09e1253c85bf9774fe | |
parent | d2d137731f88b8a0d35294284ec3571f46bd18b5 (diff) |
display sent mail on customer notes page, and improve sent mail log UI, #29250
-rw-r--r-- | FS/FS/cust_msg.pm | 31 | ||||
-rw-r--r-- | httemplate/search/cust_msg.html | 12 | ||||
-rwxr-xr-x | httemplate/view/cust_main.cgi | 70 | ||||
-rwxr-xr-x | httemplate/view/cust_main/notes.html | 234 | ||||
-rw-r--r--[-rwxr-xr-x] | httemplate/view/cust_main/notes/attachments.html (renamed from httemplate/view/cust_main/attachments.html) | 6 | ||||
-rw-r--r-- | httemplate/view/cust_main/notes/notes.html | 168 | ||||
-rwxr-xr-x | httemplate/view/cust_msg.html | 86 | ||||
-rw-r--r-- | httemplate/view/cust_msg_part.html | 23 |
8 files changed, 384 insertions, 246 deletions
diff --git a/FS/FS/cust_msg.pm b/FS/FS/cust_msg.pm index 8d57a54..72f64b9 100644 --- a/FS/FS/cust_msg.pm +++ b/FS/FS/cust_msg.pm @@ -3,6 +3,7 @@ package FS::cust_msg; use strict; use base qw( FS::cust_main_Mixin FS::Record ); use FS::Record qw( qsearch qsearchs ); +use MIME::Parser; use vars qw( @statuses ); =head1 NAME @@ -149,6 +150,36 @@ sub check { $self->SUPER::check; } +=item entity + +Returns the complete message as a L<MIME::Entity>. + +=item parts + +Returns a list of the MIME parts contained in the message, as L<MIME::Entity> +objects. + +=cut + +sub entity { + my $self = shift; + if ( !exists($self->{entity}) ) { + my $parser = MIME::Parser->new; + my $output_dir = "$FS::UID::cache_dir/cache.$FS::UID::datasrc/mimeparts"; + mkdir($output_dir) unless -d $output_dir; + $parser->output_under($output_dir); + $self->{entity} = + $parser->parse_data( $self->header . "\n" . $self->body ); + } + $self->{entity}; +} + +sub parts { + my $self = shift; + # return only the parts with bodies, not the multipart containers + grep { $_->bodyhandle } $self->entity->parts_DFS; +} + =back =head1 SEE ALSO diff --git a/httemplate/search/cust_msg.html b/httemplate/search/cust_msg.html index 716addf..2b6f08e 100644 --- a/httemplate/search/cust_msg.html +++ b/httemplate/search/cust_msg.html @@ -1,6 +1,6 @@ <& 'elements/search.html', 'title' => $title, - 'name' => 'messages', + 'name_singular' => 'message', 'query' => $query, 'count_query' => $count_query, 'header' => [ @@ -24,6 +24,12 @@ 'status', sub { encode_entities($_[0]->error) }, ], + 'sort_fields' => [ '_date', + 'msgtype', + 'env_to', + 'status', + 'error', + ], 'align' => 'rllcl', 'links' => [ ], 'link_onclicks' => [ @@ -41,6 +47,7 @@ ], 'html_init' => $html_init, 'really_disable_download' => 1, + @_ &> <%init> #hmm... @@ -58,6 +65,9 @@ if ( $cgi->param('status') =~ /^(\w+)$/ ) { if ( $cgi->param('msgtype') =~ /^(\w+)$/ ) { push @where, "msgtype = '$1'"; } +if ( $cgi->param('custnum') =~ /^(\d+)$/ ) { + push @where, "custnum = $1"; +} my ($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, ''); push @where, "(_date >= $beginning AND _date <= $ending)"; diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 6f2bb80..782556b 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -185,79 +185,14 @@ function areyousure(href, message) { % if ( $view eq 'notes' || $view eq 'jumbo' ) { -%if ( $cust_main->comments =~ /[^\s\n\r]/ ) { -<BR><% mt('Comments') |h %> -<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %> -<TR> - <TD BGCOLOR="#ffffff"> - <PRE><% encode_entities($cust_main->comments) %></PRE> - </TD> -</TR> -</TABLE></TABLE> -<BR><BR> -% } -<A NAME="notes"> -% my $notecount = scalar($cust_main->notes(0)); -% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) { - -% unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) { - <BR> - <A NAME="cust_main_note"><FONT SIZE="+2"><% mt('Notes') |h %></FONT></A><BR> -% } - -% if ( $curuser->access_right('Add customer note') && -% ! $conf->exists('cust_main-disable_notes') -% ) { - - <& /elements/popup_link-cust_main.html, - 'label' => emt('Add customer note'), - 'action' => $p. 'edit/cust_main_note.cgi', - 'actionlabel' => emt('Enter customer note'), - 'cust_main' => $cust_main, - 'width' => 616, - 'height' => 538, #575 - &> - -% } - -<BR> - -<& cust_main/notes.html, 'custnum' => $cust_main->custnum &> - -% } -<BR> - -% if(! $conf->config('disable_cust_attachment') -% and $curuser->access_right('Add attachment')) { -<& /elements/popup_link-cust_main.html, - 'label' => emt('Attach file'), - 'action' => $p.'edit/cust_main_attach.cgi', - 'actionlabel' => emt('Upload file'), - 'cust_main' => $cust_main, - 'width' => 480, - 'height' => 296, -&> -% } -% if( $curuser->access_right('View attachments') ) { -<& cust_main/attachments.html, 'custnum' => $cust_main->custnum &> -% if ($cgi->param('show_deleted')) { -<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum . - ($view ? ";show=$view" : '') . '#notes' - %>"><I>(<% mt('Show active attachments') |h %>)</I></A> -% } -% elsif($curuser->access_right('View deleted attachments')) { -<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum . - ($view ? ";show=$view" : '') . ';show_deleted=1#notes' - %>"><I>(<% mt('Show deleted attachments') |h %>)</I></A> -% } -% } -<BR> +<& cust_main/notes.html, 'cust_main' => $cust_main &> % } % if ( $view eq 'jumbo' ) { <BR> % } + <BR> % if ( $view eq 'tickets' || $view eq 'jumbo' ) { @@ -339,6 +274,7 @@ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) { my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array $query =~ /^(\d+)$/; $custnum = $1; + $cgi->param('custnum', $1); } my $cust_main = qsearchs( { diff --git a/httemplate/view/cust_main/notes.html b/httemplate/view/cust_main/notes.html index 2de68ff..1cd6e09 100755 --- a/httemplate/view/cust_main/notes.html +++ b/httemplate/view/cust_main/notes.html @@ -1,143 +1,91 @@ -% if ( scalar(@notes) ) { - -<SCRIPT TYPE="text/javascript"> - - function display_notes_classnum(classnum){ - document.getElementById('notes_'+classnum).style.display = 'block'; - document.getElementById('notes_tablink_'+classnum).style.fontWeight = 'bold'; - - var divs = document.getElementsByTagName("div"); - var i; - for(i=0; i < divs.length; i++){ - var d = divs[i]; - if(d.id.length > 6 && d.id.substring(0,6) == 'notes_') { - if(divs[i].id != 'notes_'+classnum) { - divs[i].style.display = 'none'; - } - } - } - - var as = document.getElementsByTagName("a"); - for(i=0; i < as.length; i++){ - var a = as[i]; - if(a.id.length > 14 && a.id.substring(0,14) == 'notes_tablink_') { - if(as[i].id != 'notes_tablink_'+classnum) { - as[i].style.fontWeight = 'normal'; - } - } - } - } - -</SCRIPT> - - <& /elements/init_overlib.html &> - -% my $bgcolor1 = '#eeeeee'; -% my $bgcolor2 = '#ffffff'; -% my $bgcolor = ''; -% my $last_classnum = -1; -% my $skipheader = 0; -% my %classes = (); -% -% foreach my $note (@notes) { -% -% if ( $bgcolor eq $bgcolor1 ) { -% $bgcolor = $bgcolor2; -% } else { -% $bgcolor = $bgcolor1; -% } -% -% my $pop = popurl(3); -% my $notenum = $note->notenum; -% my $onclick = include( '/elements/popup_link_onclick.html', -% 'action' => popurl(2). -% 'edit/cust_main_note.cgi'. -% "?custnum=$custnum". -% ";notenum=$notenum", -% 'actionlabel' => emt('Edit customer note'), -% 'width' => 616, -% 'height' => 538, #575 -% 'frame' => 'top', -% ); -% my $clickjs = qq!onclick="$onclick"!; -% -% my $edit = ''; -% if ($curuser->access_right('Edit customer note') ) { -% my $delete_url = $fsurl.'misc/delete-note.html?'.$notenum; -% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>'. -% qq! <A HREF="$delete_url" !. -% qq! onclick="return confirm('Delete this note?')">!. -% '('.emt('delete').')</A>'; -% } -% -% if ( $last_classnum != $note->classnum && !$skipheader ) { -% my $tmp_classnum = $note->classnum ? $note->classnum : 0; -% $classes{$tmp_classnum} = $note->classname ne '' ? $note->classname -% : emt('Other'); -% if ( $last_classnum != -1 ) { - </TABLE> - </DIV> +% # Customer comments +% if ( $cust_main->comments =~ /[^\s\n\r]/ ) { +<BR><% mt('Comments') |h %> +<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %> +<TR> + <TD BGCOLOR="#ffffff"> + <PRE><% encode_entities($cust_main->comments) %></PRE> + </TD> +</TR> +</TABLE></TABLE> +<BR><BR> % } -% my $display = ($tmp_classnum == 0 || !$conf->exists('note-classes') -% || $conf->config('note-classes') < 2) -% ? 'block' : 'none'; - <DIV id="notes_<% $tmp_classnum %>" - style="display:<% $display %>" - > - <& /elements/table-grid.html &> - <TR> - <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH> -% if ( $conf->exists('cust_main_note-display_times') ) { - <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH> -% } - <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH> -% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) { - <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Class') |h %></TH> + +% # Notes, if any +<A NAME="notes"> +% my $notecount = scalar($cust_main->notes(0)); +% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) { + +% unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) { +<P> + <A NAME="cust_main_note"><FONT SIZE="+2"><% mt('Notes') |h %></FONT></A> +</P> + % } - <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Note') |h %></TH> -% if ($curuser->access_right('Edit customer note') ) { - <TH CLASS="grid" BGCOLOR="#cccccc"> </TH> + +% if ( $curuser->access_right('Add customer note') && +% ! $conf->exists('cust_main-disable_notes') +% ) { + + <& /elements/popup_link-cust_main.html, + 'label' => emt('Add customer note'), + 'action' => $p. 'edit/cust_main_note.cgi', + 'actionlabel' => emt('Enter customer note'), + 'cust_main' => $cust_main, + 'width' => 616, + 'height' => 538, #575 + &> + % } - </TR> -% $skipheader = (!$conf->exists('note-classes') || $conf->config('note-classes') < 2); -% $last_classnum = $note->classnum; +<BR> + +% # actually display notes +<& notes/notes.html, 'cust_main' => $cust_main &> +<BR> +% } # end of notes + +% # Attachments +% # XXX at some point move all of this into notes/attachments.html +% if( $curuser->access_right('View attachments') ) { +% # List attachments +<& notes/attachments.html, 'cust_main' => $cust_main &> +% # "Attach file" link +% if(! $conf->config('disable_cust_attachment') +% and $curuser->access_right('Add attachment')) { +<& /elements/popup_link-cust_main.html, + 'label' => emt('Attach file'), + 'action' => $p.'edit/cust_main_attach.cgi', + 'actionlabel' => emt('Upload file'), + 'cust_main' => $cust_main, + 'width' => 480, + 'height' => 296, +&> % } - <TR> - <% note_datestr($note,$conf,$bgcolor) %> - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> - <% $note->usernum ? $note->access_user->name : $note->otaker %> - </TD> -% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) { - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> - <% $note->classname %> - </TD> -% } - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> - <% $note->comments | defang %> - </TD> -% if($edit) { - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $edit %></TD> -% } - </TR> - -% } #end display notes - -</TABLE> -</DIV> - -% if ( $conf->exists('note-classes') && $conf->config('note-classes') == 2 ) { -% my($classnum,$classname); -<% mt('Show notes of class:') |h %> -% foreach my $classnum ( sort { $b <=> $a } (keys %classes) ) { - <A id="notes_tablink_<% $classnum %>" - HREF="javascript:display_notes_classnum(<% $classnum %>)" - style="font-weight: <% $classnum == 0 ? 'bold' : 'normal' %>" - ><% $classes{$classnum} %></A> -% } - <BR> +% if ($cgi->param('show_deleted')) { +<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum . + ($view ? ";show=$view" : '') . '#notes' + %>"><I>(<% mt('Show active attachments') |h %>)</I></A> +% } elsif($curuser->access_right('View deleted attachments')) { +<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum . + ($view ? ";show=$view" : '') . ';show_deleted=1#notes' + %>"><I>(<% mt('Show deleted attachments') |h %>)</I></A> +% } % } +<BR> +% if ( $curuser->access_right('View email logs') +% and FS::cust_msg->count("custnum = $custnum")) { +<BR> +% if (!$cgi->param('order_by')) { +% my $order_by = '_date'; +% $order_by .= ' DESC' if $curuser->option('history_order') eq 'newest'; +% $cgi->param('order_by', $order_by); +% } +<& /search/cust_msg.html, + nohtmlheader => 1, + html_init => mt('Mail sent to this customer: '), +&> % } <%init> @@ -148,23 +96,9 @@ my $curuser = $FS::CurrentUser::CurrentUser; my(%opt) = @_; -my $custnum = $opt{'custnum'}; - -my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} ); -die "Customer not found!" unless $cust_main; - -my (@notes) = $cust_main->notes($conf->exists('note-classes') && $conf->config('note-classes') == 2); - -#subroutines +my $cust_main = $opt{'cust_main'}; +my $custnum = $cust_main->custnum; -sub note_datestr { - my($note, $conf, $bgcolor) = @_ or return ''; - my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">}; - my $format = "$td%b %o, %Y</TD>"; - $format .= "$td%l:%M%P</TD>" - if $conf->exists('cust_main_note-display_times'); - ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g; - $strip; -} +my $view = $cgi->param('show') || $curuser->default_customer_view; </%init> diff --git a/httemplate/view/cust_main/attachments.html b/httemplate/view/cust_main/notes/attachments.html index d51d826..0c16835 100755..100644 --- a/httemplate/view/cust_main/attachments.html +++ b/httemplate/view/cust_main/notes/attachments.html @@ -113,10 +113,8 @@ my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" if !$curuser->access_right('View attachments'); my(%opt) = @_; -my $custnum = $opt{'custnum'}; - -my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} ); -die "Customer not found!" unless $cust_main; +my $cust_main = $opt{'cust_main'}; +my $custnum = $cust_main->custnum; my (@attachments) = qsearch('cust_attachment', {'custnum' => $custnum}); diff --git a/httemplate/view/cust_main/notes/notes.html b/httemplate/view/cust_main/notes/notes.html new file mode 100644 index 0000000..6a7a06a --- /dev/null +++ b/httemplate/view/cust_main/notes/notes.html @@ -0,0 +1,168 @@ +% if ( scalar(@notes) ) { + +<SCRIPT TYPE="text/javascript"> + + function display_notes_classnum(classnum){ + document.getElementById('notes_'+classnum).style.display = 'block'; + document.getElementById('notes_tablink_'+classnum).style.fontWeight = 'bold'; + + var divs = document.getElementsByTagName("div"); + var i; + for(i=0; i < divs.length; i++){ + var d = divs[i]; + if(d.id.length > 6 && d.id.substring(0,6) == 'notes_') { + if(divs[i].id != 'notes_'+classnum) { + divs[i].style.display = 'none'; + } + } + } + + var as = document.getElementsByTagName("a"); + for(i=0; i < as.length; i++){ + var a = as[i]; + if(a.id.length > 14 && a.id.substring(0,14) == 'notes_tablink_') { + if(as[i].id != 'notes_tablink_'+classnum) { + as[i].style.fontWeight = 'normal'; + } + } + } + } + +</SCRIPT> + + <& /elements/init_overlib.html &> + +% my $bgcolor1 = '#eeeeee'; +% my $bgcolor2 = '#ffffff'; +% my $bgcolor = ''; +% my $last_classnum = -1; +% my $skipheader = 0; +% my %classes = (); +% +% foreach my $note (@notes) { +% +% if ( $bgcolor eq $bgcolor1 ) { +% $bgcolor = $bgcolor2; +% } else { +% $bgcolor = $bgcolor1; +% } +% +% my $pop = popurl(3); +% my $notenum = $note->notenum; +% my $onclick = include( '/elements/popup_link_onclick.html', +% 'action' => popurl(2). +% 'edit/cust_main_note.cgi'. +% "?custnum=$custnum". +% ";notenum=$notenum", +% 'actionlabel' => emt('Edit customer note'), +% 'width' => 616, +% 'height' => 538, #575 +% 'frame' => 'top', +% ); +% my $clickjs = qq!onclick="$onclick"!; +% +% my $edit = ''; +% if ($curuser->access_right('Edit customer note') ) { +% my $delete_url = $fsurl.'misc/delete-note.html?'.$notenum; +% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>'. +% qq! <A HREF="$delete_url" !. +% qq! onclick="return confirm('Delete this note?')">!. +% '('.emt('delete').')</A>'; +% } +% +% if ( $last_classnum != $note->classnum && !$skipheader ) { +% my $tmp_classnum = $note->classnum ? $note->classnum : 0; +% $classes{$tmp_classnum} = $note->classname ne '' ? $note->classname +% : emt('Other'); +% if ( $last_classnum != -1 ) { + </TABLE> + </DIV> +% } +% my $display = ($tmp_classnum == 0 || !$conf->exists('note-classes') +% || $conf->config('note-classes') < 2) +% ? 'block' : 'none'; + <DIV id="notes_<% $tmp_classnum %>" + style="display:<% $display %>" + > + <& /elements/table-grid.html &> + <TR> + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH> +% if ( $conf->exists('cust_main_note-display_times') ) { + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH> +% } + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH> +% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) { + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Class') |h %></TH> +% } + <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Note') |h %></TH> +% if ($curuser->access_right('Edit customer note') ) { + <TH CLASS="grid" BGCOLOR="#cccccc"> </TH> +% } + </TR> +% $skipheader = (!$conf->exists('note-classes') || $conf->config('note-classes') < 2); +% $last_classnum = $note->classnum; +% } + + <TR> + <% note_datestr($note,$conf,$bgcolor) %> + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $note->usernum ? $note->access_user->name : $note->otaker %> + </TD> +% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) { + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $note->classname %> + </TD> +% } + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% $note->comments | defang %> + </TD> +% if($edit) { + <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $edit %></TD> +% } + </TR> + +% } #end display notes + +</TABLE> +</DIV> + +% if ( $conf->exists('note-classes') && $conf->config('note-classes') == 2 ) { +% my($classnum,$classname); +<% mt('Show notes of class:') |h %> +% foreach my $classnum ( sort { $b <=> $a } (keys %classes) ) { + <A id="notes_tablink_<% $classnum %>" + HREF="javascript:display_notes_classnum(<% $classnum %>)" + style="font-weight: <% $classnum == 0 ? 'bold' : 'normal' %>" + ><% $classes{$classnum} %></A> +% } + <BR> +% } + +% } +<%init> + +use HTML::Defang; + +my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; + +my(%opt) = @_; + +my $cust_main = $opt{'cust_main'}; +my $custnum = $cust_main->custnum; + +my (@notes) = $cust_main->notes($conf->exists('note-classes') && $conf->config('note-classes') == 2); + +#subroutines + +sub note_datestr { + my($note, $conf, $bgcolor) = @_ or return ''; + my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">}; + my $format = "$td%b %o, %Y</TD>"; + $format .= "$td%l:%M%P</TD>" + if $conf->exists('cust_main_note-display_times'); + ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g; + $strip; +} + +</%init> diff --git a/httemplate/view/cust_msg.html b/httemplate/view/cust_msg.html index 67ceef7..91a08eb 100755 --- a/httemplate/view/cust_msg.html +++ b/httemplate/view/cust_msg.html @@ -1,4 +1,16 @@ <& /elements/header-popup.html &> +<STYLE> +P.pre { + font-family: monospace; + height: auto; + width: auto; + display: block; + white-space: pre-wrap; + text-align: left; + border: 1px solid #7e0079 +} +</STYLE> + <TABLE> <TR><TD>From:</TD><TD><% $cust_msg->env_from %></TD></TR> <TR><TD>To:</TD><TD><% $env_to %></TD></TR> @@ -8,31 +20,35 @@ % if ( $cust_msg->error ) { <TR><TD>Error:</TD><TD><% encode_entities($cust_msg->error) %></TD></TR> % } -<TR><TD colspan=2> -<FORM name="myform"> -<SCRIPT type="text/javascript"> -function toggle_display(obj) { - document.getElementById('content-header').style.display = - (obj.value == 'header' ? 'block' : 'none'); - document.getElementById('content-body').style.display = - (obj.value == 'body' ? 'block' : 'none'); -} -</SCRIPT> -<INPUT type="radio" name="what_to_show" onchange="toggle_display(this)" value="header" checked> Header -<INPUT type="radio" name="what_to_show" onchange="toggle_display(this)" value="body"> Body -</FORM> -</TR> -<TR><TD colspan=2 style="text-align:left"> -<TEXTAREA id="content-header" style="font-family:monospace" -readonly=1 cols=80 rows=20> -<% encode_entities($cust_msg->header) %> -</TEXTAREA> -<TEXTAREA id="content-body" style="font-family:monospace;display:none" -readonly=1 cols=80 rows=20> -<% encode_entities($cust_msg->body) %> -</TEXTAREA> -</TD></TR> +<& /elements/menubar.html, + { 'newstyle' => 1, + 'url_base' => $cgi->self_url . ';part=', + 'selected' => $selected_index, + }, + map { $partnames[$_] => $_ } (0 .. scalar(@parts) - 1), +&> </TABLE> +<DIV STYLE="text-align:center"> +% if ( $selected_part->isa('MIME::Entity') ) { +% my $type = $selected_part->mime_type; +% if ( $type =~ /^text/ ) { +%#<TEXTAREA style="font-family:monospace" readonly=1 cols=80 rows=20> + <P CLASS="pre"><% encode_entities( $selected_part->bodyhandle->as_string ) %></P> +% } else { # show a download link +% my $url = $fsurl . "view/cust_msg_part.html?$custmsgnum+$selected_index"; + <A HREF="<% $url %>"> + <DIV STYLE="display: inline-block; padding: 4px; border: 2px solid #00c"> +% if ( $type =~ /^image\/\w+$/ ) { + <IMG SRC="<% $url %>"> +% } else { + <FONT SIZE="+1">Download <% $partnames[$selected_index] %></FONT> +% } + </A> +% } +% } elsif ($selected_part->isa('MIME::Head')) { + <P CLASS="pre"><% encode_entities( $cust_msg->header ) %></P> +% } +</DIV> <& /elements/footer.html &> <%init> @@ -52,4 +68,26 @@ my %label = ( 'failed' => 'Attempted: ', 'prepared' => 'Not sent', ); + +my $partname = sub { + my %friendly_name = ( 'text/plain' => 'Text', 'text/html' => 'HTML' ); + my $part = shift; + $part->head->recommended_filename + || $friendly_name{$part->mime_type} + || $part->mime_type; +}; + +my @parts = $cust_msg->parts; +my @partnames = map { &{$partname}($_) } @parts; +push @parts, $cust_msg->entity->head; +push @partnames, mt('Header'); + +my $selected_part; +my $selected_index = 0; +if ( $cgi->param('part') =~ /^(\d+)$/ ) { + $selected_index = $1 if $1 < scalar(@parts); +} +$selected_part = $parts[$selected_index]; +$cgi->delete('part'); # for self_url + </%init> diff --git a/httemplate/view/cust_msg_part.html b/httemplate/view/cust_msg_part.html new file mode 100644 index 0000000..0be5705 --- /dev/null +++ b/httemplate/view/cust_msg_part.html @@ -0,0 +1,23 @@ +<%init> +die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('View email logs'); +# invoke this as "view/cust_msg_part.html?$custmsgnum+$partnum" +my ($custmsgnum, $partnum) = $cgi->keywords; +$custmsgnum =~ /^\d+$/ or die "bad custmsgnum"; +$partnum =~ /^\d+$/ or die "bad partnum"; +my $cust_msg = FS::cust_msg->by_key($custmsgnum) + or die "message not found"; +my $part = ($cust_msg->parts)[$partnum] + or die "message part $partnum does not exist"; + +my $filename = $part->head->recommended_filename; +if (!$filename) { + # for lack of a better idea + $part->bodyhandle->{MB_Path} =~ /.*\/(.*)/; + $filename = $1; +} + +$m->clear_buffer; +$r->content_type($part->mime_type || 'application/octet-stream'); +$r->headers_out->add('Content-Disposition' => 'attachment;filename=' . $filename); +$m->print($part->bodyhandle->as_string); +</%init> |