mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Bug fixes
This commit is contained in:
parent
dfd1ae502f
commit
6b063abe9a
@ -197,7 +197,7 @@ class CheckData extends Command {
|
|||||||
$activityFix = 0;
|
$activityFix = 0;
|
||||||
}
|
}
|
||||||
} else if ($activity->activity_type_id == ACTIVITY_TYPE_DELETE_PAYMENT) {
|
} else if ($activity->activity_type_id == ACTIVITY_TYPE_DELETE_PAYMENT) {
|
||||||
// **Fix for delting payment after deleting invoice**
|
// **Fix for deleting payment after deleting invoice**
|
||||||
if ($activity->adjustment != 0 && $invoice->is_deleted && $activity->created_at > $invoice->deleted_at) {
|
if ($activity->adjustment != 0 && $invoice->is_deleted && $activity->created_at > $invoice->deleted_at) {
|
||||||
$this->info("Incorrect adjustment for deleted payment adjustment:{$activity->adjustment}");
|
$this->info("Incorrect adjustment for deleted payment adjustment:{$activity->adjustment}");
|
||||||
$foundProblem = true;
|
$foundProblem = true;
|
||||||
|
@ -33,6 +33,7 @@ use App\Models\DateFormat;
|
|||||||
use App\Models\DatetimeFormat;
|
use App\Models\DatetimeFormat;
|
||||||
use App\Models\Language;
|
use App\Models\Language;
|
||||||
use App\Models\Size;
|
use App\Models\Size;
|
||||||
|
use App\Models\Gateway;
|
||||||
use App\Models\Timezone;
|
use App\Models\Timezone;
|
||||||
use App\Models\Industry;
|
use App\Models\Industry;
|
||||||
use App\Models\InvoiceDesign;
|
use App\Models\InvoiceDesign;
|
||||||
@ -150,7 +151,7 @@ class AccountController extends BaseController
|
|||||||
public function showSection($section = ACCOUNT_DETAILS, $subSection = false)
|
public function showSection($section = ACCOUNT_DETAILS, $subSection = false)
|
||||||
{
|
{
|
||||||
if ($section == ACCOUNT_DETAILS) {
|
if ($section == ACCOUNT_DETAILS) {
|
||||||
$primaryUser = Auth::user()->account->users()->orderBy('id')->first();
|
$primaryUser = Auth::user()->account->getPrimaryUser();
|
||||||
$data = [
|
$data = [
|
||||||
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
|
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
|
||||||
'countries' => Cache::get('countries'),
|
'countries' => Cache::get('countries'),
|
||||||
@ -177,7 +178,7 @@ class AccountController extends BaseController
|
|||||||
return Redirect::to('gateways/create');
|
return Redirect::to('gateways/create');
|
||||||
} else {
|
} else {
|
||||||
return View::make('accounts.payments', [
|
return View::make('accounts.payments', [
|
||||||
'showAdd' => $count < 3,
|
'showAdd' => $count < count(Gateway::$paymentTypes),
|
||||||
'title' => trans('texts.online_payments')
|
'title' => trans('texts.online_payments')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -251,11 +252,16 @@ class AccountController extends BaseController
|
|||||||
}
|
}
|
||||||
} else if ($subSection == ACCOUNT_TEMPLATES_AND_REMINDERS) {
|
} else if ($subSection == ACCOUNT_TEMPLATES_AND_REMINDERS) {
|
||||||
$data['templates'] = [];
|
$data['templates'] = [];
|
||||||
|
$data['defaultTemplates'] = [];
|
||||||
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
|
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
|
||||||
$data['templates'][$type] = [
|
$data['templates'][$type] = [
|
||||||
'subject' => $account->getEmailSubject($type),
|
'subject' => $account->getEmailSubject($type),
|
||||||
'template' => $account->getEmailTemplate($type),
|
'template' => $account->getEmailTemplate($type),
|
||||||
];
|
];
|
||||||
|
$data['defaultTemplates'][$type] = [
|
||||||
|
'subject' => $account->getDefaultEmailSubject($type),
|
||||||
|
'template' => $account->getDefaultEmailTemplate($type),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
$data['emailFooter'] = $account->getEmailFooter();
|
$data['emailFooter'] = $account->getEmailFooter();
|
||||||
$data['title'] = trans('texts.email_templates');
|
$data['title'] = trans('texts.email_templates');
|
||||||
@ -321,18 +327,22 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
|
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
|
||||||
$subjectField = "email_subject_{$type}";
|
$subjectField = "email_subject_{$type}";
|
||||||
$account->$subjectField = Input::get($subjectField, $account->getEmailSubject($type));
|
$subject = Input::get($subjectField, $account->getEmailSubject($type));
|
||||||
|
$account->$subjectField = ($subject == $account->getDefaultEmailSubject($type) ? null : $subject);
|
||||||
|
|
||||||
$bodyField = "email_template_{$type}";
|
$bodyField = "email_template_{$type}";
|
||||||
$account->$bodyField = Input::get($bodyField, $account->getEmailTemplate($type));
|
$body = Input::get($bodyField, $account->getEmailTemplate($type));
|
||||||
|
$account->$bodyField = ($body == $account->getDefaultEmailTemplate($type) ? null : $body);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ([REMINDER1, REMINDER2, REMINDER3] as $type) {
|
foreach ([REMINDER1, REMINDER2, REMINDER3] as $type) {
|
||||||
$enableField = "enable_{$type}";
|
$enableField = "enable_{$type}";
|
||||||
$account->$enableField = Input::get($enableField) ? true : false;
|
$account->$enableField = Input::get($enableField) ? true : false;
|
||||||
|
|
||||||
$numDaysField = "num_days_{$type}";
|
if ($account->$enableField) {
|
||||||
$account->$numDaysField = Input::get($numDaysField);
|
$numDaysField = "num_days_{$type}";
|
||||||
|
$account->$numDaysField = Input::get($numDaysField);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$account->save();
|
$account->save();
|
||||||
@ -716,6 +726,11 @@ class AccountController extends BaseController
|
|||||||
$user->username = trim(Input::get('email'));
|
$user->username = trim(Input::get('email'));
|
||||||
$user->email = trim(strtolower(Input::get('email')));
|
$user->email = trim(strtolower(Input::get('email')));
|
||||||
$user->phone = trim(Input::get('phone'));
|
$user->phone = trim(Input::get('phone'));
|
||||||
|
if (Utils::isNinja()) {
|
||||||
|
if (Input::get('referral_code')) {
|
||||||
|
$user->referral_code = $this->accountRepo->getReferralCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Utils::isNinjaDev()) {
|
if (Utils::isNinjaDev()) {
|
||||||
$user->dark_mode = Input::get('dark_mode') ? true : false;
|
$user->dark_mode = Input::get('dark_mode') ? true : false;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,13 @@ class HomeController extends BaseController
|
|||||||
Auth::logout();
|
Auth::logout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Track the referral/campaign code
|
||||||
|
foreach (['rc', 'utm_campaign'] as $code) {
|
||||||
|
if (Input::has($code)) {
|
||||||
|
Session::set(SESSION_REFERRAL_CODE, Input::get($code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
$redirectTo = Input::get('redirect_to', 'invoices/create');
|
$redirectTo = Input::get('redirect_to', 'invoices/create');
|
||||||
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
|
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
|
||||||
|
@ -356,6 +356,10 @@ class InvoiceController extends BaseController
|
|||||||
'lastSent' => $lastSent);
|
'lastSent' => $lastSent);
|
||||||
$data = array_merge($data, self::getViewModel());
|
$data = array_merge($data, self::getViewModel());
|
||||||
|
|
||||||
|
if ($clone) {
|
||||||
|
$data['formIsChanged'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the invitation link on the client's contacts
|
// Set the invitation link on the client's contacts
|
||||||
if (!$clone) {
|
if (!$clone) {
|
||||||
$clients = $data['clients'];
|
$clients = $data['clients'];
|
||||||
@ -526,9 +530,11 @@ class InvoiceController extends BaseController
|
|||||||
Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT, $url);
|
Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT, $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
$pdfUpload = Input::get('pdfupload');
|
if ($invoice->account->pdf_email_attachment) {
|
||||||
if (!empty($pdfUpload) && strpos($pdfUpload, 'data:application/pdf;base64,') === 0) {
|
$pdfUpload = Input::get('pdfupload');
|
||||||
$invoice->updateCachedPDF(Input::get('pdfupload'));
|
if (!empty($pdfUpload) && strpos($pdfUpload, 'data:application/pdf;base64,') === 0) {
|
||||||
|
$invoice->updateCachedPDF(Input::get('pdfupload'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($action == 'clone') {
|
if ($action == 'clone') {
|
||||||
|
@ -218,8 +218,12 @@ class PaymentController extends BaseController
|
|||||||
}
|
}
|
||||||
Session::put('payment_type', $paymentType);
|
Session::put('payment_type', $paymentType);
|
||||||
|
|
||||||
|
$accountGateway = $invoice->client->account->getGatewayByType($paymentType);
|
||||||
|
$gateway = $accountGateway->gateway;
|
||||||
|
$acceptedCreditCardTypes = $accountGateway->getCreditcardTypes();
|
||||||
|
|
||||||
// Handle offsite payments
|
// Handle offsite payments
|
||||||
if ($useToken || $paymentType != PAYMENT_TYPE_CREDIT_CARD) {
|
if ($useToken || $paymentType != PAYMENT_TYPE_CREDIT_CARD || $gateway->id == GATEWAY_EWAY) {
|
||||||
if (Session::has('error')) {
|
if (Session::has('error')) {
|
||||||
Session::reflash();
|
Session::reflash();
|
||||||
return Redirect::to('view/'.$invitationKey);
|
return Redirect::to('view/'.$invitationKey);
|
||||||
@ -228,10 +232,6 @@ class PaymentController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$accountGateway = $invoice->client->account->getGatewayByType($paymentType);
|
|
||||||
$gateway = $accountGateway->gateway;
|
|
||||||
$acceptedCreditCardTypes = $accountGateway->getCreditcardTypes();
|
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'showBreadcrumbs' => false,
|
'showBreadcrumbs' => false,
|
||||||
'url' => 'payment/'.$invitationKey,
|
'url' => 'payment/'.$invitationKey,
|
||||||
@ -327,7 +327,8 @@ class PaymentController extends BaseController
|
|||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
return Redirect::to('license')
|
return Redirect::to('license')
|
||||||
->withErrors($validator);
|
->withErrors($validator)
|
||||||
|
->withInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
$account = $this->accountRepo->getNinjaAccount();
|
$account = $this->accountRepo->getNinjaAccount();
|
||||||
@ -438,7 +439,6 @@ class PaymentController extends BaseController
|
|||||||
$validator = Validator::make(Input::all(), $rules);
|
$validator = Validator::make(Input::all(), $rules);
|
||||||
|
|
||||||
if ($validator->fails()) {
|
if ($validator->fails()) {
|
||||||
//Utils::logError('Payment Error [invalid]');
|
|
||||||
return Redirect::to('payment/'.$invitationKey)
|
return Redirect::to('payment/'.$invitationKey)
|
||||||
->withErrors($validator)
|
->withErrors($validator)
|
||||||
->withInput();
|
->withInput();
|
||||||
@ -456,8 +456,16 @@ class PaymentController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// For offsite payments send the client's details on file
|
||||||
|
// If we're using a token then we don't need to send any other data
|
||||||
|
if (!$onSite || $useToken) {
|
||||||
|
$data = false;
|
||||||
|
} else {
|
||||||
|
$data = Input::all();
|
||||||
|
}
|
||||||
|
|
||||||
$gateway = $this->paymentService->createGateway($accountGateway);
|
$gateway = $this->paymentService->createGateway($accountGateway);
|
||||||
$details = $this->paymentService->getPaymentDetails($invitation, ($useToken || !$onSite) ? false : Input::all());
|
$details = $this->paymentService->getPaymentDetails($invitation, $data);
|
||||||
|
|
||||||
// check if we're creating/using a billing token
|
// check if we're creating/using a billing token
|
||||||
if ($accountGateway->gateway_id == GATEWAY_STRIPE) {
|
if ($accountGateway->gateway_id == GATEWAY_STRIPE) {
|
||||||
@ -475,7 +483,13 @@ class PaymentController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$response = $gateway->purchase($details)->send();
|
$response = $gateway->purchase($details)->send();
|
||||||
$ref = $response->getTransactionReference();
|
|
||||||
|
if ($accountGateway->gateway_id == GATEWAY_EWAY) {
|
||||||
|
$ref = $response->getData()['AccessCode'];
|
||||||
|
$token = $response->getCardReference();
|
||||||
|
} else {
|
||||||
|
$ref = $response->getTransactionReference();
|
||||||
|
}
|
||||||
|
|
||||||
if (!$ref) {
|
if (!$ref) {
|
||||||
$this->error('No-Ref', $response->getMessage(), $accountGateway);
|
$this->error('No-Ref', $response->getMessage(), $accountGateway);
|
||||||
|
@ -385,28 +385,4 @@ class UserController extends BaseController
|
|||||||
return View::make('users.account_management');
|
return View::make('users.account_management');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function claimReferralCode($email)
|
|
||||||
{
|
|
||||||
$user = User::whereEmail($email)
|
|
||||||
->whereReferralCode(null)
|
|
||||||
->whereConfirmed(true)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if ($user) {
|
|
||||||
do {
|
|
||||||
$code = strtoupper(str_random(8));
|
|
||||||
$match = User::whereReferralCode($code)
|
|
||||||
->withTrashed()
|
|
||||||
->first();
|
|
||||||
} while ($match);
|
|
||||||
|
|
||||||
$user->referral_code = $code;
|
|
||||||
$user->save();
|
|
||||||
|
|
||||||
return $code;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Redirect::to('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,39 +37,6 @@ class StartupCheck
|
|||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check data has been cached
|
|
||||||
$cachedTables = [
|
|
||||||
'currencies' => 'App\Models\Currency',
|
|
||||||
'sizes' => 'App\Models\Size',
|
|
||||||
'industries' => 'App\Models\Industry',
|
|
||||||
'timezones' => 'App\Models\Timezone',
|
|
||||||
'dateFormats' => 'App\Models\DateFormat',
|
|
||||||
'datetimeFormats' => 'App\Models\DatetimeFormat',
|
|
||||||
'languages' => 'App\Models\Language',
|
|
||||||
'paymentTerms' => 'App\Models\PaymentTerm',
|
|
||||||
'paymentTypes' => 'App\Models\PaymentType',
|
|
||||||
'countries' => 'App\Models\Country',
|
|
||||||
'invoiceDesigns' => 'App\Models\InvoiceDesign',
|
|
||||||
];
|
|
||||||
if (Input::has('clear_cache')) {
|
|
||||||
Session::flash('message', 'Cache cleared');
|
|
||||||
}
|
|
||||||
foreach ($cachedTables as $name => $class) {
|
|
||||||
if (Input::has('clear_cache') || !Cache::has($name)) {
|
|
||||||
if ($name == 'paymentTerms') {
|
|
||||||
$orderBy = 'num_days';
|
|
||||||
} elseif (in_array($name, ['currencies', 'sizes', 'industries', 'languages', 'countries'])) {
|
|
||||||
$orderBy = 'name';
|
|
||||||
} else {
|
|
||||||
$orderBy = 'id';
|
|
||||||
}
|
|
||||||
$tableData = $class::orderBy($orderBy)->get();
|
|
||||||
if (count($tableData)) {
|
|
||||||
Cache::forever($name, $tableData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the application is up to date and for any news feed messages
|
// check the application is up to date and for any news feed messages
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
$count = Session::get(SESSION_COUNTER, 0);
|
$count = Session::get(SESSION_COUNTER, 0);
|
||||||
@ -122,11 +89,6 @@ class StartupCheck
|
|||||||
App::setLocale($locale);
|
App::setLocale($locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track the referral code
|
|
||||||
if (Input::has('rc')) {
|
|
||||||
Session::set(SESSION_REFERRAL_CODE, Input::get('rc'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure the account/user localization settings are in the session
|
// Make sure the account/user localization settings are in the session
|
||||||
if (Auth::check() && !Session::has(SESSION_TIMEZONE)) {
|
if (Auth::check() && !Session::has(SESSION_TIMEZONE)) {
|
||||||
Event::fire(new UserSettingsChanged());
|
Event::fire(new UserSettingsChanged());
|
||||||
@ -147,10 +109,11 @@ class StartupCheck
|
|||||||
$design = new InvoiceDesign();
|
$design = new InvoiceDesign();
|
||||||
$design->id = $item->id;
|
$design->id = $item->id;
|
||||||
$design->name = $item->name;
|
$design->name = $item->name;
|
||||||
$design->javascript = $item->javascript;
|
$design->pdfmake = $item->pdfmake;
|
||||||
$design->save();
|
$design->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cache::forget('invoiceDesigns');
|
||||||
Session::flash('message', trans('texts.bought_designs'));
|
Session::flash('message', trans('texts.bought_designs'));
|
||||||
}
|
}
|
||||||
} elseif ($productId == PRODUCT_WHITE_LABEL) {
|
} elseif ($productId == PRODUCT_WHITE_LABEL) {
|
||||||
@ -165,6 +128,40 @@ class StartupCheck
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check data has been cached
|
||||||
|
$cachedTables = [
|
||||||
|
'currencies' => 'App\Models\Currency',
|
||||||
|
'sizes' => 'App\Models\Size',
|
||||||
|
'industries' => 'App\Models\Industry',
|
||||||
|
'timezones' => 'App\Models\Timezone',
|
||||||
|
'dateFormats' => 'App\Models\DateFormat',
|
||||||
|
'datetimeFormats' => 'App\Models\DatetimeFormat',
|
||||||
|
'languages' => 'App\Models\Language',
|
||||||
|
'paymentTerms' => 'App\Models\PaymentTerm',
|
||||||
|
'paymentTypes' => 'App\Models\PaymentType',
|
||||||
|
'countries' => 'App\Models\Country',
|
||||||
|
'invoiceDesigns' => 'App\Models\InvoiceDesign',
|
||||||
|
];
|
||||||
|
if (Input::has('clear_cache')) {
|
||||||
|
Session::flash('message', 'Cache cleared');
|
||||||
|
}
|
||||||
|
foreach ($cachedTables as $name => $class) {
|
||||||
|
if (Input::has('clear_cache') || !Cache::has($name)) {
|
||||||
|
if ($name == 'paymentTerms') {
|
||||||
|
$orderBy = 'num_days';
|
||||||
|
} elseif (in_array($name, ['currencies', 'sizes', 'industries', 'languages', 'countries'])) {
|
||||||
|
$orderBy = 'name';
|
||||||
|
} else {
|
||||||
|
$orderBy = 'id';
|
||||||
|
}
|
||||||
|
$tableData = $class::orderBy($orderBy)->get();
|
||||||
|
if (count($tableData)) {
|
||||||
|
Cache::forever($name, $tableData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
|
if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
Session::flash('error', trans('texts.old_browser'));
|
Session::flash('error', trans('texts.old_browser'));
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ Route::get('terms', 'HomeController@showTerms');
|
|||||||
Route::get('log_error', 'HomeController@logError');
|
Route::get('log_error', 'HomeController@logError');
|
||||||
Route::get('invoice_now', 'HomeController@invoiceNow');
|
Route::get('invoice_now', 'HomeController@invoiceNow');
|
||||||
Route::get('keep_alive', 'HomeController@keepAlive');
|
Route::get('keep_alive', 'HomeController@keepAlive');
|
||||||
Route::get('referral_code/{email}', 'UserController@claimReferralCode');
|
|
||||||
Route::post('get_started', 'AccountController@getStarted');
|
Route::post('get_started', 'AccountController@getStarted');
|
||||||
|
|
||||||
// Client visible pages
|
// Client visible pages
|
||||||
@ -358,6 +357,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('PAYMENT_LIBRARY_PHP_PAYMENTS', 2);
|
define('PAYMENT_LIBRARY_PHP_PAYMENTS', 2);
|
||||||
|
|
||||||
define('GATEWAY_AUTHORIZE_NET', 1);
|
define('GATEWAY_AUTHORIZE_NET', 1);
|
||||||
|
define('GATEWAY_EWAY', 4);
|
||||||
define('GATEWAY_AUTHORIZE_NET_SIM', 2);
|
define('GATEWAY_AUTHORIZE_NET_SIM', 2);
|
||||||
define('GATEWAY_PAYPAL_EXPRESS', 17);
|
define('GATEWAY_PAYPAL_EXPRESS', 17);
|
||||||
define('GATEWAY_PAYPAL_PRO', 18);
|
define('GATEWAY_PAYPAL_PRO', 18);
|
||||||
@ -382,7 +382,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('NINJA_GATEWAY_CONFIG', 'NINJA_GATEWAY_CONFIG');
|
define('NINJA_GATEWAY_CONFIG', 'NINJA_GATEWAY_CONFIG');
|
||||||
define('NINJA_WEB_URL', 'https://www.invoiceninja.com');
|
define('NINJA_WEB_URL', 'https://www.invoiceninja.com');
|
||||||
define('NINJA_APP_URL', 'https://app.invoiceninja.com');
|
define('NINJA_APP_URL', 'https://app.invoiceninja.com');
|
||||||
define('NINJA_VERSION', '2.3.4');
|
define('NINJA_VERSION', '2.4.0');
|
||||||
define('NINJA_DATE', '2000-01-01');
|
define('NINJA_DATE', '2000-01-01');
|
||||||
|
|
||||||
define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com');
|
define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com');
|
||||||
@ -391,6 +391,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
|
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
|
||||||
define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html');
|
define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html');
|
||||||
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/');
|
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/');
|
||||||
|
define('REFERRAL_PROGRAM_URL', false);
|
||||||
|
|
||||||
define('COUNT_FREE_DESIGNS', 4);
|
define('COUNT_FREE_DESIGNS', 4);
|
||||||
define('COUNT_FREE_DESIGNS_SELF_HOST', 5); // include the custom design
|
define('COUNT_FREE_DESIGNS_SELF_HOST', 5); // include the custom design
|
||||||
|
@ -412,6 +412,15 @@ class Account extends Eloquent
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getDefaultEmailSubject($entityType)
|
||||||
|
{
|
||||||
|
if (strpos($entityType, 'reminder') !== false) {
|
||||||
|
$entityType = 'reminder';
|
||||||
|
}
|
||||||
|
|
||||||
|
return trans("texts.{$entityType}_subject", ['invoice' => '$invoice', 'account' => '$account']);
|
||||||
|
}
|
||||||
|
|
||||||
public function getEmailSubject($entityType)
|
public function getEmailSubject($entityType)
|
||||||
{
|
{
|
||||||
$field = "email_subject_{$entityType}";
|
$field = "email_subject_{$entityType}";
|
||||||
@ -421,22 +430,11 @@ class Account extends Eloquent
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strpos($entityType, 'reminder') !== false) {
|
return $this->getDefaultEmailSubject($entityType);
|
||||||
$entityType = 'reminder';
|
|
||||||
}
|
|
||||||
|
|
||||||
return trans("texts.{$entityType}_subject", ['invoice' => '$invoice', 'account' => '$account']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEmailTemplate($entityType, $message = false)
|
public function getDefaultEmailTemplate($entityType, $message = false)
|
||||||
{
|
{
|
||||||
$field = "email_template_{$entityType}";
|
|
||||||
$template = $this->$field;
|
|
||||||
|
|
||||||
if ($template) {
|
|
||||||
return $template;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strpos($entityType, 'reminder') >= 0) {
|
if (strpos($entityType, 'reminder') >= 0) {
|
||||||
$entityType = ENTITY_INVOICE;
|
$entityType = ENTITY_INVOICE;
|
||||||
}
|
}
|
||||||
@ -452,6 +450,18 @@ class Account extends Eloquent
|
|||||||
return $template . "\$footer";
|
return $template . "\$footer";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEmailTemplate($entityType, $message = false)
|
||||||
|
{
|
||||||
|
$field = "email_template_{$entityType}";
|
||||||
|
$template = $this->$field;
|
||||||
|
|
||||||
|
if ($template) {
|
||||||
|
return $template;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getDefaultEmailTemplate($entityType, $message);
|
||||||
|
}
|
||||||
|
|
||||||
public function getEmailFooter()
|
public function getEmailFooter()
|
||||||
{
|
{
|
||||||
if ($this->email_footer) {
|
if ($this->email_footer) {
|
||||||
|
@ -397,4 +397,16 @@ class AccountRepository
|
|||||||
{
|
{
|
||||||
return Account::whereRaw('enable_reminder1 = 1 OR enable_reminder2 = 1 OR enable_reminder3 = 1')->get();
|
return Account::whereRaw('enable_reminder1 = 1 OR enable_reminder2 = 1 OR enable_reminder3 = 1')->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getReferralCode()
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
$code = strtoupper(str_random(8));
|
||||||
|
$match = User::whereReferralCode($code)
|
||||||
|
->withTrashed()
|
||||||
|
->first();
|
||||||
|
} while ($match);
|
||||||
|
|
||||||
|
return $code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,16 +289,15 @@ class InvoiceRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($invoice->is_recurring) {
|
if ($invoice->is_recurring) {
|
||||||
|
if ($invoice->start_date && $invoice->start_date != Utils::toSqlDate($data['start_date'])) {
|
||||||
|
$invoice->last_sent_date = null;
|
||||||
|
}
|
||||||
|
|
||||||
$invoice->frequency_id = $data['frequency_id'] ? $data['frequency_id'] : 0;
|
$invoice->frequency_id = $data['frequency_id'] ? $data['frequency_id'] : 0;
|
||||||
$invoice->start_date = Utils::toSqlDate($data['start_date']);
|
$invoice->start_date = Utils::toSqlDate($data['start_date']);
|
||||||
$invoice->end_date = Utils::toSqlDate($data['end_date']);
|
$invoice->end_date = Utils::toSqlDate($data['end_date']);
|
||||||
$invoice->due_date = null;
|
$invoice->due_date = null;
|
||||||
$invoice->auto_bill = isset($data['auto_bill']) && $data['auto_bill'] ? true : false;
|
$invoice->auto_bill = isset($data['auto_bill']) && $data['auto_bill'] ? true : false;
|
||||||
|
|
||||||
if (isset($data['show_last_sent_date']) && $data['show_last_sent_date']
|
|
||||||
&& isset($data['last_sent_date']) && $data['last_sent_date']) {
|
|
||||||
$invoice->last_sent_date = Utils::toSqlDate($data['last_sent_date']);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$invoice->due_date = isset($data['due_date_sql']) ? $data['due_date_sql'] : Utils::toSqlDate($data['due_date']);
|
$invoice->due_date = isset($data['due_date_sql']) ? $data['due_date_sql'] : Utils::toSqlDate($data['due_date']);
|
||||||
$invoice->frequency_id = 0;
|
$invoice->frequency_id = 0;
|
||||||
|
@ -68,6 +68,8 @@ class TaskRepository
|
|||||||
$timeLog = [];
|
$timeLog = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array_multisort($timeLog);
|
||||||
|
|
||||||
if (isset($data['action'])) {
|
if (isset($data['action'])) {
|
||||||
if ($data['action'] == 'start') {
|
if ($data['action'] == 'start') {
|
||||||
$task->is_running = true;
|
$task->is_running = true;
|
||||||
|
@ -62,7 +62,7 @@ class PaymentService {
|
|||||||
} elseif (Session::get($key)) {
|
} elseif (Session::get($key)) {
|
||||||
$data = Session::get($key);
|
$data = Session::get($key);
|
||||||
} else {
|
} else {
|
||||||
$data = [];
|
$data = $this->createDataForClient($invitation);
|
||||||
}
|
}
|
||||||
|
|
||||||
$card = new CreditCard($data);
|
$card = new CreditCard($data);
|
||||||
@ -74,6 +74,8 @@ class PaymentService {
|
|||||||
'returnUrl' => URL::to('complete'),
|
'returnUrl' => URL::to('complete'),
|
||||||
'cancelUrl' => $invitation->getLink(),
|
'cancelUrl' => $invitation->getLink(),
|
||||||
'description' => trans('texts.' . $invoice->getEntityType()) . " {$invoice->invoice_number}",
|
'description' => trans('texts.' . $invoice->getEntityType()) . " {$invoice->invoice_number}",
|
||||||
|
'transactionId' => $invoice->invoice_number,
|
||||||
|
'transactionType' => 'Purchase',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +112,34 @@ class PaymentService {
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function createDataForClient($invitation)
|
||||||
|
{
|
||||||
|
$invoice = $invitation->invoice;
|
||||||
|
$client = $invoice->client;
|
||||||
|
$contact = $invitation->contact ?: $client->contacts()->first();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'email' => $contact->email,
|
||||||
|
'company' => $client->getDisplayName(),
|
||||||
|
'firstName' => $contact->first_name,
|
||||||
|
'lastName' => $contact->last_name,
|
||||||
|
'billingAddress1' => $client->address1,
|
||||||
|
'billingAddress2' => $client->address2,
|
||||||
|
'billingCity' => $client->city,
|
||||||
|
'billingPostcode' => $client->postal_code,
|
||||||
|
'billingState' => $client->state,
|
||||||
|
'billingCountry' => $client->country->iso_3166_2,
|
||||||
|
'billingPhone' => $contact->phone,
|
||||||
|
'shippingAddress1' => $client->address1,
|
||||||
|
'shippingAddress2' => $client->address2,
|
||||||
|
'shippingCity' => $client->city,
|
||||||
|
'shippingPostcode' => $client->postal_code,
|
||||||
|
'shippingState' => $client->state,
|
||||||
|
'shippingCountry' => $client->country->iso_3166_2,
|
||||||
|
'shippingPhone' => $contact->phone,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function createToken($gateway, $details, $accountGateway, $client, $contactId)
|
public function createToken($gateway, $details, $accountGateway, $client, $contactId)
|
||||||
{
|
{
|
||||||
$tokenResponse = $gateway->createCard($details)->send();
|
$tokenResponse = $gateway->createCard($details)->send();
|
||||||
|
@ -40,10 +40,15 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
['name' => 'Skrill', 'provider' => 'Skrill', 'payment_library_id' => 1],
|
['name' => 'Skrill', 'provider' => 'Skrill', 'payment_library_id' => 1],
|
||||||
['name' => 'BitPay', 'provider' => 'BitPay', 'payment_library_id' => 1],
|
['name' => 'BitPay', 'provider' => 'BitPay', 'payment_library_id' => 1],
|
||||||
['name' => 'Dwolla', 'provider' => 'Dwolla', 'payment_library_id' => 1],
|
['name' => 'Dwolla', 'provider' => 'Dwolla', 'payment_library_id' => 1],
|
||||||
|
['name' => 'Eway Rapid', 'provider' => 'Eway_RapidShared', 'payment_library_id' => 1],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($gateways as $gateway) {
|
foreach ($gateways as $gateway) {
|
||||||
if (!DB::table('gateways')->where('name', '=', $gateway['name'])->get()) {
|
$record = Gateway::where('name', '=', $gateway['name'])->first();
|
||||||
|
if ($record) {
|
||||||
|
$record->provider = $gateway['provider'];
|
||||||
|
$record->save();
|
||||||
|
} else {
|
||||||
Gateway::create($gateway);
|
Gateway::create($gateway);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +91,7 @@ class PaymentLibrariesSeeder extends Seeder
|
|||||||
['name' => 'Thai baht', 'code' => 'THB', 'symbol' => 'THB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Thai baht', 'code' => 'THB', 'symbol' => 'THB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => 'NGN ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => 'NGN ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
|
['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($currencies as $currency) {
|
foreach ($currencies as $currency) {
|
||||||
|
3
public/css/built.css
vendored
3
public/css/built.css
vendored
@ -2404,6 +2404,9 @@ margin-top: 0;
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
.form-control-static {
|
||||||
|
padding-top: 11px;
|
||||||
|
}
|
||||||
textarea.form-control {
|
textarea.form-control {
|
||||||
/*height: auto !important;*/
|
/*height: auto !important;*/
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
|
3
public/css/style.css
vendored
3
public/css/style.css
vendored
@ -54,6 +54,9 @@ margin-top: 0;
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
}
|
}
|
||||||
|
.form-control-static {
|
||||||
|
padding-top: 11px;
|
||||||
|
}
|
||||||
textarea.form-control {
|
textarea.form-control {
|
||||||
/*height: auto !important;*/
|
/*height: auto !important;*/
|
||||||
min-height: 40px;
|
min-height: 40px;
|
||||||
|
@ -31546,6 +31546,14 @@ function doubleDollarSign(str) {
|
|||||||
if (!str) return '';
|
if (!str) return '';
|
||||||
return str.replace(/\$/g, '\$\$\$');
|
return str.replace(/\$/g, '\$\$\$');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function truncate(string, length){
|
||||||
|
if (string.length > length) {
|
||||||
|
return string.substring(0, length) + '...';
|
||||||
|
} else {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
};
|
||||||
var NINJA = NINJA || {};
|
var NINJA = NINJA || {};
|
||||||
|
|
||||||
NINJA.TEMPLATES = {
|
NINJA.TEMPLATES = {
|
||||||
@ -31575,6 +31583,11 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
return function (i, node) {
|
return function (i, node) {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
} else if ((val+'').indexOf('$notFirstAndLastColumn') === 0) {
|
||||||
|
var parts = val.split(':');
|
||||||
|
return function (i, node) {
|
||||||
|
return (i === 0 || i === node.table.widths.length) ? 0 : parseFloat(parts[1]);
|
||||||
|
};
|
||||||
} else if ((val+'').indexOf('$notFirst') === 0) {
|
} else if ((val+'').indexOf('$notFirst') === 0) {
|
||||||
var parts = val.split(':');
|
var parts = val.split(':');
|
||||||
return function (i, node) {
|
return function (i, node) {
|
||||||
@ -31599,12 +31612,18 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
|
|
||||||
//console.log(javascript);
|
//console.log(javascript);
|
||||||
var dd = JSON.parse(javascript, jsonCallBack);
|
var dd = JSON.parse(javascript, jsonCallBack);
|
||||||
|
var designId = invoice.invoice_design_id;
|
||||||
if (!invoice.is_pro && dd.hasOwnProperty('footer') && dd.footer.hasOwnProperty('columns')) {
|
if (!invoice.is_pro) {
|
||||||
dd.footer.columns.push({image: logoImages.imageLogo1, alignment: 'right', width: 130})
|
if (designId == NINJA.TEMPLATES.CLEAN || designId == NINJA.TEMPLATES.NORMAL) {
|
||||||
|
dd.footer.columns.push({image: logoImages.imageLogo1, alignment: 'right', width: 130, margin: [0, 0, 0, 0]})
|
||||||
|
} else if (designId == NINJA.TEMPLATES.BOLD) {
|
||||||
|
dd.footer[1].columns.push({image: logoImages.imageLogo2, alignment: 'right', width: 130, margin: [0, -20, 20, 0]})
|
||||||
|
} else if (designId == NINJA.TEMPLATES.MODERN) {
|
||||||
|
dd.footer[1].columns[0].stack.push({image: logoImages.imageLogo3, alignment: 'left', width: 130, margin: [40, 6, 0, 0]});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(JSON.stringify(dd));
|
//console.log(JSON.stringify(dd.footer[1].columns));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
var fonts = {
|
var fonts = {
|
||||||
@ -31640,6 +31659,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
'invoiceLineItems': NINJA.invoiceLines(invoice),
|
'invoiceLineItems': NINJA.invoiceLines(invoice),
|
||||||
'invoiceLineItemColumns': NINJA.invoiceColumns(invoice),
|
'invoiceLineItemColumns': NINJA.invoiceColumns(invoice),
|
||||||
'quantityWidth': NINJA.quantityWidth(invoice),
|
'quantityWidth': NINJA.quantityWidth(invoice),
|
||||||
|
'taxWidth': NINJA.taxWidth(invoice),
|
||||||
'clientDetails': NINJA.clientDetails(invoice),
|
'clientDetails': NINJA.clientDetails(invoice),
|
||||||
'notesAndTerms': NINJA.notesAndTerms(invoice),
|
'notesAndTerms': NINJA.notesAndTerms(invoice),
|
||||||
'subtotals': NINJA.subtotals(invoice),
|
'subtotals': NINJA.subtotals(invoice),
|
||||||
@ -31647,7 +31667,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
'subtotalsWithoutBalance': NINJA.subtotals(invoice, true),
|
'subtotalsWithoutBalance': NINJA.subtotals(invoice, true),
|
||||||
'subtotalsBalance': NINJA.subtotalsBalance(invoice),
|
'subtotalsBalance': NINJA.subtotalsBalance(invoice),
|
||||||
'balanceDue': formatMoney(invoice.balance_amount, invoice.client.currency_id),
|
'balanceDue': formatMoney(invoice.balance_amount, invoice.client.currency_id),
|
||||||
'invoiceFooter': invoice.invoice_footer || ' ',
|
'invoiceFooter': NINJA.invoiceFooter(invoice),
|
||||||
'invoiceNumber': invoice.invoice_number || ' ',
|
'invoiceNumber': invoice.invoice_number || ' ',
|
||||||
'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice,
|
'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice,
|
||||||
'entityTypeUC': (invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice).toUpperCase(),
|
'entityTypeUC': (invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice).toUpperCase(),
|
||||||
@ -31658,7 +31678,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
|
|
||||||
for (var key in json) {
|
for (var key in json) {
|
||||||
// remove trailing commas for these fields
|
// remove trailing commas for these fields
|
||||||
if (['quantityWidth'].indexOf(key) >= 0) {
|
if (['quantityWidth', 'taxWidth'].indexOf(key) >= 0) {
|
||||||
var regExp = new RegExp('"\\$'+key+'",', 'g');
|
var regExp = new RegExp('"\\$'+key+'",', 'g');
|
||||||
val = json[key];
|
val = json[key];
|
||||||
} else {
|
} else {
|
||||||
@ -31754,11 +31774,25 @@ NINJA.invoiceColumns = function(invoice)
|
|||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NINJA.invoiceFooter = function(invoice)
|
||||||
|
{
|
||||||
|
if (!invoice.is_pro && invoice.invoice_design_id == 3) {
|
||||||
|
return invoice.invoice_footer ? invoice.invoice_footer.substring(0, 200) : ' ';
|
||||||
|
} else {
|
||||||
|
return invoice.invoice_footer || ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NINJA.quantityWidth = function(invoice)
|
NINJA.quantityWidth = function(invoice)
|
||||||
{
|
{
|
||||||
return invoice.account.hide_quantity == '1' ? '' : '"14%", ';
|
return invoice.account.hide_quantity == '1' ? '' : '"14%", ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NINJA.taxWidth = function(invoice)
|
||||||
|
{
|
||||||
|
return invoice.account.show_item_taxes == '1' ? '"14%", ' : '';
|
||||||
|
}
|
||||||
|
|
||||||
NINJA.invoiceLines = function(invoice) {
|
NINJA.invoiceLines = function(invoice) {
|
||||||
var total = 0;
|
var total = 0;
|
||||||
var shownItem = false;
|
var shownItem = false;
|
||||||
|
@ -27,6 +27,11 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
return function (i, node) {
|
return function (i, node) {
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
} else if ((val+'').indexOf('$notFirstAndLastColumn') === 0) {
|
||||||
|
var parts = val.split(':');
|
||||||
|
return function (i, node) {
|
||||||
|
return (i === 0 || i === node.table.widths.length) ? 0 : parseFloat(parts[1]);
|
||||||
|
};
|
||||||
} else if ((val+'').indexOf('$notFirst') === 0) {
|
} else if ((val+'').indexOf('$notFirst') === 0) {
|
||||||
var parts = val.split(':');
|
var parts = val.split(':');
|
||||||
return function (i, node) {
|
return function (i, node) {
|
||||||
@ -51,12 +56,18 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
|
|
||||||
//console.log(javascript);
|
//console.log(javascript);
|
||||||
var dd = JSON.parse(javascript, jsonCallBack);
|
var dd = JSON.parse(javascript, jsonCallBack);
|
||||||
|
var designId = invoice.invoice_design_id;
|
||||||
if (!invoice.is_pro && dd.hasOwnProperty('footer') && dd.footer.hasOwnProperty('columns')) {
|
if (!invoice.is_pro) {
|
||||||
dd.footer.columns.push({image: logoImages.imageLogo1, alignment: 'right', width: 130})
|
if (designId == NINJA.TEMPLATES.CLEAN || designId == NINJA.TEMPLATES.NORMAL) {
|
||||||
|
dd.footer.columns.push({image: logoImages.imageLogo1, alignment: 'right', width: 130, margin: [0, 0, 0, 0]})
|
||||||
|
} else if (designId == NINJA.TEMPLATES.BOLD) {
|
||||||
|
dd.footer[1].columns.push({image: logoImages.imageLogo2, alignment: 'right', width: 130, margin: [0, -20, 20, 0]})
|
||||||
|
} else if (designId == NINJA.TEMPLATES.MODERN) {
|
||||||
|
dd.footer[1].columns[0].stack.push({image: logoImages.imageLogo3, alignment: 'left', width: 130, margin: [40, 6, 0, 0]});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log(JSON.stringify(dd));
|
//console.log(JSON.stringify(dd.footer[1].columns));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
var fonts = {
|
var fonts = {
|
||||||
@ -92,6 +103,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
'invoiceLineItems': NINJA.invoiceLines(invoice),
|
'invoiceLineItems': NINJA.invoiceLines(invoice),
|
||||||
'invoiceLineItemColumns': NINJA.invoiceColumns(invoice),
|
'invoiceLineItemColumns': NINJA.invoiceColumns(invoice),
|
||||||
'quantityWidth': NINJA.quantityWidth(invoice),
|
'quantityWidth': NINJA.quantityWidth(invoice),
|
||||||
|
'taxWidth': NINJA.taxWidth(invoice),
|
||||||
'clientDetails': NINJA.clientDetails(invoice),
|
'clientDetails': NINJA.clientDetails(invoice),
|
||||||
'notesAndTerms': NINJA.notesAndTerms(invoice),
|
'notesAndTerms': NINJA.notesAndTerms(invoice),
|
||||||
'subtotals': NINJA.subtotals(invoice),
|
'subtotals': NINJA.subtotals(invoice),
|
||||||
@ -99,7 +111,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
'subtotalsWithoutBalance': NINJA.subtotals(invoice, true),
|
'subtotalsWithoutBalance': NINJA.subtotals(invoice, true),
|
||||||
'subtotalsBalance': NINJA.subtotalsBalance(invoice),
|
'subtotalsBalance': NINJA.subtotalsBalance(invoice),
|
||||||
'balanceDue': formatMoney(invoice.balance_amount, invoice.client.currency_id),
|
'balanceDue': formatMoney(invoice.balance_amount, invoice.client.currency_id),
|
||||||
'invoiceFooter': invoice.invoice_footer || ' ',
|
'invoiceFooter': NINJA.invoiceFooter(invoice),
|
||||||
'invoiceNumber': invoice.invoice_number || ' ',
|
'invoiceNumber': invoice.invoice_number || ' ',
|
||||||
'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice,
|
'entityType': invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice,
|
||||||
'entityTypeUC': (invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice).toUpperCase(),
|
'entityTypeUC': (invoice.is_quote ? invoiceLabels.quote : invoiceLabels.invoice).toUpperCase(),
|
||||||
@ -110,7 +122,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
|
|
||||||
for (var key in json) {
|
for (var key in json) {
|
||||||
// remove trailing commas for these fields
|
// remove trailing commas for these fields
|
||||||
if (['quantityWidth'].indexOf(key) >= 0) {
|
if (['quantityWidth', 'taxWidth'].indexOf(key) >= 0) {
|
||||||
var regExp = new RegExp('"\\$'+key+'",', 'g');
|
var regExp = new RegExp('"\\$'+key+'",', 'g');
|
||||||
val = json[key];
|
val = json[key];
|
||||||
} else {
|
} else {
|
||||||
@ -206,11 +218,25 @@ NINJA.invoiceColumns = function(invoice)
|
|||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NINJA.invoiceFooter = function(invoice)
|
||||||
|
{
|
||||||
|
if (!invoice.is_pro && invoice.invoice_design_id == 3) {
|
||||||
|
return invoice.invoice_footer ? invoice.invoice_footer.substring(0, 200) : ' ';
|
||||||
|
} else {
|
||||||
|
return invoice.invoice_footer || ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NINJA.quantityWidth = function(invoice)
|
NINJA.quantityWidth = function(invoice)
|
||||||
{
|
{
|
||||||
return invoice.account.hide_quantity == '1' ? '' : '"14%", ';
|
return invoice.account.hide_quantity == '1' ? '' : '"14%", ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NINJA.taxWidth = function(invoice)
|
||||||
|
{
|
||||||
|
return invoice.account.show_item_taxes == '1' ? '"14%", ' : '';
|
||||||
|
}
|
||||||
|
|
||||||
NINJA.invoiceLines = function(invoice) {
|
NINJA.invoiceLines = function(invoice) {
|
||||||
var total = 0;
|
var total = 0;
|
||||||
var shownItem = false;
|
var shownItem = false;
|
||||||
|
@ -1668,3 +1668,11 @@ function doubleDollarSign(str) {
|
|||||||
if (!str) return '';
|
if (!str) return '';
|
||||||
return str.replace(/\$/g, '\$\$\$');
|
return str.replace(/\$/g, '\$\$\$');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function truncate(string, length){
|
||||||
|
if (string.length > length) {
|
||||||
|
return string.substring(0, length) + '...';
|
||||||
|
} else {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
};
|
@ -185,7 +185,7 @@
|
|||||||
'users' => 'Brugere',
|
'users' => 'Brugere',
|
||||||
'localization' => 'Lokalisering',
|
'localization' => 'Lokalisering',
|
||||||
'remove_logo' => 'Fjern logo',
|
'remove_logo' => 'Fjern logo',
|
||||||
'logo_help' => 'Understøttede filtyper: JPEG, GIF og PNG. Anbefalet størrelse: 200px bredde og 120px højde',
|
'logo_help' => 'Understøttede filtyper: JPEG, GIF og PNG',
|
||||||
'payment_gateway' => 'Betalingsløsning',
|
'payment_gateway' => 'Betalingsløsning',
|
||||||
'gateway_id' => 'Kort betalings udbyder',
|
'gateway_id' => 'Kort betalings udbyder',
|
||||||
'email_notifications' => 'Notifikation via e-mail',
|
'email_notifications' => 'Notifikation via e-mail',
|
||||||
@ -788,6 +788,9 @@
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Benutzer',
|
'users' => 'Benutzer',
|
||||||
'localization' => 'Lokalisierung',
|
'localization' => 'Lokalisierung',
|
||||||
'remove_logo' => 'Logo entfernen',
|
'remove_logo' => 'Logo entfernen',
|
||||||
'logo_help' => 'Unterstützt: JPEG, GIF und PNG. Empfohlene Höhe: 120px',
|
'logo_help' => 'Unterstützt: JPEG, GIF und PNG',
|
||||||
'payment_gateway' => 'Zahlungseingang',
|
'payment_gateway' => 'Zahlungseingang',
|
||||||
'gateway_id' => 'Provider',
|
'gateway_id' => 'Provider',
|
||||||
'email_notifications' => 'E-Mail Benachrichtigungen',
|
'email_notifications' => 'E-Mail Benachrichtigungen',
|
||||||
@ -787,6 +787,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Users',
|
'users' => 'Users',
|
||||||
'localization' => 'Localization',
|
'localization' => 'Localization',
|
||||||
'remove_logo' => 'Remove logo',
|
'remove_logo' => 'Remove logo',
|
||||||
'logo_help' => 'Supported: JPEG, GIF and PNG. Recommended size: 200px width by 120px height',
|
'logo_help' => 'Supported: JPEG, GIF and PNG',
|
||||||
'payment_gateway' => 'Payment Gateway',
|
'payment_gateway' => 'Payment Gateway',
|
||||||
'gateway_id' => 'Gateway',
|
'gateway_id' => 'Gateway',
|
||||||
'email_notifications' => 'Email Notifications',
|
'email_notifications' => 'Email Notifications',
|
||||||
@ -672,7 +672,7 @@ return array(
|
|||||||
'counter' => 'Counter',
|
'counter' => 'Counter',
|
||||||
|
|
||||||
'payment_type_dwolla' => 'Dwolla',
|
'payment_type_dwolla' => 'Dwolla',
|
||||||
'gateway_help_43' => ':link to sign up for Dwolla.',
|
'gateway_help_43' => ':link to sign up for Dwolla.<br/>Note: remove dashes from the Destination/Dwolla Id',
|
||||||
'partial_value' => 'Must be greater than zero and less than the total',
|
'partial_value' => 'Must be greater than zero and less than the total',
|
||||||
'more_actions' => 'More Actions',
|
'more_actions' => 'More Actions',
|
||||||
|
|
||||||
@ -765,7 +765,7 @@ return array(
|
|||||||
'status_viewed' => 'Viewed',
|
'status_viewed' => 'Viewed',
|
||||||
'status_partial' => 'Partial',
|
'status_partial' => 'Partial',
|
||||||
'status_paid' => 'Paid',
|
'status_paid' => 'Paid',
|
||||||
'show_line_item_tax' => 'Display <b>line item taxes</b> inline',
|
'show_line_item_tax' => 'Display <b>line item taxes inline</b>',
|
||||||
|
|
||||||
'iframe_url' => 'Website',
|
'iframe_url' => 'Website',
|
||||||
'iframe_url_help1' => 'Copy the following code to a page on your site.',
|
'iframe_url_help1' => 'Copy the following code to a page on your site.',
|
||||||
@ -787,6 +787,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ return array(
|
|||||||
'users' => 'Usuarios',
|
'users' => 'Usuarios',
|
||||||
'localization' => 'Localización',
|
'localization' => 'Localización',
|
||||||
'remove_logo' => 'Eliminar logo',
|
'remove_logo' => 'Eliminar logo',
|
||||||
'logo_help' => 'Formatos aceptados: JPEG, GIF y PNG. Altura recomendada: 120px',
|
'logo_help' => 'Formatos aceptados: JPEG, GIF y PNG',
|
||||||
'payment_gateway' => 'Pasarela de pago',
|
'payment_gateway' => 'Pasarela de pago',
|
||||||
'gateway_id' => 'Proveedor',
|
'gateway_id' => 'Proveedor',
|
||||||
'email_notifications' => 'Notificaciones de email',
|
'email_notifications' => 'Notificaciones de email',
|
||||||
@ -765,6 +765,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
@ -196,7 +196,7 @@ return array(
|
|||||||
'users' => 'Usuarios',
|
'users' => 'Usuarios',
|
||||||
'localization' => 'Localización',
|
'localization' => 'Localización',
|
||||||
'remove_logo' => 'Eliminar logo',
|
'remove_logo' => 'Eliminar logo',
|
||||||
'logo_help' => 'Formatos aceptados: JPEG, GIF y PNG. Altura recomendada: 120px',
|
'logo_help' => 'Formatos aceptados: JPEG, GIF y PNG',
|
||||||
'payment_gateway' => 'Pasarela de pago',
|
'payment_gateway' => 'Pasarela de pago',
|
||||||
'gateway_id' => 'Proveedor',
|
'gateway_id' => 'Proveedor',
|
||||||
'email_notifications' => 'Notificaciones de email',
|
'email_notifications' => 'Notificaciones de email',
|
||||||
@ -787,6 +787,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Utilisateurs',
|
'users' => 'Utilisateurs',
|
||||||
'localization' => 'Localisation',
|
'localization' => 'Localisation',
|
||||||
'remove_logo' => 'Supprimer le logo',
|
'remove_logo' => 'Supprimer le logo',
|
||||||
'logo_help' => 'Formats supportés: JPEG, GIF et PNG. Hauteur recommandé: 120px',
|
'logo_help' => 'Formats supportés: JPEG, GIF et PNG',
|
||||||
'payment_gateway' => 'Passerelle de paiement',
|
'payment_gateway' => 'Passerelle de paiement',
|
||||||
'gateway_id' => 'Fournisseur',
|
'gateway_id' => 'Fournisseur',
|
||||||
'email_notifications' => 'Notifications par courriel',
|
'email_notifications' => 'Notifications par courriel',
|
||||||
@ -779,6 +779,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Utilisateurs',
|
'users' => 'Utilisateurs',
|
||||||
'localization' => 'Localisation',
|
'localization' => 'Localisation',
|
||||||
'remove_logo' => 'Supprimer le logo',
|
'remove_logo' => 'Supprimer le logo',
|
||||||
'logo_help' => 'Formats supportés: JPEG, GIF et PNG. Hauteur recommandé: 120px',
|
'logo_help' => 'Formats supportés: JPEG, GIF et PNG',
|
||||||
'payment_gateway' => 'Passerelle de paiement',
|
'payment_gateway' => 'Passerelle de paiement',
|
||||||
'gateway_id' => 'Fournisseur',
|
'gateway_id' => 'Fournisseur',
|
||||||
'email_notifications' => 'Notifications par courriel',
|
'email_notifications' => 'Notifications par courriel',
|
||||||
@ -780,6 +780,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Utenti',
|
'users' => 'Utenti',
|
||||||
'localization' => 'Localizzazione',
|
'localization' => 'Localizzazione',
|
||||||
'remove_logo' => 'Rimuovi logo',
|
'remove_logo' => 'Rimuovi logo',
|
||||||
'logo_help' => 'Supportati: JPEG, GIF e PNG. Altezza raccomandata: 120px',
|
'logo_help' => 'Supportati: JPEG, GIF e PNG',
|
||||||
'payment_gateway' => 'Servizi di Pagamento',
|
'payment_gateway' => 'Servizi di Pagamento',
|
||||||
'gateway_id' => 'Piattaforma',
|
'gateway_id' => 'Piattaforma',
|
||||||
'email_notifications' => 'Notifiche Email',
|
'email_notifications' => 'Notifiche Email',
|
||||||
@ -782,5 +782,8 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Users',
|
'users' => 'Users',
|
||||||
'localization' => 'Localization',
|
'localization' => 'Localization',
|
||||||
'remove_logo' => 'Remove logo',
|
'remove_logo' => 'Remove logo',
|
||||||
'logo_help' => 'Supported: JPEG, GIF and PNG. Recommended size: 200px width by 120px height',
|
'logo_help' => 'Supported: JPEG, GIF and PNG',
|
||||||
'payment_gateway' => 'Payment Gateway',
|
'payment_gateway' => 'Payment Gateway',
|
||||||
'gateway_id' => 'Provider',
|
'gateway_id' => 'Provider',
|
||||||
'email_notifications' => 'Email Notifications',
|
'email_notifications' => 'Email Notifications',
|
||||||
@ -790,6 +790,9 @@ return array(
|
|||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Brukere',
|
'users' => 'Brukere',
|
||||||
'localization' => 'Lokaliseing',
|
'localization' => 'Lokaliseing',
|
||||||
'remove_logo' => 'Fjern logo',
|
'remove_logo' => 'Fjern logo',
|
||||||
'logo_help' => 'Støttedefiltyper: JPEG, GIF og PNG. Anbefalt størrelse: 200px bredde by 120px høyde',
|
'logo_help' => 'Støttedefiltyper: JPEG, GIF og PNG',
|
||||||
'payment_gateway' => 'Betalingsløsning',
|
'payment_gateway' => 'Betalingsløsning',
|
||||||
'gateway_id' => 'Tilbyder',
|
'gateway_id' => 'Tilbyder',
|
||||||
'email_notifications' => 'Varsel via email',
|
'email_notifications' => 'Varsel via email',
|
||||||
@ -787,6 +787,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
@ -184,7 +184,7 @@ return array(
|
|||||||
'users' => 'Gebruikers',
|
'users' => 'Gebruikers',
|
||||||
'localization' => 'Localisatie',
|
'localization' => 'Localisatie',
|
||||||
'remove_logo' => 'Verwijder logo',
|
'remove_logo' => 'Verwijder logo',
|
||||||
'logo_help' => 'Ondersteund: JPEG, GIF en PNG. Aangeraden hoogte: 120px',
|
'logo_help' => 'Ondersteund: JPEG, GIF en PNG',
|
||||||
'payment_gateway' => 'Betalingsmiddel',
|
'payment_gateway' => 'Betalingsmiddel',
|
||||||
'gateway_id' => 'Leverancier',
|
'gateway_id' => 'Leverancier',
|
||||||
'email_notifications' => 'E-mail meldingen',
|
'email_notifications' => 'E-mail meldingen',
|
||||||
@ -782,5 +782,8 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -183,7 +183,7 @@ return array(
|
|||||||
'users' => 'Usuários',
|
'users' => 'Usuários',
|
||||||
'localization' => 'Localização',
|
'localization' => 'Localização',
|
||||||
'remove_logo' => 'Remover logo',
|
'remove_logo' => 'Remover logo',
|
||||||
'logo_help' => 'Suportados: JPEG, GIF and PNG. Altura recomendada: 120px',
|
'logo_help' => 'Suportados: JPEG, GIF and PNG',
|
||||||
'payment_gateway' => 'Provedor de Pagamento',
|
'payment_gateway' => 'Provedor de Pagamento',
|
||||||
'gateway_id' => 'Provedor',
|
'gateway_id' => 'Provedor',
|
||||||
'email_notifications' => 'Notificações por Email',
|
'email_notifications' => 'Notificações por Email',
|
||||||
@ -782,5 +782,8 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -185,7 +185,7 @@ return array(
|
|||||||
'users' => 'Användare',
|
'users' => 'Användare',
|
||||||
'localization' => 'Språkanpassning',
|
'localization' => 'Språkanpassning',
|
||||||
'remove_logo' => 'Ta bort logga',
|
'remove_logo' => 'Ta bort logga',
|
||||||
'logo_help' => 'Giltiga format: JPEG, GIF och PNG. Rekommenderad storlek: 200 x 120 pixlar (BxH)',
|
'logo_help' => 'Giltiga format: JPEG, GIF och PNG',
|
||||||
'payment_gateway' => 'Betalningstjänst',
|
'payment_gateway' => 'Betalningstjänst',
|
||||||
'gateway_id' => 'Tjänst',
|
'gateway_id' => 'Tjänst',
|
||||||
'email_notifications' => 'Notifieringar',
|
'email_notifications' => 'Notifieringar',
|
||||||
@ -785,6 +785,9 @@ return array(
|
|||||||
'reset' => 'Reset',
|
'reset' => 'Reset',
|
||||||
'invoice_not_found' => 'The requested invoice is not available',
|
'invoice_not_found' => 'The requested invoice is not available',
|
||||||
|
|
||||||
|
'referral_program' => 'Referral Program',
|
||||||
|
'referral_code' => 'Referral Code',
|
||||||
|
'last_sent_on' => 'Last sent on :date',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -86,14 +86,25 @@
|
|||||||
{!! Former::text('last_name') !!}
|
{!! Former::text('last_name') !!}
|
||||||
{!! Former::text('email') !!}
|
{!! Former::text('email') !!}
|
||||||
{!! Former::text('phone') !!}
|
{!! Former::text('phone') !!}
|
||||||
@if (Utils::isNinjaDev())
|
@if (Utils::isNinja() && $primaryUser->confirmed)
|
||||||
|
@if ($primaryUser->referral_code)
|
||||||
|
{!! Former::plaintext('referral_code')
|
||||||
|
->value($primaryUser->referral_code . ' <a href="'.REFERRAL_PROGRAM_URL.'" target="_blank" title="'.trans('texts.learn_more').'">' . Icon::create('question-sign') . '</a>') !!}
|
||||||
|
@else
|
||||||
|
{!! Former::checkbox('referral_code')
|
||||||
|
->text(trans('texts.enable') . ' <a href="'.REFERRAL_PROGRAM_URL.'" target="_blank" title="'.trans('texts.learn_more').'">' . Icon::create('question-sign') . '</a>') !!}
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
@if (false && Utils::isNinjaDev())
|
||||||
{!! Former::checkbox('dark_mode')->text(trans('texts.dark_mode_help')) !!}
|
{!! Former::checkbox('dark_mode')->text(trans('texts.dark_mode_help')) !!}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (Auth::user()->confirmed)
|
@if (Utils::isNinja())
|
||||||
{!! Former::actions( Button::primary(trans('texts.change_password'))->small()->withAttributes(['onclick'=>'showChangePassword()'])) !!}
|
@if (Auth::user()->confirmed)
|
||||||
@elseif (Auth::user()->registered)
|
{!! Former::actions( Button::primary(trans('texts.change_password'))->small()->withAttributes(['onclick'=>'showChangePassword()'])) !!}
|
||||||
{!! Former::actions( Button::primary(trans('texts.resend_confirmation'))->asLinkTo(URL::to('/resend_confirmation'))->small() ) !!}
|
@elseif (Auth::user()->registered)
|
||||||
|
{!! Former::actions( Button::primary(trans('texts.resend_confirmation'))->asLinkTo(URL::to('/resend_confirmation'))->small() ) !!}
|
||||||
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -72,10 +72,12 @@
|
|||||||
<h3 class="panel-title">{!! trans('texts.email_settings') !!}</h3>
|
<h3 class="panel-title">{!! trans('texts.email_settings') !!}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{{ Former::setOption('capitalize_translations', false) }}
|
@if (Utils::isNinja())
|
||||||
{!! Former::text('subdomain')->placeholder(trans('texts.www'))->onchange('onSubdomainChange()') !!}
|
{{ Former::setOption('capitalize_translations', false) }}
|
||||||
{!! Former::text('iframe_url')->placeholder('http://invoices.example.com/')
|
{!! Former::text('subdomain')->placeholder(trans('texts.www'))->onchange('onSubdomainChange()') !!}
|
||||||
->onchange('onDomainChange()')->appendIcon('question-sign')->addGroupClass('iframe_url') !!}
|
{!! Former::text('iframe_url')->placeholder('http://invoices.example.com/')
|
||||||
|
->onchange('onDomainChange()')->appendIcon('question-sign')->addGroupClass('iframe_url') !!}
|
||||||
|
@endif
|
||||||
{!! Former::checkbox('pdf_email_attachment')->text(trans('texts.enable')) !!}
|
{!! Former::checkbox('pdf_email_attachment')->text(trans('texts.enable')) !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -130,9 +132,9 @@
|
|||||||
|
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<p>{{ trans('texts.iframe_url_help1') }}</p>
|
<p>{{ trans('texts.iframe_url_help1') }}</p>
|
||||||
<pre><iframe id="iFrame" width="800" height="1000"></iframe>
|
<pre><iframe id="invoiceIFrame" width="800" height="1000"></iframe>
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
var iframe = document.getElementById('iFrame');
|
var iframe = document.getElementById('invoiceIFrame');
|
||||||
iframe.src = '{{ SITE_URL }}/view/'
|
iframe.src = '{{ SITE_URL }}/view/'
|
||||||
+ window.location.search.substring(1);
|
+ window.location.search.substring(1);
|
||||||
</script></pre>
|
</script></pre>
|
||||||
|
@ -3,14 +3,19 @@
|
|||||||
@if (isset($isReminder) && $isReminder)
|
@if (isset($isReminder) && $isReminder)
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{!! Former::checkbox('enable_' . $field)->text(trans('texts.enable'))->label('') !!}
|
{!! Former::checkbox('enable_' . $field)
|
||||||
{!! Former::input('num_days_' . $field)->label(trans('texts.num_days_reminder')) !!}
|
->text(trans('texts.enable'))->label('') !!}
|
||||||
|
{!! Former::input('num_days_' . $field)
|
||||||
|
->label(trans('texts.num_days_reminder'))
|
||||||
|
->addClass('enable-' . $field) !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{!! Former::text('email_subject_' . $field)->label(trans('texts.subject')) !!}
|
{!! Former::text('email_subject_' . $field)
|
||||||
|
->label(trans('texts.subject'))
|
||||||
|
->addClass('enable-' . $field) !!}
|
||||||
<div class="pull-right"><a href="#" onclick="return resetText('{{ 'subject' }}', '{{ $field }}')">{{ trans("texts.reset") }}</a></div>
|
<div class="pull-right"><a href="#" onclick="return resetText('{{ 'subject' }}', '{{ $field }}')">{{ trans("texts.reset") }}</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -20,7 +25,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
{!! Former::textarea('email_template_' . $field)->label(trans('texts.body')) !!}
|
{!! Former::textarea('email_template_' . $field)
|
||||||
|
->label(trans('texts.body'))
|
||||||
|
->addClass('enable-' . $field) !!}
|
||||||
<div class="pull-right"><a href="#" onclick="return resetText('{{ 'template' }}', '{{ $field }}')">{{ trans("texts.reset") }}</a></div>
|
<div class="pull-right"><a href="#" onclick="return resetText('{{ 'template' }}', '{{ $field }}')">{{ trans("texts.reset") }}</a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
var entityTypes = ['invoice', 'quote', 'payment', 'reminder1', 'reminder2', 'reminder3'];
|
var entityTypes = ['invoice', 'quote', 'payment', 'reminder1', 'reminder2', 'reminder3'];
|
||||||
var stringTypes = ['subject', 'template'];
|
var stringTypes = ['subject', 'template'];
|
||||||
var templates = {!! json_encode($templates) !!};
|
var templates = {!! json_encode($defaultTemplates) !!};
|
||||||
|
|
||||||
function refreshPreview() {
|
function refreshPreview() {
|
||||||
for (var i=0; i<entityTypes.length; i++) {
|
for (var i=0; i<entityTypes.length; i++) {
|
||||||
@ -109,7 +109,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
for (var i=0; i<entityTypes.length; i++) {
|
for (var i=0; i<entityTypes.length; i++) {
|
||||||
var entityType = entityTypes[i];
|
var entityType = entityTypes[i];
|
||||||
for (var j=0; j<stringTypes.length; j++) {
|
for (var j=0; j<stringTypes.length; j++) {
|
||||||
@ -118,9 +117,22 @@
|
|||||||
$(idName).keyup(refreshPreview);
|
$(idName).keyup(refreshPreview);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var i=1; i<=3; i++) {
|
||||||
|
$('#enable_reminder' + i).bind('click', {id: i}, function(event) {
|
||||||
|
enableReminder(event.data.id)
|
||||||
|
});
|
||||||
|
enableReminder(i);
|
||||||
|
}
|
||||||
|
|
||||||
refreshPreview();
|
refreshPreview();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function enableReminder(id) {
|
||||||
|
var checked = $('#enable_reminder' + id).is(':checked');
|
||||||
|
$('.enable-reminder' + id).attr('disabled', !checked)
|
||||||
|
}
|
||||||
|
|
||||||
function processVariables(str) {
|
function processVariables(str) {
|
||||||
if (!str) {
|
if (!str) {
|
||||||
return '';
|
return '';
|
||||||
|
@ -101,20 +101,8 @@
|
|||||||
{!! trans('texts.created_by_invoice', ['invoice' => link_to('/invoices/'.$invoice->recurring_invoice->public_id, trans('texts.recurring_invoice'))]) !!}
|
{!! trans('texts.created_by_invoice', ['invoice' => link_to('/invoices/'.$invoice->recurring_invoice->public_id, trans('texts.recurring_invoice'))]) !!}
|
||||||
</div>
|
</div>
|
||||||
@elseif ($invoice && isset($lastSent) && $lastSent)
|
@elseif ($invoice && isset($lastSent) && $lastSent)
|
||||||
<div class="form-group" data-bind="visible: !show_last_sent_date()" >
|
<div class="pull-right" style="padding-top: 6px">
|
||||||
<label for="client" class="control-label col-lg-4 col-sm-4">{{ trans('texts.last_sent') }}</label>
|
{!! trans('texts.last_sent_on', ['date' => link_to('/invoices/'.$lastSent->public_id, Utils::dateToString($invoice->last_sent_date))]) !!}
|
||||||
<div class="col-lg-8 col-sm-8">
|
|
||||||
<div style="padding-top:10px">
|
|
||||||
<a href="#" data-bind="click: $root.clickLastSentDate">{{ Utils::dateToString($invoice->last_sent_date) }}</a> -
|
|
||||||
{!! link_to('/invoices/'.$lastSent->public_id, trans('texts.view_invoice'), ['id' => 'lastInvoiceSent']) !!}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div data-bind="visible: show_last_sent_date()" style="display:none">
|
|
||||||
{!! Former::text('last_sent_date')->data_bind("datePicker: last_sent_date, valueUpdate: 'afterkeydown', visible: show_last_sent_date()")
|
|
||||||
->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))
|
|
||||||
->label(trans('texts.last_sent'))
|
|
||||||
->appendIcon('calendar')->addGroupClass('last_sent_date') !!}
|
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
@ -192,8 +180,8 @@
|
|||||||
<td style="text-align:right;padding-top:9px !important">
|
<td style="text-align:right;padding-top:9px !important">
|
||||||
<div class="line-total" data-bind="text: totals.total"></div>
|
<div class="line-total" data-bind="text: totals.total"></div>
|
||||||
</td>
|
</td>
|
||||||
<td style="cursor:pointer" class="hide-border td-icon">
|
<td style="cursor:pointer" class="hide-border td-icon">
|
||||||
<i style="display:none" data-bind="click: $parent.removeItem, visible: actionsVisible() &&
|
<i style="display:none;padding-left:4px" data-bind="click: $parent.removeItem, visible: actionsVisible() &&
|
||||||
$index() < ($parent.invoice_items().length - 1) &&
|
$index() < ($parent.invoice_items().length - 1) &&
|
||||||
$parent.invoice_items().length > 1" class="fa fa-minus-circle redlink" title="Remove item"/>
|
$parent.invoice_items().length > 1" class="fa fa-minus-circle redlink" title="Remove item"/>
|
||||||
</td>
|
</td>
|
||||||
@ -966,10 +954,6 @@
|
|||||||
self.invoice = ko.observable(data ? false : new InvoiceModel());
|
self.invoice = ko.observable(data ? false : new InvoiceModel());
|
||||||
self.tax_rates = ko.observableArray();
|
self.tax_rates = ko.observableArray();
|
||||||
|
|
||||||
self.clickLastSentDate = function() {
|
|
||||||
self.invoice().show_last_sent_date(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.loadClient = function(client) {
|
self.loadClient = function(client) {
|
||||||
ko.mapping.fromJS(client, model.invoice().client().mapping, model.invoice().client);
|
ko.mapping.fromJS(client, model.invoice().client().mapping, model.invoice().client);
|
||||||
@if (!$invoice)
|
@if (!$invoice)
|
||||||
@ -1217,7 +1201,6 @@
|
|||||||
self.invoice_design_id = ko.observable({{ $account->invoice_design_id }});
|
self.invoice_design_id = ko.observable({{ $account->invoice_design_id }});
|
||||||
self.partial = ko.observable(0);
|
self.partial = ko.observable(0);
|
||||||
self.has_tasks = ko.observable(false);
|
self.has_tasks = ko.observable(false);
|
||||||
self.show_last_sent_date = ko.observable(false);
|
|
||||||
|
|
||||||
self.custom_value1 = ko.observable(0);
|
self.custom_value1 = ko.observable(0);
|
||||||
self.custom_value2 = ko.observable(0);
|
self.custom_value2 = ko.observable(0);
|
||||||
@ -1641,7 +1624,7 @@
|
|||||||
|
|
||||||
this.prettyRate = ko.computed({
|
this.prettyRate = ko.computed({
|
||||||
read: function () {
|
read: function () {
|
||||||
return this.rate() ? this.rate() : '';
|
return this.rate() ? roundToTwo(this.rate()) : '';
|
||||||
},
|
},
|
||||||
write: function (value) {
|
write: function (value) {
|
||||||
this.rate(value);
|
this.rate(value);
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
@yield('body')
|
@yield('body')
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
NINJA.formIsChanged = false;
|
NINJA.formIsChanged = {{ isset($formIsChanged) && $formIsChanged ? 'true' : 'false' }};
|
||||||
$(function() {
|
$(function() {
|
||||||
$('form.warn-on-exit input, form.warn-on-exit textarea, form.warn-on-exit select').change(function() {
|
$('form.warn-on-exit input, form.warn-on-exit textarea, form.warn-on-exit select').change(function() {
|
||||||
NINJA.formIsChanged = true;
|
NINJA.formIsChanged = true;
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
"style": "invoiceLineItemsTable",
|
"style": "invoiceLineItemsTable",
|
||||||
"table": {
|
"table": {
|
||||||
"headerRows": 1,
|
"headerRows": 1,
|
||||||
"widths": ["15%", "*", "14%", "$quantityWidth", "22%"],
|
"widths": ["22%", "*", "14%", "$quantityWidth", "$taxWidth", "22%"],
|
||||||
"body": "$invoiceLineItems"
|
"body": "$invoiceLineItems"
|
||||||
},
|
},
|
||||||
"layout": {
|
"layout": {
|
||||||
@ -74,13 +74,19 @@
|
|||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"footer": [
|
"footer":
|
||||||
{"canvas": [{ "type": "line", "x1": 0, "y1": 0, "x2": 600, "y2": 0,"lineWidth": 100,"lineColor":"$secondaryColor:#2e2b2b"}]},
|
[
|
||||||
|
{"canvas": [{ "type": "line", "x1": 0, "y1": 0, "x2": 600, "y2": 0,"lineWidth": 100,"lineColor":"$secondaryColor:#292526"}]},
|
||||||
{
|
{
|
||||||
"text": "$invoiceFooter",
|
"columns":
|
||||||
"margin": [40, 0, 40, 0],
|
[
|
||||||
"alignment": "left",
|
{
|
||||||
"color": "#FFFFFF"
|
"text": "$invoiceFooter",
|
||||||
|
"margin": [40, -40, 40, 0],
|
||||||
|
"alignment": "left",
|
||||||
|
"color": "#FFFFFF"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"header": [
|
"header": [
|
||||||
@ -93,7 +99,7 @@
|
|||||||
"x2": 600,
|
"x2": 600,
|
||||||
"y2": 0,
|
"y2": 0,
|
||||||
"lineWidth": 200,
|
"lineWidth": 200,
|
||||||
"lineColor": "$secondaryColor:#2e2b2b"
|
"lineColor": "$secondaryColor:#292526"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"width": 10
|
"width": 10
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
"table": {
|
"table": {
|
||||||
"body": "$invoiceDetails"
|
"body": "$invoiceDetails"
|
||||||
},
|
},
|
||||||
"margin": [0, 0, 12, 4],
|
"margin": [0, 0, 12, 0],
|
||||||
"layout": "noBorders"
|
"layout": "noBorders"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"paddingLeft": "$amount:8",
|
"paddingLeft": "$amount:8",
|
||||||
"paddingRight": "$amount:8",
|
"paddingRight": "$amount:8",
|
||||||
"paddingTop": "$amount:6",
|
"paddingTop": "$amount:6",
|
||||||
"paddingBottom": "$amount:2"
|
"paddingBottom": "$amount:6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
{
|
{
|
||||||
"content": [
|
"content": [
|
||||||
{
|
|
||||||
"columns": [
|
|
||||||
{
|
{
|
||||||
"image": "$accountLogo",
|
"columns": [
|
||||||
"fit": [120, 80],
|
{
|
||||||
"margin": [0, 60, 0, 30]
|
"image": "$accountLogo",
|
||||||
|
"fit": [120, 80],
|
||||||
|
"margin": [0, 60, 0, 30]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stack": "$clientDetails",
|
||||||
|
"margin": [260, 80, 0, 0]
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"stack": "$clientDetails",
|
|
||||||
"margin": [260, 80, 0, 0]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"canvas": [{ "type": "rect", "x": 0, "y": 0, "w": 515, "h": 26, "r":0, "lineWidth": 1, "color":"$secondaryColor:#403d3d"}],"width":10,"margin":[0,25,0,-30]},
|
|
||||||
{
|
{
|
||||||
"style": "invoiceLineItemsTable",
|
"style": "invoiceLineItemsTable",
|
||||||
"table": {
|
"table": {
|
||||||
@ -24,8 +22,9 @@
|
|||||||
},
|
},
|
||||||
"layout": {
|
"layout": {
|
||||||
"hLineWidth": "$notFirst:.5",
|
"hLineWidth": "$notFirst:.5",
|
||||||
"vLineWidth": "$none",
|
"vLineWidth": "$notFirstAndLastColumn:.5",
|
||||||
"hLineColor": "#888888",
|
"hLineColor": "#888888",
|
||||||
|
"vLineColor": "#FFFFFF",
|
||||||
"paddingLeft": "$amount:8",
|
"paddingLeft": "$amount:8",
|
||||||
"paddingRight": "$amount:8",
|
"paddingRight": "$amount:8",
|
||||||
"paddingTop": "$amount:8",
|
"paddingTop": "$amount:8",
|
||||||
@ -92,17 +91,22 @@
|
|||||||
"canvas": [
|
"canvas": [
|
||||||
{
|
{
|
||||||
"type": "line", "x1": 0, "y1": 0, "x2": 600, "y2": 0,"lineWidth": 100,"lineColor":"$primaryColor:#f26621"
|
"type": "line", "x1": 0, "y1": 0, "x2": 600, "y2": 0,"lineWidth": 100,"lineColor":"$primaryColor:#f26621"
|
||||||
}]
|
}]
|
||||||
,"width":10
|
,"width":10
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
"text": "$invoiceFooter",
|
"width": 350,
|
||||||
"margin": [40, -30, 40, 0],
|
"stack": [
|
||||||
"alignment": "left",
|
{
|
||||||
"color": "#FFFFFF",
|
"text": "$invoiceFooter",
|
||||||
"width": 350
|
"margin": [40, -40, 40, 0],
|
||||||
|
"alignment": "left",
|
||||||
|
"color": "#FFFFFF"
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"stack": "$accountDetails",
|
"stack": "$accountDetails",
|
||||||
@ -175,7 +179,8 @@
|
|||||||
"tableHeader": {
|
"tableHeader": {
|
||||||
"bold": true,
|
"bold": true,
|
||||||
"color": "#FFFFFF",
|
"color": "#FFFFFF",
|
||||||
"fontSize": "$fontSizeLargest"
|
"fontSize": "$fontSizeLargest",
|
||||||
|
"fillColor": "$secondaryColor:#403d3d"
|
||||||
},
|
},
|
||||||
"costTableHeader": {
|
"costTableHeader": {
|
||||||
"alignment": "right"
|
"alignment": "right"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user