MT#5879 Loading of template data to form and to server in progress. Other left: confirm on deletion )href is not used, would be good to implement using datatables at least for invoice data, and use dynamic invoice data for online generation.

svg-edit: would be very nice to implement editing of rows amount and text in text boxes, and as a very  cool feature - applying styles. But next step will be cron.
ipeshinskaya/InvoiceTemplate5
Irina Peshinskaya 12 years ago committed by Victor Seva
parent 174367338b
commit bc0ce4bee0

@ -826,7 +826,7 @@ sub invoice_data :Chained('base') :PathPart('invoice') :CaptureArgs(0) {
stime => $stime,
etime => $etime,
);
#FAKE FAKE FAKE FAKE
#TODO: FAKE FAKE FAKE FAKE
$invoice_details = [$invoice_details->all()];
my $i = 1;
$invoice_details = [map{[$i++,$_]} (@$invoice_details) x 21];
@ -928,8 +928,7 @@ sub invoice_template :Chained('invoice_data') :PathPart('template') :Args {
$validator = NGCP::Panel::Form::Customer::InvoiceTemplate->new;
# $form->schema( $c->model('DB::InvoiceTemplate')->schema );
#to common form package ? removing is necessary due to FormHandler param presence evaluation - it is based on key presence, not on defined/not defined value
foreach ( keys %$in) { if(!( defined $in->{$_} )){ delete $in->{$_}; } };
$validator->remove_undef_in($in);
#really, we don't need a form here at all
#just use as already implemented fields checking and defaults applying
@ -1016,6 +1015,8 @@ sub invoice_template :Chained('invoice_data') :PathPart('template') :Args {
$c->response->content_type('application/pdf');
}elsif($in->{tt_output_type} eq 'html'){
$c->response->content_type('text/html');
}elsif($in->{tt_output_type} eq 'json'){
$c->response->content_type('application/json');
}elsif($in->{tt_output_type}=~m'zip'){
$c->response->content_type('application/zip');
}
@ -1035,32 +1036,43 @@ sub invoice_template :Chained('invoice_data') :PathPart('template') :Args {
#preShowInvoice
#even better - to template filters
#also to model
$out->{tt_string}=~s/(?:{\s*)?<!--{|}-->(?:\s*})?//gs;
$out->{tt_string}=~s/(<g .*?(id *=["' ]+(?:title|bg|mid)page["' ]+)?.*?)(?:display="none")(?(2)(?:.*?>)($2.*?>))/$1$3/gs;
$out->{tt_string_prepared}=$out->{tt_string_stored}=$out->{tt_string};
$out->{tt_string_prepared}=~s/(?:{\s*)?<!--{|}-->(?:\s*})?//gs;
$out->{tt_string_prepared}=~s/(<g .*?(id *=["' ]+(?:title|bg|mid)page["' ]+)?.*?)(?:display="none")(?(2)(?:.*?>)($2.*?>))/$1$3/gs;
}
if( ($in->{tt_output_type} eq 'svg') || ( $in->{tt_output_type} eq 'html') ){
#$c->response->content_type('image/svg+xml');
$c->stash( template => \$out->{tt_string} );
$c->stash( template => \$out->{tt_string_prepared} );
$c->detach( $c->view('SVG') );
}elsif($in->{tt_output_type} eq 'json'){
#method
$c->log->debug('prepare json');
my $aaData = {
template =>{
raw => $out->{tt_string},
parsed => $c->view('SVG')->getTemplateProcessed($c,\$out->{tt_string}, $c->stash ),
raw => $out->{tt_string_stored},
parsed => $c->view('SVG')->getTemplateProcessed($c, \$out->{tt_string_prepared}, $c->stash ),
},
form => {
};
#can be empty if we just load default
if($out->{tt_data}){
$aaData->{form} = {
tt_id => $out->{tt_data}->get_column('id'),
};
foreach(qw/name is_active/){
$aaData->{form}->{$_} = $out->{tt_data}->get_column($_);
}
};
foreach(qw/name is_active/){
$aaData->{form}->{$_} = $out->{tt_data}->get_column($_);
}else{
#if we didn't have tt_data - then we have empty form fields with applied defaults
$aaData->{form} = $in;
}
#$c->stash( aaData => $out );
$c->stash( aaData => $aaData );
$c->detach( $c->view('JSON') );
}elsif($in->{tt_output_type} eq 'pdf'){
#method
$c->response->content_type('application/pdf');
my $svg = $c->view('SVG')->getTemplateProcessed($c,\$out->{tt_string}, $c->stash );
my $svg = $c->view('SVG')->getTemplateProcessed($c,\$out->{tt_string_prepared}, $c->stash );
my(@pages) = $svg=~/(<svg.*?(?:\/svg>))/sig;
#$c->log->debug($svg);
@ -1111,10 +1123,10 @@ sub invoice_template :Chained('invoice_data') :PathPart('template') :Args {
open B, "$cmd |";
binmode B;
local $/ = undef;
$out->{tt_string} = <B>;
$out->{tt_string_pdf} = <B>;
close B;
}
$c->response->body($out->{tt_string});
$c->response->body($out->{tt_string_pdf});
return;
#$out->{tt_string} = `cat $filename `;
}

@ -5,8 +5,8 @@ extends 'NGCP::Panel::Form::ValidatorBase';
use Moose::Util::TypeConstraints;
enum 'TemplateType' => [ qw/svg html/ ];#html
enum 'TemplateTypeOutput' => [ qw/svg html pdf svgzip htmlzip pdfzip/ ];#html
enum 'TemplateViewMode' => [ qw/raw parsed/ ];
enum 'TemplateTypeOutput' => [ qw/svg html pdf json svgzip htmlzip pdfzip/ ];#html
enum 'TemplateViewMode' => [ qw/raw parsed both/ ];
enum 'TemplateSourceState' => [ qw/saved previewed default/ ];
#no Moose::Util::TypeConstraints;
@ -61,11 +61,23 @@ has_field 'contract_id' => (
);
has_field 'tt_id' => (
type => 'Text',
type => 'Hidden',
#default => \&
#apply => [ { check => \&validate_tt_string } ],
required => 0,
);
has_field 'name' => (
type => 'Text',
default => '',
#apply => [ { check => \&validate_tt_string } ],
required => 0,
);
has_field 'is_active' => (
type => 'Checkbox',
default => '0',
#apply => [ { check => \&validate_tt_string } ],
required => 0,
);
1;

@ -1,24 +1,39 @@
package NGCP::Panel::Model::DB::InvoiceTemplate;
use base NGCP::Panel::Model::DB::Base;
sub getCustomerInvoiceTemplate{
my $self = shift;
my (%params) = @_;
my ($contract_id,$tt_sourcestate,$tt_type,$tt_id) = @params{qw/contract_id tt_sourcestate tt_type tt_id/};
use irka;
use Data::Dumper;
my $result = '';
sub getDefaultConditions{
my $self = shift;
my ($params) = @_;
irka::loglong(Dumper($params));
my ($contract_id,$tt_sourcestate,$tt_type,$tt_id) = @$params{qw/contract_id tt_sourcestate tt_type tt_id/};
my $conditions = {};
irka::loglong("getDefaultConditions: tt_id=$tt_id;\n");
#my $tt_record = $self->resultset('invoice_template')->search({
if($tt_id){
$conditions = { id => $tt_id };
}else{
$conditions = {
reseller_id => $contract_id,
type => $tt_type,
is_active => 1,
type => $tt_type
};
}
return $conditions;
}
sub getCustomerInvoiceTemplate{
my $self = shift;
my (%params) = @_;
my ($contract_id,$tt_sourcestate,$tt_type,$tt_id) = @params{qw/contract_id tt_sourcestate tt_type tt_id/};
irka::loglong("getCustomerInvoiceTemplate: tt_id=$tt_id;\n");
irka::loglong(Dumper(\%params));
my $result = '';
my $conditions = $self->getDefaultConditions(\%params);
#my $tt_record = $self->resultset('invoice_template')->search({
my $tt_record = $self->schema->resultset('invoice_template')->search($conditions)->first;
#here may be base64 decoding
@ -31,13 +46,13 @@ sub getCustomerInvoiceTemplate{
if( $result && exists $params{result} ){
${$params{result}} = $result;
}
return ( $tt_id, \$result, $tt_record );#sgorila hata, gori i saray
return ( $tt_id, \$result, $tt_record );#tt_record - sgorila hata, gori i saray
}
sub storeCustomerInvoiceTemplate{
my $self = shift;
my (%params) = @_;
my ($contract_id,$tt_sourcestate,$tt_type, $tt_string, $tt_id) = @params{qw/contract_id tt_sourcestate tt_type tt_string_sanitized tt_id/};
my ($contract_id, $tt_sourcestate, $tt_type,$tt_string,$tt_id,$is_active,$name) = @params{qw/contract_id tt_sourcestate tt_type tt_string_sanitized tt_id is_active name/};
#my $tt_record = $self->resultset('invoice_template')->search({
$self->schema->txn_do(sub {
@ -49,11 +64,7 @@ sub storeCustomerInvoiceTemplate{
# 'base64_'.$tt_sourcestate => $$tt_string,
# });
my $tt_record = $self->schema->resultset('invoice_template')->search({
reseller_id => $contract_id,
type => $tt_type,
is_active => 1,
})->first;
#here may be base64 decoding
# $self->schema->resultset('ivoice_template')->search({
@ -63,22 +74,22 @@ sub storeCustomerInvoiceTemplate{
# is_active => 0,
# });
if( !$tt_record ){
if( !$tt_id ){
$self->schema->resultset('invoice_template')->create({
reseller_id => $contract_id,
type => $tt_type,
is_active => 1,
name => $name,
'base64_'.$tt_sourcestate => $$tt_string,
});
}else{
$self->schema->resultset('invoice_template')->update({
reseller_id => $contract_id,
type => $tt_type,
is_active => 1,
my $conditions = $self->getDefaultConditions(\%params);
my $tt_record = $self->schema->resultset('invoice_template')->search($conditions);
$tt_record->update({
is_active => $is_active,
name => $name,
'base64_'.$tt_sourcestate => $$tt_string,
id => $tt_record->get_column( 'id' ),
},
{ key => 'id' });
});
}
});
}

@ -92,7 +92,7 @@
<script src="/js/Theme.js"></script>
<script>
$(function () {
var mainWrapperInit = function () {
Theme.init ();
$('[rel="tooltip"]').tooltip({'html': false});
@ -199,7 +199,8 @@ $(function () {
}
});
}
});
};
$(mainWrapperInit);
</script>
</body>
[% # vim: set tabstop=4 syntax=html expandtab: -%]

@ -0,0 +1,168 @@
/*
* File: jquery.loadJSON.js
* Version: 1.0.0.
* Author: Jovan Popovic
*
* Copyright 2011 Jovan Popovic, all rights reserved.
*
* This source file is free software, under either the GPL v2 license or a
* BSD style license, as supplied with this software.
*
* This source file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* This file contains implementation of the JQuery templating engine that load JSON
* objects into the HTML code. It is based on Alexandre Caprais notemplate plugin
* with several enchancements that are added to this plugin.
*/
(function ($) {
$.fn.loadJSON = function (obj, options) {
function setElementValue(element, value, name) {
var type = element.type || element.tagName;
if (type == null)
return;
type = type.toLowerCase();
switch (type) {
case 'radio':
if (value.toString().toLowerCase() == element.value.toLowerCase())
$(element).attr("checked", "checked");
break;
case 'checkbox':
if (value)
$(element).attr("checked", "checked");
break;
case 'select-multiple':
var values = value.constructor == Array ? value : [value];
for (var i = 0; i < element.options.length; i++) {
for (var j = 0; j < values.length; j++) {
element.options[i].selected |= element.options[i].value == values[j];
}
}
break;
case 'select':
case 'select-one':
case 'text':
case 'hidden':
$(element).attr("value", value);
break;
case 'a':
var href = $(element).attr("href");
var iPosition = href.indexOf('?');
if (iPosition > 0) // if parameters in the URL exists add new pair using &
href = href.substring(0, iPosition) + '?' + name + '=' + value;
else//otherwise attach pair to URL
href = href + '?' + name + '=' + value;
$(element).attr("href", href);
break;
case 'img': //Assumption is that value is in the HREF$ALT format
var iPosition = value.indexOf('$');
var src = "";
var alt = "";
if (iPosition > 0) {
src = value.substring(0, iPosition);
alt = value.substring(iPosition + 1);
}
else {
src = value;
var iPositionStart = value.lastIndexOf('/')+1;
var iPositionEnd = value.indexOf('.');
alt = value.substring(iPositionStart, iPositionEnd);
}
$(element).attr("src", src);
$(element).attr("alt", alt);
break;
case 'textarea':
case 'submit':
case 'button':
default:
try {
$(element).html(value);
} catch (exc) { }
}
}
function browseJSON(obj, element, name) {
// no object
if (obj == undefined) {
}
// branch
else if (obj.constructor == Object) {
for (var prop in obj) {
if (prop == null)
continue;
//Find an element with class, id, name, or rel attribute that matches the propertu name
var child = jQuery.makeArray(jQuery("." + prop, element)).length > 0 ? jQuery("." + prop, element) :
jQuery("#" + prop, element).length > 0 ? jQuery("#" + prop, element) :
jQuery('[name="' + prop + '"]', element).length > 0 ? jQuery('[name="' + prop + '"]', element) : jQuery('[rel="' + prop + '"]');
if (child.length != 0)
browseJSON(obj[prop], jQuery(child, element), prop);
}
}
// array
else if (obj.constructor == Array) {
if (element.length > 0 && element[0].tagName == "SELECT") {
setElementValue(element[0], obj, name);
} else {
var arr = jQuery.makeArray(element);
//how many duplicate
var nbToCreate = obj.length - arr.length;
var i = 0;
for (iExist = 0; iExist < arr.length; iExist++) {
if (i < obj.length) {
$(element).eq(iExist).loadJSON(obj[i]);
}
i++;
}
//fill started by last
i = obj.length - 1;
for (iCreate = 0; iCreate < nbToCreate; iCreate++) {
//duplicate the last
$(arr[arr.length - 1]).clone(true).insertAfter(arr[arr.length - 1]).loadJSON(obj[i]);
i--;
}
}
}
// data only
else {
var value = obj;
var type;
if (element.length > 0) {
for (i = 0; i < element.length; i++)
setElementValue(element[i], obj, name);
}
else {
setElementValue(element, obj, name);
}
}
} //function browseJSON end
var defaults = {
};
properties = $.extend(defaults, options);
return this.each(function () {
if (obj.constructor == String) {
var element = $(this);
$.get(obj, function (data) {
element.loadJSON(data);
});
}
else {
browseJSON(obj, this);
}
});
};
})(jQuery);

@ -18,15 +18,16 @@
<script type="text/javascript" src="/js/libs/svg-edit/embedapi.js"></script>
<script type="text/javascript" src="/js/background.js"></script>
<script type="text/javascript" src="/js/jquery.loadJSON.js"></script>
<script type="text/javascript">
//constructor
var svgCanvasEmbed = null;
function init_embed() {
var svgEditFrameName = 'svgedit';
var frame = document.getElementById(svgEditFrameName);
svgCanvasEmbed = new EmbeddedSVGEdit(frame);
// Hide main button, as we will be controlling new/load/save etc from the host document
var doc;
doc = frame.contentDocument;
var doc = frame.contentDocument;
if (!doc)
{
doc = frame.contentWindow.document;
@ -34,15 +35,9 @@ function init_embed() {
//var mainButton = doc.getElementById('main_button');
//mainButton.style.display = 'none';
}
function setSvgStringToEditor( svgParsedString ){
svgCanvasEmbed.setSvgString( svgParsedString )(
function(data,error){
if(error){
}else{
svgCanvasEmbed.zoomChanged('', 'canvas');
}
}
);
//private
function getSvgString(){
return svgCanvasEmbed.frame.contentWindow.svgCanvas.getSvgString();
}
var uriForAction = function( data, type ){
//also we can think about getting URI's via ajax )
@ -54,7 +49,7 @@ var uriForAction = function( data, type ){
break;
case 'invoice_template_saved':
//q_template = '[%- c.uri_for_action("/customer/invoice_template", ['contract_id','svg','parsed','saved','svg','tt_id']) -%]';
q_template = '[%- c.uri_for_action("/customer/invoice_template", ["contract_id"]) -%]'+'/svg/parsed/previewed/svg/tt_id';
q_template = '[%- c.uri_for_action("/customer/invoice_template", ["contract_id"]) -%]'+'/svg/parsed/saved/svg/tt_id';
break;
case 'invoice_template_list':
q_template = '[%- c.uri_for_action("/customer/invoice_template_list", ['contract_id']) -%]';
@ -65,63 +60,54 @@ var uriForAction = function( data, type ){
q_template = '[%- c.uri_for_action("/customer/invoice_template", ["contract_id"]) -%]'+'/tt_type/tt_viewmode/tt_sourcestate/tt_output_type/tt_id';
break;
}
//alert('1.q_template='+q_template);
//alert('contract_id='+data.contract_id+';tt_id='+data.tt_id);
if(!data.tt_id){data.tt_id = '';}
if(!data.tt_type){data.tt_type = 'svg';}
if(!data.tt_output_type){data.tt_output_type = 'svg';}
if(!data.tt_viewmode){data.tt_viewmode = 'both';}
var params = ['contract_id','tt_id','tt_type','tt_output_type','tt_viewmode','tt_sourcestate'];
params.forEach(function(key){
q_template=q_template.replace(key,data[key]);
});
/*
q_template=q_template.replace('contract_id',data.contract_id);
q_template=q_template.replace('tt_id',data.tt_id);
q_template=q_template.replace('tt_type',data.tt_type);
q_template=q_template.replace('tt_output_type',data.tt_output_type);
q_template=q_template.replace('tt_viewmode',data.tt_viewmode);
q_template=q_template.replace('tt_sourcestate',data.tt_sourcestate);
*/
q_template=q_template.replace(/([^:])\/{2,}/g,'$1/');
q_template=q_template.replace(/\/+$/,'');
//alert('2.q_template='+q_template);
return q_template;
}
//function loadInvoiceTemplateData(params) {
//function loadInvoiceTemplateData(tt_type,tt_viewmode,tt_sourcestate,tt_output_type,tt_id,contract_id) {
function loadInvoiceTemplateData( data ){
//params spec: tt_type=[svg|html]/tt_viewmode[parsed|raw]/tt_sourcestate[default|previewed]/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 <svg> tags (<svg> per page).
var q = uriForAction( data, 'invoice_template' );
alert('loadInvoiceTemplateData: q='+q+';');
$.ajax({
url: q,
datatype: "json",
}).done(function(jsonres){
var templatedata = $.parseJson(res);
svgRawString = templatedata.template.raw;
setSvgStringToEditor( svgRawString );
});
}
function fetchSvgToEditor( data ) {
var q = uriForAction( data, 'invoice_template' );
//alert('fetchSvgToEditor: q='+q+';');
$.ajax({
url: q,
}).done( function ( httpResponse ){
setSvgStringToEditor( httpResponse );
} );
function setSvgStringToEditor( svgParsedString ){
alert('setSvgStringToEditor: '+svgParsedString);
svgCanvasEmbed.setSvgString( svgParsedString )(
function(data,error){
if(error){
}else{
svgCanvasEmbed.zoomChanged('', 'canvas');
}
}
);
}
var setSvgStringToPreview = function( svgParsedString, q ) {
function setSvgStringToPreview( svgParsedString, q, data ) {
var previewIframe = document.getElementById('svgpreview');
alert('setSvgStringToPreview: svgParsedString='+svgParsedString+';');
if ($.browser.msie) {
//we need to repeat query to server for msie if we don't want send template string via GET method
if(!q){
var dataPreview = data;
dataPreview.tt_viewmode = 'parsed';
dataPreview.tt_type = 'svg';
dataPreview.tt_sourcestate = dataPreview.tt_sourcestate || 'saved';
q = uriForAction( dataPreview, 'invoice_template' );
}
previewIframe.src = q;
}else{
previewIframe.src = "data:text/html," + encodeURIComponent(svgParsedString);
}
}
function fetchSvgToEditor( data ) {
var q = uriForAction( data, 'invoice_template' );
alert('fetchSvgToEditor: q='+q+';');
$.ajax({
url: q,
}).done( function ( httpResponse ){
setSvgStringToEditor( httpResponse );
});
}
function refreshTemplateList ( contract_id ){
fetch_into(
'collapse_invoice_template_list',
@ -130,28 +116,56 @@ function refreshTemplateList ( contract_id ){
function(){ mainWrapperInit(); }
);
}
function getSvgString(){
return svgCanvasEmbed.frame.contentWindow.svgCanvas.getSvgString();
//public
function fetchInvoiceTemplateData( data ){
//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 <svg> tags (<svg> per page).
data.tt_output_type = 'json';
var q = uriForAction( data, 'invoice_template' );
alert('fetchInvoiceTemplateData: q='+q+';');
$.ajax({
url: q,
datatype: "json",
//}).done( function( jsonres ){
}).done( function( templatedata ){
if(templatedata.aaData){
if( templatedata.aaData.template ){
setSvgStringToEditor( templatedata.aaData.template.raw );
setSvgStringToPreview( templatedata.aaData.template.parsed );
}
if( templatedata.aaData.form ){
$('form[name=invoice_template]').loadJSON(templatedata.aaData.form);
}
}
//can use some plugin for jquery like populate for more complex forms
/*
$.each(templatedata.aaData.form, function( key, value ){
var field = $('form[name=invoice_template] input[name='+key+']');
field.val(value);
});
*/
});
}
function savePreviewedAndShowParsed( data ){
var svgString = getSvgString();
var q = uriForAction( data, 'invoice_template_previewed' );
//alert('svgString='+svgString+'; q='+q+';');
//alert('savePreviewedAndShowParsed: svgString='+svgString+'; q='+q+';');
//alert('savePreviewedAndShowParsed: q='+q+';');
//save
$.post( q, { template: svgString } )
.done( function( httpResponse ){
// & show template
//alert('httpResponse='+httpResponse+';');
//alert('savePreviewedAndShowParsed: httpResponse='+httpResponse+';');
setSvgStringToPreview( httpResponse, q )
//refresh list after saving
refreshTemplateList( data.contract_id );
} );
}
function saveTemplate( contract_id, tt_id ) {
function saveTemplate( data ) {
var svgString = getSvgString();
data.tt_sourcestate='saved';
var q = uriForAction( data, 'invoice_template_saved' );
alert('saveTemplate: q='+q+';');
$.post( q, { template: encodeURIComponent( svgString ) })
.done( function( httpResponse ) {
refreshTemplateList( data.contract_id );
@ -251,9 +265,22 @@ function getTtIdVal(){
return $('form[name=invoice_template] input[name=tt_id]').val();
}
</script>
<form name="invoice_template" id="invoice_template" action="[%- c.uri_for_action('/customer/invoice_template', [contract.id]) -%]">
<form name="invoice_template" id="invoice_template" action="[%- c.uri_for_action('/customer/invoice_template', [contract.id]) -%]" class="form-horizontal" enctype="multipart/form-data" method="post">
<input type="hidden" name="tt_id" value="">
<div class="ngcp-separator"></div>
<div class="control-group">
<label class="control-label" for="name">[%c.loc('Template name')%]</label>
<div class="controls">
<input type="text" name="name" id="name" value="" />
</div>
</div>
<div class="ngcp-separator"></div>
<div class="control-group">
<label class="control-label" for="is_active">[%c.loc('Active')%]</label>
<div class="controls" class="checkbox">
<input type="checkbox" name="is_active" id="is_active" value="1" />
</div>
</div>
<span>
<a class="btn btn-primary btn-large" onclick="
savePreviewedAndShowParsed({
@ -262,9 +289,15 @@ function getTtIdVal(){
});void(0);">[% c.loc('Refresh Preview')%] <i class="icon-refresh"></i></a>
</span>
<span>
<a class="btn btn-primary btn-large" onclick="saveTemplate({contract_id:'[%contract.id%]',tt_id: $('form[name=invoice_template] input[name=tt_id]').val()});void(0);">[% c.loc('Save template')%] <i class="icon-disk"></i></a>
<a class="btn btn-primary btn-large" onclick="
alert('tt_id='+getTtIdVal()+';');
saveTemplate({
contract_id:'[%contract.id%]',
tt_id: getTtIdVal(),
});void(0);">[% c.loc('Save template')%] <i class="icon-disk"></i></a>
</span>
<div class="ngcp-separator"></div>
[%initial = 'default'%]
<iframe
type="text/html"

@ -8,8 +8,7 @@
<div class="accordion-inner" style="overflow:auto; height: 300px;">
[% IF write_access -%]
<span>
<a class="btn btn-primary btn-large" onclick="fetchSvgToEditor({
tt_viewmode: 'raw',
<a class="btn btn-primary btn-large" onclick="fetchInvoiceTemplateData({
tt_sourcestate: 'default',
contract_id: '[%contract.id%]',
});void(0);">[% c.loc('Create invoice template')%] <i class="icon-edit"></i></a>
@ -33,20 +32,29 @@
<tr class="sw_action_row">
<td>[% template.get_column('is_active') %]</td>
<td>[% template.get_column('type') %]</td>
<td>=[%- c.uri_for_action("/customer/invoice_template_delete", [contract.id, template.get_column('id')]) -%]= [%# template.get_column('name') %]</td>
<td>[% template.get_column('name') %]</td>
<td class="ngcp-actions-column">
<div class="sw_actions">
[% IF write_access -%]
[%IF template.get_column('base64_previewed')%]
<a class="btn btn-primary btn-small"
onclick="loadSvg('/svg/raw/previewed/svg/[%template.get_column('id')%]');void(0);">
onclick="fetchInvoiceTemplateData({
tt_sourcestate: 'previewed',
contract_id: '[%contract.id%]',
tt_id: '[%template.get_column('id')%]',
});">
<i class="icon-edit"></i> [% c.loc('Edit previewed') %]
</a>
[%END%]
[%IF template.get_column('base64_saved')%]
<a class="btn btn-small btn-primary"
onclick="loadSvg('/svg/raw/saved/svg/[%template.get_column('id')%]');void(0);">
onclick="fetchInvoiceTemplateData({
tt_sourcestate: 'saved',
contract_id: '[%contract.id%]',
tt_id: '[%template.get_column('id')%]',
});">
<i class="icon-edit"></i> [% c.loc('Edit saved') %]
</a>
[%END%]

Loading…
Cancel
Save