mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 19:14:40 -04:00
Added HTML email designs
This commit is contained in:
parent
7109b30673
commit
c5a1abf66f
@ -46,29 +46,78 @@ class CheckData extends Command {
|
|||||||
public function fire()
|
public function fire()
|
||||||
{
|
{
|
||||||
$this->info(date('Y-m-d') . ' Running CheckData...');
|
$this->info(date('Y-m-d') . ' Running CheckData...');
|
||||||
$today = new DateTime();
|
|
||||||
|
|
||||||
if (!$this->option('client_id')) {
|
if (!$this->option('client_id')) {
|
||||||
// update client paid_to_date value
|
$this->checkPaidToDate();
|
||||||
$clients = DB::table('clients')
|
}
|
||||||
->join('payments', 'payments.client_id', '=', 'clients.id')
|
|
||||||
->join('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
$this->checkBalances();
|
||||||
->where('payments.is_deleted', '=', 0)
|
|
||||||
->where('invoices.is_deleted', '=', 0)
|
$this->checkActivityAccount();
|
||||||
->groupBy('clients.id')
|
|
||||||
->havingRaw('clients.paid_to_date != sum(payments.amount) and clients.paid_to_date != 999999999.9999')
|
$this->info('Done');
|
||||||
->get(['clients.id', 'clients.paid_to_date', DB::raw('sum(payments.amount) as amount')]);
|
}
|
||||||
$this->info(count($clients) . ' clients with incorrect paid to date');
|
|
||||||
|
private function checkActivityAccount()
|
||||||
|
{
|
||||||
|
$entityTypes = [
|
||||||
|
ENTITY_INVOICE,
|
||||||
|
ENTITY_CLIENT,
|
||||||
|
ENTITY_CONTACT,
|
||||||
|
ENTITY_PAYMENT,
|
||||||
|
ENTITY_INVITATION,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($entityTypes as $entityType) {
|
||||||
|
$activities = DB::table('activities')
|
||||||
|
->join("{$entityType}s", "{$entityType}s.id", '=', "activities.{$entityType}_id");
|
||||||
|
|
||||||
|
if ($entityType != ENTITY_CLIENT) {
|
||||||
|
$activities = $activities->join('clients', 'clients.id', '=', 'activities.client_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
$activities = $activities->where('activities.account_id', '!=', DB::raw("{$entityType}s.account_id"))
|
||||||
|
->get(['activities.id', "clients.account_id", "clients.user_id"]);
|
||||||
|
|
||||||
|
$this->info(count($activities) . " {$entityType} activity with incorrect account id");
|
||||||
|
|
||||||
if ($this->option('fix') == 'true') {
|
if ($this->option('fix') == 'true') {
|
||||||
foreach ($clients as $client) {
|
foreach ($activities as $activity) {
|
||||||
DB::table('clients')
|
DB::table('activities')
|
||||||
->where('id', $client->id)
|
->where('id', $activity->id)
|
||||||
->update(['paid_to_date' => $client->amount]);
|
->update([
|
||||||
|
'account_id' => $activity->account_id,
|
||||||
|
'user_id' => $activity->user_id,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkPaidToDate()
|
||||||
|
{
|
||||||
|
// update client paid_to_date value
|
||||||
|
$clients = DB::table('clients')
|
||||||
|
->join('payments', 'payments.client_id', '=', 'clients.id')
|
||||||
|
->join('invoices', 'invoices.id', '=', 'payments.invoice_id')
|
||||||
|
->where('payments.is_deleted', '=', 0)
|
||||||
|
->where('invoices.is_deleted', '=', 0)
|
||||||
|
->groupBy('clients.id')
|
||||||
|
->havingRaw('clients.paid_to_date != sum(payments.amount) and clients.paid_to_date != 999999999.9999')
|
||||||
|
->get(['clients.id', 'clients.paid_to_date', DB::raw('sum(payments.amount) as amount')]);
|
||||||
|
$this->info(count($clients) . ' clients with incorrect paid to date');
|
||||||
|
|
||||||
|
if ($this->option('fix') == 'true') {
|
||||||
|
foreach ($clients as $client) {
|
||||||
|
DB::table('clients')
|
||||||
|
->where('id', $client->id)
|
||||||
|
->update(['paid_to_date' => $client->amount]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkBalances()
|
||||||
|
{
|
||||||
// find all clients where the balance doesn't equal the sum of the outstanding invoices
|
// find all clients where the balance doesn't equal the sum of the outstanding invoices
|
||||||
$clients = DB::table('clients')
|
$clients = DB::table('clients')
|
||||||
->join('invoices', 'invoices.client_id', '=', 'clients.id')
|
->join('invoices', 'invoices.client_id', '=', 'clients.id')
|
||||||
@ -249,8 +298,6 @@ class CheckData extends Command {
|
|||||||
->update($data);
|
->update($data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->info('Done');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getArguments()
|
protected function getArguments()
|
||||||
|
@ -432,6 +432,11 @@ class AccountController extends BaseController
|
|||||||
{
|
{
|
||||||
if (Auth::user()->account->isPro()) {
|
if (Auth::user()->account->isPro()) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
$account->email_design_id = Input::get('email_design_id');
|
||||||
|
|
||||||
|
if (Utils::isNinja()) {
|
||||||
|
$account->enable_email_markup = Input::get('enable_email_markup') ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
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}";
|
||||||
|
@ -253,6 +253,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('ENTITY_CONTACT', 'contact');
|
define('ENTITY_CONTACT', 'contact');
|
||||||
define('ENTITY_INVOICE', 'invoice');
|
define('ENTITY_INVOICE', 'invoice');
|
||||||
define('ENTITY_INVOICE_ITEMS', 'invoice_items');
|
define('ENTITY_INVOICE_ITEMS', 'invoice_items');
|
||||||
|
define('ENTITY_INVITATION', 'invitation');
|
||||||
define('ENTITY_RECURRING_INVOICE', 'recurring_invoice');
|
define('ENTITY_RECURRING_INVOICE', 'recurring_invoice');
|
||||||
define('ENTITY_PAYMENT', 'payment');
|
define('ENTITY_PAYMENT', 'payment');
|
||||||
define('ENTITY_CREDIT', 'credit');
|
define('ENTITY_CREDIT', 'credit');
|
||||||
@ -446,6 +447,7 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/api/browser/v2/');
|
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/api/browser/v2/');
|
||||||
define('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php');
|
define('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php');
|
||||||
define('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/');
|
define('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/');
|
||||||
|
define('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup/overview');
|
||||||
|
|
||||||
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
|
||||||
@ -498,6 +500,9 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('API_SERIALIZER_ARRAY', 'array');
|
define('API_SERIALIZER_ARRAY', 'array');
|
||||||
define('API_SERIALIZER_JSON', 'json');
|
define('API_SERIALIZER_JSON', 'json');
|
||||||
|
|
||||||
|
define('EMAIL_DESIGN_PLAIN', 1);
|
||||||
|
define('FLAT_BUTTON_CSS', 'border:0 none;border-radius:6px;padding:12px 40px;margin:0 6px;cursor:hand;display:inline-block;font-size:14px;color:#fff;text-transform:none');
|
||||||
|
|
||||||
$creditCards = [
|
$creditCards = [
|
||||||
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
|
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
|
||||||
2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'],
|
2 => ['card' => 'images/credit_cards/Test-MasterCard-Icon.png', 'text' => 'Master Card'],
|
||||||
@ -522,7 +527,6 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
'invoiceStatus' => 'App\Models\InvoiceStatus',
|
'invoiceStatus' => 'App\Models\InvoiceStatus',
|
||||||
'frequencies' => 'App\Models\Frequency',
|
'frequencies' => 'App\Models\Frequency',
|
||||||
'gateways' => 'App\Models\Gateway',
|
'gateways' => 'App\Models\Gateway',
|
||||||
'themes' => 'App\Models\Theme',
|
|
||||||
];
|
];
|
||||||
define('CACHED_TABLES', serialize($cachedTables));
|
define('CACHED_TABLES', serialize($cachedTables));
|
||||||
|
|
||||||
|
@ -279,9 +279,19 @@ class Utils
|
|||||||
return json_decode(json_encode((array) $data), true);
|
return json_decode(json_encode((array) $data), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function toSpaceCase($camelStr)
|
public static function toSpaceCase($string)
|
||||||
{
|
{
|
||||||
return preg_replace('/([a-z])([A-Z])/s', '$1 $2', $camelStr);
|
return preg_replace('/([a-z])([A-Z])/s', '$1 $2', $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function toSnakeCase($string)
|
||||||
|
{
|
||||||
|
return preg_replace('/([a-z])([A-Z])/s', '$1_$2', $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function toCamelCase($string)
|
||||||
|
{
|
||||||
|
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $string))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function timestampToDateTimeString($timestamp)
|
public static function timestampToDateTimeString($timestamp)
|
||||||
|
@ -5,6 +5,7 @@ use Utils;
|
|||||||
use Session;
|
use Session;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use Event;
|
use Event;
|
||||||
|
use Cache;
|
||||||
use App;
|
use App;
|
||||||
use File;
|
use File;
|
||||||
use App\Events\UserSettingsChanged;
|
use App\Events\UserSettingsChanged;
|
||||||
@ -204,10 +205,26 @@ class Account extends Eloquent
|
|||||||
return $this->date_format ? $this->date_format->format : DEFAULT_DATE_FORMAT;
|
return $this->date_format ? $this->date_format->format : DEFAULT_DATE_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function formatMoney($amount, $client = null)
|
||||||
|
{
|
||||||
|
$currency = ($client && $client->currency) ? $client->currency : $this->currency;
|
||||||
|
|
||||||
|
if ( ! $currency) {
|
||||||
|
$currencies = Cache::get('currencies')->filter(function($item) {
|
||||||
|
return $item->id == DEFAULT_CURRENCY;
|
||||||
|
});
|
||||||
|
$currency = $currencies->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $currency->symbol . number_format($amount, $currency->precision, $currency->decimal_separator, $currency->thousand_separator);
|
||||||
|
}
|
||||||
|
|
||||||
public function formatDate($date)
|
public function formatDate($date)
|
||||||
{
|
{
|
||||||
if (!$date) {
|
if ( ! $date) {
|
||||||
return null;
|
return null;
|
||||||
|
} elseif ( ! $date instanceof \DateTime) {
|
||||||
|
$date = new \DateTime($date);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $date->format($this->getCustomDateFormat());
|
return $date->format($this->getCustomDateFormat());
|
||||||
@ -677,9 +694,9 @@ class Account extends Eloquent
|
|||||||
$entityType = ENTITY_INVOICE;
|
$entityType = ENTITY_INVOICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
$template = "<div>\$client,</div><br/>" .
|
$template = "<div>\$client,</div><br>" .
|
||||||
"<div>" . trans("texts.{$entityType}_message", ['amount' => '$amount']) . "</div><br/>" .
|
"<div>" . trans("texts.{$entityType}_message", ['amount' => '$amount']) . "</div><br>" .
|
||||||
"<div><a href=\"\$link\">\$link</a></div><br/>";
|
"<div><a href=\"\$viewLink\">\$viewLink</a></div><br>";
|
||||||
|
|
||||||
if ($message) {
|
if ($message) {
|
||||||
$template .= "$message<p/>\r\n\r\n";
|
$template .= "$message<p/>\r\n\r\n";
|
||||||
@ -693,13 +710,14 @@ class Account extends Eloquent
|
|||||||
if ($this->isPro()) {
|
if ($this->isPro()) {
|
||||||
$field = "email_template_{$entityType}";
|
$field = "email_template_{$entityType}";
|
||||||
$template = $this->$field;
|
$template = $this->$field;
|
||||||
|
|
||||||
if ($template) {
|
|
||||||
return $template;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->getDefaultEmailTemplate($entityType, $message);
|
if (!$template) {
|
||||||
|
$template = $this->getDefaultEmailTemplate($entityType, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <br/> is causing page breaks with the email designs
|
||||||
|
return str_replace('/>', ' />', $template);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEmailFooter()
|
public function getEmailFooter()
|
||||||
@ -708,7 +726,7 @@ class Account extends Eloquent
|
|||||||
// Add line breaks if HTML isn't already being used
|
// Add line breaks if HTML isn't already being used
|
||||||
return strip_tags($this->email_footer) == $this->email_footer ? nl2br($this->email_footer) : $this->email_footer;
|
return strip_tags($this->email_footer) == $this->email_footer ? nl2br($this->email_footer) : $this->email_footer;
|
||||||
} else {
|
} else {
|
||||||
return "<p>" . trans('texts.email_signature') . "\n<br>\$account</p>";
|
return "<p>" . trans('texts.email_signature') . "\n<br>\$account</ p>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Omnipay;
|
use Omnipay;
|
||||||
|
use Utils;
|
||||||
|
|
||||||
class Gateway extends Eloquent
|
class Gateway extends Eloquent
|
||||||
{
|
{
|
||||||
@ -44,13 +45,20 @@ class Gateway extends Eloquent
|
|||||||
return $this->id == $gatewayId;
|
return $this->id == $gatewayId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getPaymentTypeName($type)
|
||||||
|
{
|
||||||
|
return Utils::toCamelCase(strtolower(str_replace('PAYMENT_TYPE_', '', $type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public static function getPaymentTypeLinks() {
|
public static function getPaymentTypeLinks() {
|
||||||
$data = [];
|
$data = [];
|
||||||
foreach (self::$paymentTypes as $type) {
|
foreach (self::$paymentTypes as $type) {
|
||||||
$data[] = strtolower(str_replace('PAYMENT_TYPE_', '', $type));
|
$data[] = Utils::toCamelCase(strtolower(str_replace('PAYMENT_TYPE_', '', $type)));
|
||||||
}
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public function getHelp()
|
public function getHelp()
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ class Invitation extends EntityModel
|
|||||||
return $this->belongsTo('App\Models\Account');
|
return $this->belongsTo('App\Models\Account');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLink()
|
public function getLink($type = 'view')
|
||||||
{
|
{
|
||||||
if (!$this->account) {
|
if (!$this->account) {
|
||||||
$this->load('account');
|
$this->load('account');
|
||||||
@ -46,7 +46,7 @@ class Invitation extends EntityModel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "{$url}/view/{$this->invitation_key}";
|
return "{$url}/{$type}/{$this->invitation_key}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStatus()
|
public function getStatus()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?php namespace App\Ninja\Mailers;
|
<?php namespace App\Ninja\Mailers;
|
||||||
|
|
||||||
|
use HTML;
|
||||||
use Utils;
|
use Utils;
|
||||||
use Event;
|
use Event;
|
||||||
use URL;
|
use URL;
|
||||||
@ -15,6 +16,21 @@ use App\Events\QuoteWasEmailed;
|
|||||||
|
|
||||||
class ContactMailer extends Mailer
|
class ContactMailer extends Mailer
|
||||||
{
|
{
|
||||||
|
public static $variableFields = [
|
||||||
|
'footer',
|
||||||
|
'account',
|
||||||
|
'client',
|
||||||
|
'amount',
|
||||||
|
'contact',
|
||||||
|
'firstName',
|
||||||
|
'invoice',
|
||||||
|
'quote',
|
||||||
|
'viewLink',
|
||||||
|
'viewButton',
|
||||||
|
'paymentLink',
|
||||||
|
'paymentButton',
|
||||||
|
];
|
||||||
|
|
||||||
public function sendInvoice(Invoice $invoice, $reminder = false, $pdfString = false)
|
public function sendInvoice(Invoice $invoice, $reminder = false, $pdfString = false)
|
||||||
{
|
{
|
||||||
$invoice->load('invitations', 'client.language', 'account');
|
$invoice->load('invitations', 'client.language', 'account');
|
||||||
@ -97,6 +113,7 @@ class ContactMailer extends Mailer
|
|||||||
'invoiceId' => $invoice->id,
|
'invoiceId' => $invoice->id,
|
||||||
'invitation' => $invitation,
|
'invitation' => $invitation,
|
||||||
'account' => $account,
|
'account' => $account,
|
||||||
|
'client' => $client,
|
||||||
'invoice' => $invoice,
|
'invoice' => $invoice,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -107,8 +124,14 @@ class ContactMailer extends Mailer
|
|||||||
|
|
||||||
$subject = $this->processVariables($subject, $variables);
|
$subject = $this->processVariables($subject, $variables);
|
||||||
$fromEmail = $user->email;
|
$fromEmail = $user->email;
|
||||||
|
|
||||||
|
if ($account->email_design_id == EMAIL_DESIGN_PLAIN) {
|
||||||
|
$view = ENTITY_INVOICE;
|
||||||
|
} else {
|
||||||
|
$view = 'design' . ($account->email_design_id - 1);
|
||||||
|
}
|
||||||
|
|
||||||
$response = $this->sendTo($invitation->contact->email, $fromEmail, $account->getDisplayName(), $subject, ENTITY_INVOICE, $data);
|
$response = $this->sendTo($invitation->contact->email, $fromEmail, $account->getDisplayName(), $subject, $view, $data);
|
||||||
|
|
||||||
if ($response === true) {
|
if ($response === true) {
|
||||||
return true;
|
return true;
|
||||||
@ -192,22 +215,33 @@ class ContactMailer extends Mailer
|
|||||||
|
|
||||||
private function processVariables($template, $data)
|
private function processVariables($template, $data)
|
||||||
{
|
{
|
||||||
|
$account = $data['account'];
|
||||||
|
$client = $data['client'];
|
||||||
|
$invitation = $data['invitation'];
|
||||||
|
$invoice = $invitation->invoice;
|
||||||
|
|
||||||
$variables = [
|
$variables = [
|
||||||
'$footer' => $data['account']->getEmailFooter(),
|
'$footer' => $account->getEmailFooter(),
|
||||||
'$link' => $data['invitation']->getLink(),
|
'$client' => $client->getDisplayName(),
|
||||||
'$client' => $data['client']->getDisplayName(),
|
'$account' => $account->getDisplayName(),
|
||||||
'$account' => $data['account']->getDisplayName(),
|
'$contact' => $invitation->contact->getDisplayName(),
|
||||||
'$contact' => $data['invitation']->contact->getDisplayName(),
|
'$firstName' => $invitation->contact->first_name,
|
||||||
'$firstName' => $data['invitation']->contact->first_name,
|
'$amount' => Utils::formatMoney($data['amount'], $client->getCurrencyId()),
|
||||||
'$amount' => Utils::formatMoney($data['amount'], $data['client']->getCurrencyId()),
|
'$invoice' => $invoice->invoice_number,
|
||||||
'$invoice' => $data['invitation']->invoice->invoice_number,
|
'$quote' => $invoice->invoice_number,
|
||||||
'$quote' => $data['invitation']->invoice->invoice_number,
|
'$link' => $invitation->getLink(),
|
||||||
'$advancedRawInvoice->' => '$'
|
'$viewLink' => $invitation->getLink(),
|
||||||
|
'$viewButton' => HTML::emailViewButton($invitation->getLink(), $invoice->getEntityType()),
|
||||||
|
'$paymentLink' => $invitation->getLink('payment'),
|
||||||
|
'$paymentButton' => HTML::emailPaymentButton($invitation->getLink('payment')),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Add variables for available payment types
|
// Add variables for available payment types
|
||||||
foreach (Gateway::getPaymentTypeLinks() as $type) {
|
foreach (Gateway::$paymentTypes as $type) {
|
||||||
$variables["\${$type}_link"] = URL::to("/payment/{$data['invitation']->invitation_key}/{$type}");
|
$camelType = Gateway::getPaymentTypeName($type);
|
||||||
|
$type = Utils::toSnakeCase($camelType);
|
||||||
|
$variables["\${$camelType}Link"] = $invitation->getLink() . "/{$type}";
|
||||||
|
$variables["\${$camelType}Button"] = HTML::emailPaymentButton($invitation->getLink('payment') . "/{$type}");
|
||||||
}
|
}
|
||||||
|
|
||||||
$str = str_replace(array_keys($variables), array_values($variables), $template);
|
$str = str_replace(array_keys($variables), array_values($variables), $template);
|
||||||
|
@ -67,7 +67,7 @@ class Mailer
|
|||||||
|
|
||||||
private function handleFailure($exception)
|
private function handleFailure($exception)
|
||||||
{
|
{
|
||||||
if (isset($_ENV['POSTMARK_API_TOKEN']) && $exception->getResponse()) {
|
if (isset($_ENV['POSTMARK_API_TOKEN']) && method_exists($exception, 'getResponse')) {
|
||||||
$response = $exception->getResponse()->getBody()->getContents();
|
$response = $exception->getResponse()->getBody()->getContents();
|
||||||
$response = json_decode($response);
|
$response = json_decode($response);
|
||||||
$emailError = nl2br($response->Message);
|
$emailError = nl2br($response->Message);
|
||||||
|
@ -15,6 +15,17 @@ class InvoicePresenter extends Presenter {
|
|||||||
return $this->entity->user->getDisplayName();
|
return $this->entity->user->getDisplayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function balanceDueLabel()
|
||||||
|
{
|
||||||
|
if ($this->entity->partial) {
|
||||||
|
return 'amount_due';
|
||||||
|
} elseif ($this->entity->is_quote) {
|
||||||
|
return 'total';
|
||||||
|
} else {
|
||||||
|
return 'balance_due';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function balance_due()
|
public function balance_due()
|
||||||
{
|
{
|
||||||
$amount = $this->entity->getRequestedAmount();
|
$amount = $this->entity->getRequestedAmount();
|
||||||
|
@ -44,7 +44,7 @@ class ActivityRepository
|
|||||||
{
|
{
|
||||||
$activity = new Activity();
|
$activity = new Activity();
|
||||||
|
|
||||||
if (Auth::check()) {
|
if (Auth::check() && Auth::user()->account_id == $entity->account_id) {
|
||||||
$activity->user_id = Auth::user()->id;
|
$activity->user_id = Auth::user()->id;
|
||||||
$activity->account_id = Auth::user()->account_id;
|
$activity->account_id = Auth::user()->account_id;
|
||||||
} else {
|
} else {
|
||||||
|
@ -65,6 +65,29 @@ class AppServiceProvider extends ServiceProvider {
|
|||||||
return 'data:image/jpeg;base64,' . base64_encode(file_get_contents(public_path().'/'.$imagePath));
|
return 'data:image/jpeg;base64,' . base64_encode(file_get_contents(public_path().'/'.$imagePath));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
HTML::macro('flatButton', function($label, $color) {
|
||||||
|
return '<input type="button" value="' . trans("texts.{$label}") . '" style="background-color:' . $color . ';border:0 none;border-radius:5px;padding:12px 40px;margin:0 6px;cursor:hand;display:inline-block;font-size:14px;color:#fff;text-transform:none;font-weight:bold;"/>';
|
||||||
|
});
|
||||||
|
|
||||||
|
HTML::macro('emailViewButton', function($link = '#', $entityType = ENTITY_INVOICE) {
|
||||||
|
return view('partials.email_button')
|
||||||
|
->with([
|
||||||
|
'link' => $link,
|
||||||
|
'field' => "view_{$entityType}",
|
||||||
|
'color' => '#0b4d78',
|
||||||
|
])
|
||||||
|
->render();
|
||||||
|
});
|
||||||
|
|
||||||
|
HTML::macro('emailPaymentButton', function($link = '#') {
|
||||||
|
return view('partials.email_button')
|
||||||
|
->with([
|
||||||
|
'link' => $link,
|
||||||
|
'field' => 'pay_now',
|
||||||
|
'color' => '#36c157',
|
||||||
|
])
|
||||||
|
->render();
|
||||||
|
});
|
||||||
|
|
||||||
HTML::macro('breadcrumbs', function() {
|
HTML::macro('breadcrumbs', function() {
|
||||||
$str = '<ol class="breadcrumb">';
|
$str = '<ol class="breadcrumb">';
|
||||||
|
@ -40,7 +40,7 @@ class UserService extends BaseService
|
|||||||
[
|
[
|
||||||
'first_name',
|
'first_name',
|
||||||
function ($model) {
|
function ($model) {
|
||||||
return link_to('users/'.$model->public_id.'/edit', $model->first_name.' '.$model->last_name);
|
return $model->public_id ? link_to('users/'.$model->public_id.'/edit', $model->first_name.' '.$model->last_name) : ($model->first_name.' '.$model->last_name);
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -317,12 +317,12 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->date('due_date')->nullable();
|
$t->date('due_date')->nullable();
|
||||||
$t->text('terms');
|
$t->text('terms');
|
||||||
$t->text('public_notes');
|
$t->text('public_notes');
|
||||||
$t->boolean('is_deleted')->default(false);
|
$t->boolean('is_deleted')->default(false);
|
||||||
$t->boolean('is_recurring');
|
$t->boolean('is_recurring')->default(false);
|
||||||
$t->unsignedInteger('frequency_id');
|
$t->unsignedInteger('frequency_id');
|
||||||
$t->date('start_date')->nullable();
|
$t->date('start_date')->nullable();
|
||||||
$t->date('end_date')->nullable();
|
$t->date('end_date')->nullable();
|
||||||
$t->timestamp('last_sent_date')->nullable();
|
$t->timestamp('last_sent_date')->nullable();
|
||||||
$t->unsignedInteger('recurring_invoice_id')->index()->nullable();
|
$t->unsignedInteger('recurring_invoice_id')->index()->nullable();
|
||||||
|
|
||||||
$t->string('tax_name');
|
$t->string('tax_name');
|
||||||
|
34
database/migrations/2015_11_30_133206_add_email_designs.php
Normal file
34
database/migrations/2015_11_30_133206_add_email_designs.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class AddEmailDesigns extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function ($table) {
|
||||||
|
$table->smallInteger('email_design_id')->default(1);
|
||||||
|
$table->boolean('enable_email_markup')->default(false);
|
||||||
|
$table->string('website')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function ($table) {
|
||||||
|
$table->dropColumn('email_design_id');
|
||||||
|
$table->dropColumn('enable_email_markup');
|
||||||
|
$table->dropColumn('website');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
15
public/css/built.css
vendored
15
public/css/built.css
vendored
@ -3381,4 +3381,19 @@ ul.user-accounts a:hover div.remove {
|
|||||||
|
|
||||||
div.panel-body div.panel-body {
|
div.panel-body div.panel-body {
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.email-button {
|
||||||
|
border: 0 none;
|
||||||
|
border-radius: 36px;
|
||||||
|
|
||||||
|
padding: 12px 45px;
|
||||||
|
margin: 0 10px;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
text-transform: none;
|
||||||
}
|
}
|
@ -31758,7 +31758,7 @@ NINJA.decodeJavascript = function(invoice, javascript)
|
|||||||
} else if (invoice.is_quote && field == 'your_invoice') {
|
} else if (invoice.is_quote && field == 'your_invoice') {
|
||||||
field = 'your_quote';
|
field = 'your_quote';
|
||||||
}
|
}
|
||||||
var label = invoiceLabels[field];
|
var label = invoiceLabels[field];
|
||||||
if (match.indexOf('UC') >= 0) {
|
if (match.indexOf('UC') >= 0) {
|
||||||
label = label.toUpperCase();
|
label = label.toUpperCase();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@ There are two options:
|
|||||||
* [Zapier](https://zapier.com/) integration
|
* [Zapier](https://zapier.com/) integration
|
||||||
* [D3.js](http://d3js.org/) visualizations
|
* [D3.js](http://d3js.org/) visualizations
|
||||||
|
|
||||||
|
### Recommended Providers
|
||||||
|
* [Stripe](https://stripe.com/)
|
||||||
|
* [Postmark](https://postmarkapp.com/)
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
* [Ubuntu and Apache](http://blog.technerdservices.com/index.php/2015/04/techpop-how-to-install-invoice-ninja-on-ubuntu-14-04/)
|
* [Ubuntu and Apache](http://blog.technerdservices.com/index.php/2015/04/techpop-how-to-install-invoice-ninja-on-ubuntu-14-04/)
|
||||||
* [Debian and Nginx](https://www.rosehosting.com/blog/install-invoice-ninja-on-a-debian-7-vps/)
|
* [Debian and Nginx](https://www.rosehosting.com/blog/install-invoice-ninja-on-a-debian-7-vps/)
|
||||||
@ -55,10 +59,6 @@ There are two options:
|
|||||||
* [Jeramy Simpson](https://github.com/JeramyMywork) - [MyWork](https://www.mywork.com.au)
|
* [Jeramy Simpson](https://github.com/JeramyMywork) - [MyWork](https://www.mywork.com.au)
|
||||||
* [Sigitas Limontas](https://lt.linkedin.com/in/sigitaslimontas)
|
* [Sigitas Limontas](https://lt.linkedin.com/in/sigitaslimontas)
|
||||||
|
|
||||||
### Recommended Providers
|
|
||||||
* [Stripe](https://stripe.com/)
|
|
||||||
* [Postmark](https://postmarkapp.com/)
|
|
||||||
|
|
||||||
### Frameworks/Libraries
|
### Frameworks/Libraries
|
||||||
* [laravel/laravel](https://github.com/laravel/laravel) - A PHP Framework For Web Artisans
|
* [laravel/laravel](https://github.com/laravel/laravel) - A PHP Framework For Web Artisans
|
||||||
* [twbs/bootstrap](https://github.com/twbs/bootstrap) - Sleek, intuitive, and powerful front-end framework for faster and easier web development.
|
* [twbs/bootstrap](https://github.com/twbs/bootstrap) - Sleek, intuitive, and powerful front-end framework for faster and easier web development.
|
||||||
|
@ -953,5 +953,16 @@ return array(
|
|||||||
'secret_key' => 'Secret Key',
|
'secret_key' => 'Secret Key',
|
||||||
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
|
'missing_publishable_key' => 'Set your Stripe publishable key for an improved checkout process',
|
||||||
|
|
||||||
|
'email_design' => 'Email Design',
|
||||||
|
'due_by' => 'Due by :date',
|
||||||
|
'enable_email_markup' => 'Enable Email Markup',
|
||||||
|
'enable_email_markup_help' => 'Make it easier for your clients to pay you by adding schema.org markup to your emails.',
|
||||||
|
'template_help_title' => 'Templates Help',
|
||||||
|
'template_help_1' => 'Available variables:',
|
||||||
|
'email_design_id' => 'Email Design',
|
||||||
|
'email_design_help' => 'Make your emails look more professional with HTML layouts',
|
||||||
|
'plain' => 'Plain',
|
||||||
|
'light' => 'Light',
|
||||||
|
'dark' => 'Dark',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
<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>
|
||||||
{!! Former::text('email_subject_' . $field)
|
{!! Former::text('email_subject_' . $field)
|
||||||
->label(trans('texts.subject'))
|
->label(trans('texts.subject'))
|
||||||
|
->appendIcon('question-sign')
|
||||||
|
->addGroupClass('email-subject')
|
||||||
->addClass('enable-' . $field) !!}
|
->addClass('enable-' . $field) !!}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
@ -48,25 +50,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
var editor = new Quill('#{{ $field }}Editor', {
|
var editor = new Quill('#{{ $field }}Editor', {
|
||||||
modules: {
|
modules: {
|
||||||
'toolbar': { container: '#{{ $field }}Toolbar' },
|
'toolbar': { container: '#{{ $field }}Toolbar' },
|
||||||
'link-tooltip': true
|
'link-tooltip': true
|
||||||
},
|
},
|
||||||
theme: 'snow'
|
theme: 'snow'
|
||||||
});
|
|
||||||
editor.setHTML($('#email_template_{{ $field }}').val());
|
|
||||||
editor.on('text-change', function(delta, source) {
|
|
||||||
if (source == 'api') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var html = editors['{{ $field }}'].getHTML();
|
|
||||||
$('#email_template_{{ $field }}').val(html);
|
|
||||||
refreshPreview();
|
|
||||||
NINJA.formIsChanged = true;
|
|
||||||
});
|
|
||||||
editors['{{ $field }}'] = editor;
|
|
||||||
});
|
});
|
||||||
</script>
|
editor.setHTML($('#email_template_{{ $field }}').val());
|
||||||
|
editor.on('text-change', function(delta, source) {
|
||||||
|
if (source == 'api') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var html = editors['{{ $field }}'].getHTML();
|
||||||
|
$('#email_template_{{ $field }}').val(html);
|
||||||
|
refreshPreview();
|
||||||
|
NINJA.formIsChanged = true;
|
||||||
|
});
|
||||||
|
editors['{{ $field }}'] = editor;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.email-subject .input-group-addon').click(function() {
|
||||||
|
$('#templateHelpModal').modal('show');
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
@ -32,9 +32,35 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
{!! Former::populateField("enable_reminder1", intval($account->enable_reminder1)) !!}
|
{!! Former::populateField('enable_reminder1', intval($account->enable_reminder1)) !!}
|
||||||
{!! Former::populateField("enable_reminder2", intval($account->enable_reminder2)) !!}
|
{!! Former::populateField('enable_reminder2', intval($account->enable_reminder2)) !!}
|
||||||
{!! Former::populateField("enable_reminder3", intval($account->enable_reminder3)) !!}
|
{!! Former::populateField('enable_reminder3', intval($account->enable_reminder3)) !!}
|
||||||
|
{!! Former::populateField('enable_email_markup', intval($account->enable_email_markup)) !!}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">{!! trans('texts.email_design') !!}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
{!! Former::select('email_design_id')
|
||||||
|
->style('width: 200px')
|
||||||
|
->addOption(trans('texts.plain'), 1)
|
||||||
|
->addOption(trans('texts.light'), 2)
|
||||||
|
->addOption(trans('texts.dark'), 3)
|
||||||
|
->help(trans('texts.email_design_help')) !!}
|
||||||
|
|
||||||
|
@if (Utils::isNinja())
|
||||||
|
|
||||||
|
{!! Former::checkbox('enable_email_markup')
|
||||||
|
->text(trans('texts.enable_email_markup'))
|
||||||
|
->label('')
|
||||||
|
->help(trans('texts.enable_email_markup_help')) !!}
|
||||||
|
{!! link_to(EMAIL_MARKUP_URL, trans('texts.learn_more'), ['target' => '_blank']) !!}
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
@ -83,6 +109,39 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade" id="templateHelpModal" tabindex="-1" role="dialog" aria-labelledby="templateHelpModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog" style="min-width:150px">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="templateHelpModalLabel">{{ trans('texts.template_help_title') }}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>{{ trans('texts.template_help_1') }}</p>
|
||||||
|
<ul>
|
||||||
|
@foreach (\App\Ninja\Mailers\ContactMailer::$variableFields as $field)
|
||||||
|
<li>${{ $field }}</li>
|
||||||
|
@endforeach
|
||||||
|
@if (count($account->account_gateways) > 1)
|
||||||
|
@foreach (\App\Models\Gateway::$paymentTypes as $type)
|
||||||
|
@if ($account->getGatewayByType($type))
|
||||||
|
<li>${{ \App\Models\Gateway::getPaymentTypeName($type) }}Link</li>
|
||||||
|
<li>${{ \App\Models\Gateway::getPaymentTypeName($type) }}Button</li>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer" style="margin-top: 0px">
|
||||||
|
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ trans('texts.close') }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@if (Auth::user()->isPro())
|
@if (Auth::user()->isPro())
|
||||||
<center>
|
<center>
|
||||||
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
|
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
|
||||||
@ -146,34 +205,29 @@
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
keys = [
|
var keys = {!! json_encode(\App\Ninja\Mailers\ContactMailer::$variableFields) !!};
|
||||||
'footer',
|
var vals = [
|
||||||
'account',
|
|
||||||
'client',
|
|
||||||
'amount',
|
|
||||||
'link',
|
|
||||||
'contact',
|
|
||||||
'firstName',
|
|
||||||
'invoice',
|
|
||||||
'quote'
|
|
||||||
];
|
|
||||||
|
|
||||||
vals = [
|
|
||||||
{!! json_encode($emailFooter) !!},
|
{!! json_encode($emailFooter) !!},
|
||||||
"{{ Auth::user()->account->getDisplayName() }}",
|
"{{ Auth::user()->account->getDisplayName() }}",
|
||||||
"Client Name",
|
"Client Name",
|
||||||
formatMoney(100),
|
formatMoney(100),
|
||||||
"{{ Auth::user()->account->getSiteUrl() . '...' }}",
|
|
||||||
"Contact Name",
|
"Contact Name",
|
||||||
"First Name",
|
"First Name",
|
||||||
"0001",
|
"0001",
|
||||||
"0001"
|
"0001",
|
||||||
|
"{{ URL::to('/view/...') }}",
|
||||||
|
'{!! HTML::flatButton('view_invoice', '#0b4d78') !!}',
|
||||||
|
"{{ URL::to('/payment/...') }}",
|
||||||
|
'{!! HTML::flatButton('pay_now', '#36c157') !!}',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Add any available payment method links
|
// Add any available payment method links
|
||||||
@foreach (\App\Models\Gateway::getPaymentTypeLinks() as $type)
|
@foreach (\App\Models\Gateway::$paymentTypes as $type)
|
||||||
{!! "keys.push('" . $type.'_link' . "');" !!}
|
{!! "keys.push('" . \App\Models\Gateway::getPaymentTypeName($type).'Link' . "');" !!}
|
||||||
{!! "vals.push('" . URL::to("/payment/xxxxxx/{$type}") . "');" !!}
|
{!! "vals.push('" . URL::to('/payment/...') . "');" !!}
|
||||||
|
|
||||||
|
{!! "keys.push('" . \App\Models\Gateway::getPaymentTypeName($type).'Button' . "');" !!}
|
||||||
|
{!! "vals.push('" . HTML::flatButton('pay_now', '#36c157') . "');" !!}
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
for (var i=0; i<keys.length; i++) {
|
for (var i=0; i<keys.length; i++) {
|
||||||
|
@ -1 +0,0 @@
|
|||||||
{!! nl2br($text) !!}
|
|
@ -1 +0,0 @@
|
|||||||
{!! $text !!}
|
|
46
resources/views/emails/design1_html.blade.php
Normal file
46
resources/views/emails/design1_html.blade.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
@extends('emails.master')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#F4F5F5" style="border-collapse: collapse;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="border-collapse: collapse;">
|
||||||
|
<table cellpadding="10" cellspacing="0" border="0" bgcolor="#F4F5F5" width="600" align="center"
|
||||||
|
class="header" style="border-top-width: 6px; border-top-color: {{ $account->primary_color ?: '#2E2B2B' }}; border-top-style: solid;">
|
||||||
|
<tr>
|
||||||
|
<td class="logo" width="208" style="border-collapse: collapse; vertical-align: middle;" valign="middle">
|
||||||
|
@include('emails.partials.account_logo')
|
||||||
|
</td>
|
||||||
|
<td width="183" style="border-collapse: collapse; vertical-align: middle;" valign="middle">
|
||||||
|
<p class="left" style="line-height: 22px; margin: 0; padding: 2px 0 0;">
|
||||||
|
<span style="font-size: 11px; color: #8f8d8e;">
|
||||||
|
@if ($invoice->due_date)
|
||||||
|
{{ strtoupper(trans('texts.due_by', ['date' => $account->formatDate($invoice->due_date)])) }}
|
||||||
|
@endif
|
||||||
|
</span><br />
|
||||||
|
<span style="font-size: 18px;">
|
||||||
|
{{ trans("texts.{$entityType}") }} {{ $invoice->invoice_number }}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td style="border-collapse: collapse; vertical-align: middle;" valign="middle">
|
||||||
|
<p class="right" style="line-height: 14px; margin: 0; padding: 0;">
|
||||||
|
<span style="font-size: 15px; color: #231F20;">
|
||||||
|
{{ trans('texts.' . $invoice->present()->balanceDueLabel) }}:
|
||||||
|
</span><br />
|
||||||
|
<span class="total" style="font-size: 26px; display: block;margin-top: 5px;">
|
||||||
|
{{ $account->formatMoney($invoice->getRequestedAmount(), $client) }}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content" style="border-collapse: collapse;">
|
||||||
|
<div style="font-size: 18px; margin: 42px 40px 42px; padding: 0;">{!! $body !!}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@stop
|
1
resources/views/emails/design1_text.blade.php
Normal file
1
resources/views/emails/design1_text.blade.php
Normal file
@ -0,0 +1 @@
|
|||||||
|
{!! strip_tags($body) !!}
|
46
resources/views/emails/design2_html.blade.php
Normal file
46
resources/views/emails/design2_html.blade.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
@extends('emails.master')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<tr>
|
||||||
|
<td bgcolor="#F4F5F5" style="border-collapse: collapse;"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="border-collapse: collapse;">
|
||||||
|
<table cellpadding="10" cellspacing="0" border="0" bgcolor="{{ $account->primary_color ?: '#2E2B2B' }}" width="600" align="center" class="header"
|
||||||
|
style="border-bottom-width: 6px; border-bottom-color: {{ $account->primary_color ?: '#2E2B2B' }}; border-bottom-style: solid;">
|
||||||
|
<tr>
|
||||||
|
<td class="logo" width="205" style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle">
|
||||||
|
@include('emails.partials.account_logo')
|
||||||
|
</td>
|
||||||
|
<td width="183" style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle">
|
||||||
|
<p class="left" style="line-height: 22px; margin: 3px 0 0; padding: 0;">
|
||||||
|
<span style="font-size: 11px; color: #8f8d8e;">
|
||||||
|
@if ($invoice->due_date)
|
||||||
|
{{ strtoupper(trans('texts.due_by', ['date' => $account->formatDate($invoice->due_date)])) }}
|
||||||
|
@endif
|
||||||
|
</span><br />
|
||||||
|
<span style="font-size: 19px; color: #FFFFFF;">
|
||||||
|
{{ trans("texts.{$entityType}") }} {{ $invoice->invoice_number }}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
<td style="border-collapse: collapse; vertical-align: middle; line-height: 16px;" valign="middle">
|
||||||
|
<p style="margin: 0; padding: 0;">
|
||||||
|
<span style="font-size: 12px; color: #8f8d8e;">
|
||||||
|
{{ strtoupper(trans('texts.' . $invoice->present()->balanceDueLabel)) }}:
|
||||||
|
</span><br />
|
||||||
|
<span class="total" style="font-size: 27px; color: #FFFFFF; margin-top: 5px;display: block;">
|
||||||
|
{{ $account->formatMoney($invoice->getRequestedAmount(), $client) }}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="content" style="border-collapse: collapse;">
|
||||||
|
<div style="font-size: 18px; margin: 42px 40px 42px; padding: 0;">{!! $body !!}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@stop
|
1
resources/views/emails/design2_text.blade.php
Normal file
1
resources/views/emails/design2_text.blade.php
Normal file
@ -0,0 +1 @@
|
|||||||
|
{!! strip_tags($body) !!}
|
@ -4,7 +4,7 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@if (Utils::isNinjaDev())
|
@if ($account->enable_email_markup)
|
||||||
@include('emails.view_action', ['link' => $link, 'entityType' => $entityType])
|
@include('emails.view_action', ['link' => $link, 'entityType' => $entityType])
|
||||||
@endif
|
@endif
|
||||||
{!! $body !!}
|
{!! $body !!}
|
||||||
|
85
resources/views/emails/master.blade.php
Normal file
85
resources/views/emails/master.blade.php
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml" lang="{{ App::getLocale() }}">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body style="min-height: 700px; color: #000000; font-family: Arial, Helvetica, sans-serif; font-size: 12px; -webkit-text-size-adjust: none; -ms-text-size-adjust: none; background: #F4F5F5; margin: 0; padding: 0;"
|
||||||
|
alink="#FF0000" link="#FF0000" bgcolor="#F4F5F5" text="#000000" yahoo="fix">
|
||||||
|
@if ($account->enable_email_markup)
|
||||||
|
@include('emails.view_action', ['link' => $link, 'entityType' => $entityType])
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
.footer a:visited {
|
||||||
|
font-weight: bold; font-size: 10px; color: #A7A6A6; text-decoration: none;
|
||||||
|
}
|
||||||
|
span.yshortcuts:hover {
|
||||||
|
color: #000; background-color: none; border: none;
|
||||||
|
}
|
||||||
|
span.yshortcuts:active {
|
||||||
|
color: #000; background-color: none; border: none;
|
||||||
|
}
|
||||||
|
span.yshortcuts:focus {
|
||||||
|
color: #000; background-color: none; border: none;
|
||||||
|
}
|
||||||
|
a:visited {
|
||||||
|
color: #19BB40; text-decoration: none;
|
||||||
|
}
|
||||||
|
a:focus {
|
||||||
|
color: #19BB40; text-decoration: underline;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #19BB40; text-decoration: underline;
|
||||||
|
}
|
||||||
|
@media only screen and (max-device-width: 480px) {
|
||||||
|
body[yahoo] #container1 {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
body[yahoo] p {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
|
||||||
|
body[yahoo] #container1 {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
body[yahoo] p {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="body_style" style="min-height: 700px; color: #2E2B2B; font-family: Helvetica, sans-serif; font-size: 16px;
|
||||||
|
background: #F4F5F5; padding: 0px 15px;">
|
||||||
|
|
||||||
|
<table cellpadding="0" cellspacing="0" border="0" bgcolor="#FFFFFF" width="600" align="center">
|
||||||
|
|
||||||
|
@yield('content')
|
||||||
|
|
||||||
|
<tr class="footer" style="text-align: center; color: #a7a6a6;" align="center">
|
||||||
|
<td bgcolor="#F4F5F5"
|
||||||
|
style="border-collapse: collapse; padding-top: 32px;">
|
||||||
|
<p style="color: #A7A6A6; font-size: 13px; line-height: 18px; margin: 0 0 7px; padding: 0;">
|
||||||
|
{{ $account->address1 }}
|
||||||
|
@if ($account->address1 && $account->getCityState())
|
||||||
|
-
|
||||||
|
@endif
|
||||||
|
{{ $account->getCityState() }}
|
||||||
|
@if ($account->address1 || $account->getCityState())
|
||||||
|
<br />
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if ($account->website)
|
||||||
|
<strong><a href="{{ $account->website }}" style="color: #A7A6A6; text-decoration: none; font-weight: bold; font-size: 10px;">{{ $account->website }}</a></strong>
|
||||||
|
@endif
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
11
resources/views/emails/partials/account_logo.blade.php
Normal file
11
resources/views/emails/partials/account_logo.blade.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
@if ($account->hasLogo())
|
||||||
|
@if ($account->website)
|
||||||
|
<a href="{{ $account->website }}" style="color: #19BB40; text-decoration: underline;">
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<img src="{{ $message->embed($account->getLogoPath()) }}" style="max-height:50px; max-width:140px; margin-left: 33px;" />
|
||||||
|
|
||||||
|
@if ($account->website)
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
@endif
|
22
resources/views/partials/email_button.blade.php
Normal file
22
resources/views/partials/email_button.blade.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!-- https://gist.github.com/elidickinson/9424116#file-html_email_buttons_1-html -->
|
||||||
|
<div style="display:inline-block;width:190px">
|
||||||
|
<!--[if mso]>
|
||||||
|
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="{{ $link }}" style="height:44px;v-text-anchor:middle;width:180px;" arcsize="10%" stroke="f" fillcolor="{{ $color }}">
|
||||||
|
<w:anchorlock/>
|
||||||
|
<center style="color:#ffffff;font-family:sans-serif;font-size:16px;font-weight:bold;">
|
||||||
|
{{ trans("texts.{$field}") }}
|
||||||
|
</center>
|
||||||
|
</v:roundrect>
|
||||||
|
<![endif]-->
|
||||||
|
<![if !mso]>
|
||||||
|
<table cellspacing="0" cellpadding="0"> <tr>
|
||||||
|
<td align="center" width="180" height="44" bgcolor="{{ $color }}" style="-webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; color: #ffffff; display: block;">
|
||||||
|
<a href="{{ $link }}" style="font-size:16px; font-weight: bold; font-family:sans-serif; text-decoration: none; line-height:44px; width:100%; display:inline-block">
|
||||||
|
<span style="color: #ffffff;">
|
||||||
|
{{ trans("texts.{$field}") }}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr> </table>
|
||||||
|
<![endif]>
|
||||||
|
</div>
|
Loading…
x
Reference in New Issue
Block a user