Improvements to custom designer

This commit is contained in:
Hillel Coren 2016-02-25 20:34:23 +02:00
parent edda64bd0e
commit 4a749d5868
20 changed files with 147 additions and 39 deletions

View File

@ -15,6 +15,7 @@ use Response;
use Request;
use App\Models\Affiliate;
use App\Models\License;
use App\Models\Invoice;
use App\Models\User;
use App\Models\Account;
use App\Models\Gateway;
@ -393,6 +394,21 @@ class AccountController extends BaseController
if ($section == ACCOUNT_CUSTOMIZE_DESIGN) {
$data['customDesign'] = ($account->custom_design && !$design) ? $account->custom_design : $design;
// sample invoice to help determine variables
$invoice = Invoice::scope()
->with('client', 'account')
->where('is_quote', '=', false)
->where('is_recurring', '=', false)
->first();
if ($invoice) {
$invoice->hidePrivateFields();
unset($invoice->account);
unset($invoice->invoice_items);
unset($invoice->client->contacts);
$data['sampleInvoice'] = $invoice;
}
}
return View::make("accounts.{$section}", $data);

View File

@ -439,7 +439,7 @@ class Account extends Eloquent
return $height;
}
public function createInvoice($entityType, $clientId = null)
public function createInvoice($entityType = ENTITY_INVOICE, $clientId = null)
{
$invoice = Invoice::createNew();

View File

@ -30833,6 +30833,11 @@ function truncate(str, length) {
return (str && str.length > length) ? (str.substr(0, length-1) + '...') : str;
}
// http://stackoverflow.com/questions/280634/endswith-in-javascript
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
// http://codeaid.net/javascript/convert-seconds-to-hours-minutes-and-seconds-%28javascript%29
function secondsToTime(secs)
{
@ -30865,6 +30870,11 @@ function toSnakeCase(str) {
return str.replace(/([A-Z])/g, function($1){return "_"+$1.toLowerCase();});
}
// https://coderwall.com/p/iprsng/convert-snake-case-to-camelcase
function snakeToCamel(s){
return s.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); });
}
function getDescendantProp(obj, desc) {
var arr = desc.split(".");
while(arr.length && (obj = obj[arr.shift()]));
@ -30873,6 +30883,7 @@ function getDescendantProp(obj, desc) {
function doubleDollarSign(str) {
if (!str) return '';
if (!str.replace) return str;
return str.replace(/\$/g, '\$\$\$');
}
@ -30906,6 +30917,29 @@ function loadImages(selector) {
});
}
// http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript
function prettyJson(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
match = snakeToCamel(match);
return '<span class="' + cls + '">' + match + '</span>';
});
}
var NINJA = NINJA || {};
NINJA.TEMPLATES = {
@ -31117,18 +31151,28 @@ NINJA.decodeJavascript = function(invoice, javascript)
}
// search/replace values
var regExp = new RegExp('"\\$[\\\w\\\.]*?Value"', 'g');
var regExp = new RegExp('"\\$[a-z][\\\w\\\.]*?[Value]?"', 'g');
var matches = javascript.match(regExp);
if (matches) {
for (var i=0; i<matches.length; i++) {
var match = matches[i];
field = match.substring(2, match.indexOf('Value'));
// reserved words
if (['"$none"', '"$firstAndLast"', '"$notFirstAndLastColumn"', '"$notFirst"', '"$amount"', '"$primaryColor"', '"$secondaryColor"'].indexOf(match) >= 0) {
continue;
}
// legacy style had 'Value' at the end
if (endsWith(match, 'Value"')) {
field = match.substring(2, match.indexOf('Value'));
} else {
field = match.substring(2, match.length - 1);
}
field = toSnakeCase(field);
var value = getDescendantProp(invoice, field) || ' ';
value = doubleDollarSign(value);
javascript = javascript.replace(match, '"'+value+'"');
}
}

View File

@ -209,18 +209,28 @@ NINJA.decodeJavascript = function(invoice, javascript)
}
// search/replace values
var regExp = new RegExp('"\\$[\\\w\\\.]*?Value"', 'g');
var regExp = new RegExp('"\\$[a-z][\\\w\\\.]*?[Value]?"', 'g');
var matches = javascript.match(regExp);
if (matches) {
for (var i=0; i<matches.length; i++) {
var match = matches[i];
field = match.substring(2, match.indexOf('Value'));
// reserved words
if (['"$none"', '"$firstAndLast"', '"$notFirstAndLastColumn"', '"$notFirst"', '"$amount"', '"$primaryColor"', '"$secondaryColor"'].indexOf(match) >= 0) {
continue;
}
// legacy style had 'Value' at the end
if (endsWith(match, 'Value"')) {
field = match.substring(2, match.indexOf('Value'));
} else {
field = match.substring(2, match.length - 1);
}
field = toSnakeCase(field);
var value = getDescendantProp(invoice, field) || ' ';
value = doubleDollarSign(value);
javascript = javascript.replace(match, '"'+value+'"');
}
}

View File

@ -961,6 +961,11 @@ function truncate(str, length) {
return (str && str.length > length) ? (str.substr(0, length-1) + '...') : str;
}
// http://stackoverflow.com/questions/280634/endswith-in-javascript
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
// http://codeaid.net/javascript/convert-seconds-to-hours-minutes-and-seconds-%28javascript%29
function secondsToTime(secs)
{
@ -993,6 +998,11 @@ function toSnakeCase(str) {
return str.replace(/([A-Z])/g, function($1){return "_"+$1.toLowerCase();});
}
// https://coderwall.com/p/iprsng/convert-snake-case-to-camelcase
function snakeToCamel(s){
return s.replace(/_([a-z])/g, function (g) { return g[1].toUpperCase(); });
}
function getDescendantProp(obj, desc) {
var arr = desc.split(".");
while(arr.length && (obj = obj[arr.shift()]));
@ -1001,6 +1011,7 @@ function getDescendantProp(obj, desc) {
function doubleDollarSign(str) {
if (!str) return '';
if (!str.replace) return str;
return str.replace(/\$/g, '\$\$\$');
}
@ -1033,3 +1044,27 @@ function loadImages(selector) {
$(item).attr('data-src', src);
});
}
// http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript
function prettyJson(json) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
match = snakeToCamel(match);
return '<span class="' + cls + '">' + match + '</span>';
});
}

View File

@ -747,8 +747,7 @@ return array(
'primary_user' => 'Primær bruger',
'help' => 'Hjælp',
'customize_help' => '<p>Vi bruger <a href="http://pdfmake.org/" target="_blank">pdfmake</a> til at definere faktura design felter. pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">legeplads</a> giver en god mulighed for at se biblioteket i aktion.</p>
<p>Du kan tilgå alle faktura felter ved at tilføje <code>Value</code> til slutningen. For eksempel viser <code>$invoiceNumberValue</code> fakturanummeret.</p>
<p>For at tilgå under indstillingerne ved hjælp af dot notation. For eksempel kan man for at vise klient navnet bruge <code>$client.nameValue</code>.</p>
<p>For at tilgå under indstillingerne ved hjælp af dot notation. For eksempel kan man for at vise klient navnet bruge <code>$client.name</code>.</p>
<p>Hvis du mangler svar nogen spørgsmål post et spørgsmål i vores <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Due Date',

View File

@ -747,8 +747,7 @@ return array(
'primary_user' => 'Primärer Benutzer',
'help' => 'Hilfe',
'customize_help' => '<p>Wir benutzen zur deklarativen Definition der Rechnungsdesigns <a href="http://pdfmake.org/" target="_blank">pdfmake</a>. Der pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> bietet Gelegenheit die Bibliothek in Aktion zu sehen.</p>
<p>Man kann jedes Rechnungsfeld nutzen, in dem man <code>Value</code> hinten anhängt. Zum Beispiel zeigt <code>$invoiceNumberValue</code> die Rechnungsnummer.</p>
<p>Mit der <i>dot notation</i> kann auf Kind-Eigenschaften zugegriffen werden. Für den Kundennamen kann man zum Beispiel <code>$client.nameValue</code> benutzen.</p>
<p>Mit der <i>dot notation</i> kann auf Kind-Eigenschaften zugegriffen werden. Für den Kundennamen kann man zum Beispiel <code>$client.name</code> benutzen.</p>
<p>Wenn du Hilfe brauchst schreibe uns gern im <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">Support Forum</a> (Englisch).</p>',
'invoice_due_date' => 'Fällig am',

View File

@ -655,8 +655,7 @@ $LANG = array(
'primary_user' => 'Primary User',
'help' => 'Help',
'customize_help' => '<p>We use <a href="http://pdfmake.org/" target="_blank">pdfmake</a> to define the invoice designs declaratively. The pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> provide\'s a great way to see the library in action.</p>
<p>You can access any invoice field by adding <code>Value</code> to the end. For example <code>$invoiceNumberValue</code> displays the invoice number.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.nameValue</code>.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.name</code>.</p>
<p>If you need help figuring something out post a question to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Due Date',
'quote_due_date' => 'Valid Until',

View File

@ -725,8 +725,7 @@ return array(
'primary_user' => 'Usuario Primario',
'help' => 'Ayuda',
'customize_help' => '<p>Nosotros usamos <a href="http://pdfmake.org/" target="_blank">pdfmake</a> para definir los diseños de las facturas de manera declarativa. El <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> de pdfmake es una excelente manera de ver a la librería en acción.</p>
<p>Puedes acceder cualquier campo de una factura agregando <code>Value</code> al final. Por ejemplo, <code>$invoiceNumberValue</code> muestra el número de factura.</p>
<p>Para acceder a una propiedad hija usando notación de punto.Por ejemplo, para mostrar el nombre de un cliente se puede usar <code>$client.nameValue</code>.</p>
<p>Para acceder a una propiedad hija usando notación de punto.Por ejemplo, para mostrar el nombre de un cliente se puede usar <code>$client.name</code>.</p>
<p>Si necesitas ayuda entendiendo algo puede preguntar en nuestro <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">foro de soporte</a>.</p>',
'invoice_due_date' => 'Fecha de Vencimiento',

View File

@ -746,8 +746,7 @@ return array(
'primary_user' => 'Usuario Principal',
'help' => 'Ayuda',
'customize_help' => '<p>We use <a href="http://pdfmake.org/" target="_blank">pdfmake</a> to define the invoice designs declaratively. The pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> provide\'s a great way to see the library in action.</p>
<p>You can access any invoice field by adding <code>Value</code> to the end. For example <code>$invoiceNumberValue</code> displays the invoice number.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.nameValue</code>.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.name</code>.</p>
<p>If you need help figuring something out post a question to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Fecha de Pago',

View File

@ -738,8 +738,7 @@ return array(
'primary_user' => 'Utilisateur principal',
'help' => 'Aide',
'customize_help' => '<p>Nous utilisons <a href="http://pdfmake.org/" target="_blank">pdfmake</a> pour définir le design des factures. Le <a href="http://pdfmake.org/playground.html" target="_blank">bac à sable<a> de pdfmake est une bonne façon de voir cette bibliothèque en action.</p>
<p>Vous pouvez accéder à n\'importe quel champ de facture en ajoutant <code>Value</code> à la fin. Par exemple <code>$invoiceNumberValue</code> affiche le numéro de facture.</p>
<p>Pour accéder à une propriété héritée avec la notation par point. Par exemple pour montrer le nom du client vous pouvez utiliser <code>$client.nameValue</code>.</p>
<p>Pour accéder à une propriété héritée avec la notation par point. Par exemple pour montrer le nom du client vous pouvez utiliser <code>$client.name</code>.</p>
<p>Si vous avez besoin d\'aide pour comprendre quelque chose envoyez une question à notre <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">forum de support</a>.</p>',
'invoice_due_date' => 'Date limite',

View File

@ -741,8 +741,7 @@ return array(
'primary_user' => 'Utilisateur principal',
'help' => 'Aide',
'customize_help' => '<p>Nous utilisons <a href="http://pdfmake.org/" target="_blank">pdfmake</a> pour définir le design des factures de façon déclarative. L\'<a href="http://pdfmake.org/playground.html" target="_blank">environnement</a> pdfmake permet de voir la librairie en action.</p>
<p>Vous pouvez accéder à n\'importe quel champ de facture en ajoutant <code>Value</code> à la fin. Par exemple <code>$invoiceNumberValue</code> affiche le numéro de facture.</p>
<p>Pour accéder à une propriété enfant en utilisant la notation par point. Par exemple <code>$client.nameValue</code>affiche le nom du client.</p>
<p>Pour accéder à une propriété enfant en utilisant la notation par point. Par exemple <code>$client.name</code>affiche le nom du client.</p>
<p>Si vous avez besoin d\'aide à cet effet, n\'hésitez pas à publier une question sur notre <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">forum d\'aide (en anglais)</a>.</p>',
'invoice_due_date' => 'Échéance',

View File

@ -743,8 +743,7 @@ return array(
'primary_user' => 'Primary User',
'help' => 'Help',
'customize_help' => '<p>We use <a href="http://pdfmake.org/" target="_blank">pdfmake</a> to define the invoice designs declaratively. The pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> provide\'s a great way to see the library in action.</p>
<p>You can access any invoice field by adding <code>Value</code> to the end. For example <code>$invoiceNumberValue</code> displays the invoice number.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.nameValue</code>.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.name</code>.</p>
<p>If you need help figuring something out post a question to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Due Date',

View File

@ -750,8 +750,7 @@ return array(
'primary_user' => 'Primary User',
'help' => 'Help',
'customize_help' => '<p>We use <a href="http://pdfmake.org/" target="_blank">pdfmake</a> to define the invoice designs declaratively. The pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> provide\'s a great way to see the library in action.</p>
<p>You can access any invoice field by adding <code>Value</code> to the end. For example <code>$invoiceNumberValue</code> displays the invoice number.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.nameValue</code>.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.name</code>.</p>
<p>If you need help figuring something out post a question to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Due Date',

View File

@ -746,8 +746,7 @@ return array(
'primary_user' => 'Hovedbruker',
'help' => 'Hjelp',
'customize_help' => '<p>Vi bruker <a href="http://pdfmake.org/" target="_blank">pdfmake</a> for å definere faktura designene deklarativt. Pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> gir en flott måte å se biblioteket i aksjon.</p>
<p>Du kan tilgang til hvilket som helst faktura felt ved å legge til <code>Value</code> i slutten. For eksempel <code>$invoiceNumberValue</code> viser faktura nummeret.</p>
<p>For å tilgang til et underelementet ved bruk av prikk notasjon. For eksempel for å vise klientens navn, kan du bruke <code>$client.nameValue</code>.</p>
<p>For å tilgang til et underelementet ved bruk av prikk notasjon. For eksempel for å vise klientens navn, kan du bruke <code>$client.name</code>.</p>
<p>Om du trenger hjelp til å finne ut noe, poster et spørsmål til vårt <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">brukerforum</a>.</p>',
'invoice_due_date' => 'Tidsfrist',

View File

@ -741,8 +741,7 @@ return array(
'primary_user' => 'Primaire gebruiker',
'help' => 'Help',
'customize_help' => '<p>We gebruiken <a href="http://pdfmake.org/" target="_blank">pdfmake</a> om de factuur ontwerpen declaratief te definieren. De pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> is een interessante manier om de library in actie te zien.</p>
<p>Je kan elk factuur veld gebruiken door <code>Veld</code> toe te voegen op het einde. Bijvoorbeeld <code>$invoiceNumberValue</code> toont de factuur nummer.</p>
<p>Gebruik dot notatie om een "kind eigenschap" te gebruiken. Bijvoorbeeld voor de klant naam te tonen gebruik je <code>$client.nameValue</code>.</p>
<p>Gebruik dot notatie om een "kind eigenschap" te gebruiken. Bijvoorbeeld voor de klant naam te tonen gebruik je <code>$client.name</code>.</p>
<p>Als je ergens hulp bij nodig hebt, post dan een vraag op ons <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Vervaldatum',

View File

@ -739,8 +739,7 @@ return array(
'primary_user' => 'Usuário Principal',
'help' => 'Ajuda',
'customize_help' => '<p>We use <a href="http://pdfmake.org/" target="_blank">pdfmake</a> to define the invoice designs declaratively. The pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> provide\'s a great way to see the library in action.</p>
<p>You can access any invoice field by adding <code>Value</code> to the end. For example <code>$invoiceNumberValue</code> displays the invoice number.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.nameValue</code>.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.name</code>.</p>
<p>If you need help figuring something out post a question to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Data de vencimento',

View File

@ -745,8 +745,7 @@ return array(
'primary_user' => 'Primary User',
'help' => 'Help',
'customize_help' => '<p>We use <a href="http://pdfmake.org/" target="_blank">pdfmake</a> to define the invoice designs declaratively. The pdfmake <a href="http://pdfmake.org/playground.html" target="_blank">playground</a> provide\'s a great way to see the library in action.</p>
<p>You can access any invoice field by adding <code>Value</code> to the end. For example <code>$invoiceNumberValue</code> displays the invoice number.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.nameValue</code>.</p>
<p>To access a child property using dot notation. For example to show the client name you could use <code>$client.name</code>.</p>
<p>If you need help figuring something out post a question to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>.</p>',
'invoice_due_date' => 'Due Date',

View File

@ -22,6 +22,14 @@
background: #FFFFFF !important;
}
/* http://stackoverflow.com/questions/4810841/how-can-i-pretty-print-json-using-javascript */
pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
.string { color: green; }
.number { color: darkorange; }
.boolean { color: blue; }
.null { color: magenta; }
.key { color: red; }
</style>
@stop
@ -140,8 +148,14 @@
target = target.substring(1); // strip leading #
loadEditor(target);
});
refreshPDF(true);
@if (isset($sampleInvoice) && $sampleInvoice)
var sample = {!! $sampleInvoice->toJSON() !!}
console.log(sample);
$('#sampleData').show().html(prettyJson(sample));
@endif
});
</script>
@ -206,6 +220,8 @@
<div class="panel-body" style="background-color: #fff">
{!! trans('texts.customize_help') !!}
<pre id="sampleData" style="display:none;height:200px;padding-top:16px;"></pre>
</div>
<div class="modal-footer" style="margin-top: 0px">

View File

@ -32,7 +32,7 @@
var NINJA = NINJA || {};
NINJA.fontSize = 9;
NINJA.isRegistered = {{ \Utils::isRegistered() ? 'true' : 'false' }};
window.onerror = function (errorMsg, url, lineNumber, column, error) {
if (errorMsg.indexOf('Script error.') > -1) {
return;