diff --git a/lib/NGCP/Panel/Controller/InvoiceTemplate.pm b/lib/NGCP/Panel/Controller/InvoiceTemplate.pm index 5cd2f1d8ac..5b2c0e3216 100644 --- a/lib/NGCP/Panel/Controller/InvoiceTemplate.pm +++ b/lib/NGCP/Panel/Controller/InvoiceTemplate.pm @@ -3,6 +3,7 @@ use Sipwise::Base; use namespace::sweep; BEGIN { extends 'Catalyst::Controller'; } +use NGCP::Panel::Utils::InvoiceTemplate; use NGCP::Panel::Form::Invoice::TemplateAdmin; use NGCP::Panel::Form::Invoice::TemplateReseller; @@ -260,7 +261,7 @@ sub edit_content :Chained('base') :PathPart('editcontent') :Args(0) { } sub get_content_ajax :Chained('base') :PathPart('editcontent/get/ajax') :Args(0) { - my ($self, $c, @args) = @_; + my ($self, $c) = @_; my $tmpl = $c->stash->{tmpl}; my $content; @@ -283,10 +284,59 @@ sub get_content_ajax :Chained('base') :PathPart('editcontent/get/ajax') :Args(0) } } + # some part of the chain doesn't like content being encoded as utf8 at that poing + # already; decode here, and umlauts etc will be fine througout the chain. + use utf8; + utf8::decode($content); + $c->response->content_type('text/html'); $c->response->body($content); } +sub set_content_ajax :Chained('base') :PathPart('editcontent/set/ajax') :Args(0) { + my ($self, $c, @args) = @_; + my $tmpl = $c->stash->{tmpl}; + + my $content = $c->request->body_parameters->{template}; + unless($content) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => 'empty svg file not allowed', + desc => $c->log('Attempted to save an empty invoice template'), + ); + return; + } + NGCP::Panel::Utils::InvoiceTemplate::sanitize_svg(\$content); + + try { + $tmpl->update({ + base64_saved => $content, + base64_previewed => undef, + }); + } catch($e) { + NGCP::Panel::Utils::Message->error( + c => $c, + error => $e, + desc => $c->loc('Failed to store invoice template'), + ); + return; + } + $c->flash(messages => [{type => 'success', text => $c->loc('Invoice template successfully saved')}]); + + $c->response->content_type('application/json'); + $c->response->body(''); + $c->detach($c->view('JSON')); +} + +sub messages_ajax :Chained('template_list') :PathPart('messages') :Args(0) { + my ($self, $c) = @_; + $c->stash( + messages => $c->flash->{messages}, + template => 'helpers/ajax_messages.tt', + ); + $c->detach($c->view('TT')); +} + diff --git a/lib/NGCP/Panel/Utils/InvoiceTemplate.pm b/lib/NGCP/Panel/Utils/InvoiceTemplate.pm index bfa2b1608d..85135ad3ab 100644 --- a/lib/NGCP/Panel/Utils/InvoiceTemplate.pm +++ b/lib/NGCP/Panel/Utils/InvoiceTemplate.pm @@ -9,20 +9,8 @@ use File::Temp qw/tempfile tempdir/; use File::Path qw/mkpath/; use XML::XPath; -sub getDefaultInvoiceTemplate{ - my (%in) = @_; - #in future may be we will store root default in Db too, but now it is convenient to edit template as file - my $result = $in{c}->view('SVG')->getTemplateContent($in{c}, 'invoice/invoice_template_'.$in{type}.'.tt'); - - #$in{c}->log->debug("result=$result;"); - - if( $result && exists $in{result} ){ - ${$in{result}} = $result; - } - return \$result; -} -sub convertSvg2Pdf{ - my($c,$svg_ref,$in,$out) = @_; +sub svg2pdf { + my ($c,$svg_ref,$in,$out) = @_; my $svg = $$svg_ref; my(@pages) = $svg=~/())/sig; no warnings 'uninitialized'; @@ -116,4 +104,21 @@ sub preprocessInvoiceTemplateSvg{ ##print "\n\n2.\n\n\n\nsvg=".$out->{tt_string_prepared}.";"; } -1; \ No newline at end of file +sub sanitize_svg { + my ($svg_ref) = @_; + + my $xp = XML::XPath->new($$svg_ref); + + my $s = $xp->find('//script'); + foreach my $node($s->get_nodelist) { + if($node->getAttribute('display')) { + $node->getParentNode->removeChild($node); + } + } + + $$svg_ref = ($xp->findnodes('/'))[0]->toString(); + return 1; +} + +1; +# vim: set tabstop=4 expandtab: diff --git a/share/static/js/invoice_template.js b/share/static/js/invoice_template.js index 51dc483da0..37c6d9c748 100644 --- a/share/static/js/invoice_template.js +++ b/share/static/js/invoice_template.js @@ -65,49 +65,18 @@ function fetchSvgToEditor( data ) { setSvgStringToEditor( httpResponse ); }); } -//public -function fetchInvoiceTemplateData( data, noshowform ){ - //params spec: tt_type=[svg|html]/tt_viewmode[parsed|raw]/tt_sourcestate[saved|previewed|default]/tt_output_type[svg|pdf|html|json|svgzip|pdfzip|htmlzip]/tt_id - //tt_output_type=svg really outputs text/html mimetype. But it will be couple of tags ( per page). - data.tt_output_type = 'json'; - var q = uriForAction( data, 'template' ); - //alert('fetchInvoiceTemplateData: q='+q+';'); + +function fetchInvoiceTemplateData(data) { + var q = uriForAction(data, 'template'); var queryObj = { url: q, - type: 'POST', + type: 'GET', }; - //if (!$.browser.msie) { - //msie prompts to save - queryObj.dataType = "json"; - //} - queryObj.contentType = 'application/x-www-form-urlencoded;charset=utf-8'; - //alert('QQQ'); - $.ajax( queryObj ).done( function( templatedata ){ - //alert(templatedata.aaData); - //alert(templatedata.aaData); - //if ($.browser.msie) { - //alert(templatedata); - //templatedata = jQuery.parseJSON(templatedata); - //alert(templatedata); - //} - if(templatedata && templatedata.aaData){ - if( templatedata.aaData.template ){ - setSvgStringToEditor( templatedata.aaData.template.raw ); - setSvgStringToPreview( templatedata.aaData.template.parsed, '', data ); - } -// $('#load_previewed_control').css('visibility', 'visible' ); -// $('#load_saved_control').css('visibility', 'visible' ); - if( templatedata.aaData.form ){ - $('form[name=template_editor]').loadJSON(templatedata.aaData.form); - //$('#load_previewed_control').css('display', 'inline' ); - $('#load_saved_control').css('display', 'inline' ); - } - if( !noshowform ){ - $('#template_editor_form').css('visibility','visible'); - } - } + $.ajax(queryObj).done(function(templatedata) { + setSvgStringToEditor(templatedata); }); } + function clearTemplateForm(data){ $('#template_editor_form').css('visibility','hidden'); //$('#load_previewed_control').css('display', 'none' ); @@ -118,6 +87,7 @@ function clearTemplateForm(data){ data.tt_sourcestate = 'default'; fetchInvoiceTemplateData(data, 1);//1 = no show form again, just clear it up to default state } + function savePreviewed( data, callback ){ var svgString = getSvgString(); var q = uriForAction( data, 'template_previewed' ); @@ -166,8 +136,6 @@ function savePreviewedAndShowParsed( data ){ function saveTemplate( data, callback ) { var svgString = getSvgString(); - data.tt_sourcestate='saved'; - data.tt_output_type = 'json'; var q = uriForAction( data, 'template_saved' ); q=formToUri(q); //alert('saveTemplate: q='+q+';'); diff --git a/share/templates/helpers/datatables_vars.tt b/share/templates/helpers/datatables_vars.tt deleted file mode 100644 index eb605c2cc3..0000000000 --- a/share/templates/helpers/datatables_vars.tt +++ /dev/null @@ -1,50 +0,0 @@ -[% USE JSON.Escape( pretty => 0 ) %] -[%- -#USE Dumper; - -#we can't use DEFAULT directive - it treats false the same as undefined, which doesn't allow to keep default filled values and switch them off by customization -MACRO clearHelper BLOCK; - FOREACH identifier in [ 'messages', 'length_change', 'dt_columns', 'close_target', 'create_flag', 'form_object', 'ajax_uri' ]; - helper.${identifier} = ''; - END; -END; -MACRO initHelper(var,value) BLOCK; -# Dumper.dump(helper); - identifier = "${helper.identifier}" _ "_" _ var; - UNLESS helper.${var}.defined; helper.${var} = helper.${var} || value || ${"${identifier}"} || ${var}; END; -END; -MACRO initDtColumns BLOCK; - FOR col in helper.dt_columns; - IF ! col.accessor; - col.accessor = col.name.replace('\.','_'); - END; - END; -END; -MACRO initHelperAuto BLOCK; - FOREACH identifier in [ 'messages', 'length_change', 'dt_columns', 'close_target', 'create_flag' ]; - initHelper(identifier); - END; - #; - initHelper('form_object',form); - initHelper('ajax_uri', c.uri_for( c.controller.action_for('ajax') )); - IF ! helper.ajax_uri.search('[\?&]dt_columns='); - initDtColumns(); - helper.dt_columns_json = helper.dt_columns.json() | url; - helper.ajax_uri = helper.ajax_uri _ '?dt_columns=' _ helper.dt_columns_json; - END; -END; - -IF !no_auto_helper; - clearHelper(); - initHelperAuto(); - #here we can generate couple of variants, selection of proper variant will be exact view responsibility - UNLESS c.user.read_only; - initHelper('dt_buttons',[ - { name = c.loc('Edit'), uri = "/${helper.identifier}'+full[\"id\"]+'/edit", class = 'btn-small btn-primary', icon = 'icon-edit' }, - ] ); - initHelper('top_buttons',[ - { name = c.loc("Create ${helper.name_single}"), uri = c.uri_for("/${helper.identifier}/create"), icon = 'icon-star' }, - ] ); - END; -END; --%] \ No newline at end of file diff --git a/share/templates/invoice/template.tt b/share/templates/invoice/template.tt index dc8da99354..c5f45ec733 100644 --- a/share/templates/invoice/template.tt +++ b/share/templates/invoice/template.tt @@ -4,19 +4,8 @@ write_access = 1; %] -[% PROCESS 'helpers/datatables_vars.tt' no_auto_helper = 1 -%] -[%PROCESS 'helpers/modal.tt' -%] -[% - mf_helper = { - ajax_load => 1, - ajax_list_refresh => 'template', - } -%] -[% modal_script( m = mf_helper ) %] - [% site_config.title = c.loc('Invoice template [_1]', tmpl.name ) -%] - @@ -32,9 +21,6 @@ -[% IF reseller.first.status != "active" -%] - [%messages.unshift( c.loc('Reseller is [_1]', reseller.first.status) ); %] -[% END -%]
[%PROCESS 'helpers/ajax_messages.tt' -%]
diff --git a/share/templates/invoice/template_editor_form.tt b/share/templates/invoice/template_editor_form.tt index 881901bb35..5a45291af8 100644 --- a/share/templates/invoice/template_editor_form.tt +++ b/share/templates/invoice/template_editor_form.tt @@ -1,4 +1,3 @@ -[%# USE FillInForm %]
- + + + [% c.loc('Save SVG')%] + + [% c.loc('Preview')%] + void(0);"> [% c.loc('Preview as PDF')%] + - [% c.loc('Discard Changes')%] - - - [% c.loc('Save template')%] + [% c.loc('Discard Changes')%] - -
- [% c.loc('Show template variables')%] + void(0);"> [% c.loc('Show Variables')%]