diff --git a/.env.example b/.env.example
index ce0cd9128663..8ae5c8ae153a 100644
--- a/.env.example
+++ b/.env.example
@@ -20,6 +20,6 @@ MAIL_FROM_ADDRESS
MAIL_FROM_NAME
MAIL_PASSWORD
-PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'
+#PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'
LOG=single
diff --git a/Gruntfile.js b/Gruntfile.js
index 30585856a853..fdd48d76c49d 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -120,13 +120,10 @@ module.exports = function(grunt) {
src: [
'public/vendor/bootstrap/dist/css/bootstrap.min.css',
'public/vendor/font-awesome/css/font-awesome.min.css',
- /*
- 'public/css/bootstrap.splash.css',
- 'public/css/splash.css',
- */
'public/css/bootstrap-combobox.css',
'public/vendor/datatables/media/css/jquery.dataTables.css',
'public/vendor/datatables-bootstrap3/BS3/assets/css/datatables.css',
+ 'public/css/public.style.css',
],
dest: 'public/css/built.public.css',
nonull: true,
diff --git a/app/Console/Commands/SendReminders.php b/app/Console/Commands/SendReminders.php
index 123e086feb30..a2bfdc29da8b 100644
--- a/app/Console/Commands/SendReminders.php
+++ b/app/Console/Commands/SendReminders.php
@@ -36,6 +36,10 @@ class SendReminders extends Command
$this->info(count($accounts).' accounts found');
foreach ($accounts as $account) {
+ if (!$account->isPro()) {
+ continue;
+ }
+
$invoices = $this->invoiceRepo->findNeedingReminding($account);
$this->info($account->name . ': ' . count($invoices).' invoices found');
diff --git a/app/Events/UserSettingsChanged.php b/app/Events/UserSettingsChanged.php
index 02c3a0195875..ead79b390898 100644
--- a/app/Events/UserSettingsChanged.php
+++ b/app/Events/UserSettingsChanged.php
@@ -8,14 +8,16 @@ class UserSettingsChanged extends Event {
use SerializesModels;
+ public $user;
+
/**
* Create a new event instance.
*
* @return void
*/
- public function __construct()
+ public function __construct($user = false)
{
- //
+ $this->user = $user;
}
}
diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php
index 1eb38bcbdc8a..26777a54feba 100644
--- a/app/Http/Controllers/AccountController.php
+++ b/app/Http/Controllers/AccountController.php
@@ -373,8 +373,10 @@ class AccountController extends BaseController
$rules = [];
$user = Auth::user();
$iframeURL = preg_replace('/[^a-zA-Z0-9_\-\:\/\.]/', '', substr(strtolower(Input::get('iframe_url')), 0, MAX_IFRAME_URL_LENGTH));
- $subdomain = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', substr(strtolower(Input::get('subdomain')), 0, MAX_SUBDOMAIN_LENGTH));
- if (!$subdomain || in_array($subdomain, ['www', 'app', 'mail', 'admin', 'blog', 'user', 'contact', 'payment', 'payments', 'billing', 'invoice', 'business', 'owner'])) {
+ $iframeURL = rtrim($iframeURL, "/");
+
+ $subdomain = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', substr(strtolower(Input::get('subdomain')), 0, MAX_SUBDOMAIN_LENGTH));
+ if ($iframeURL || !$subdomain || in_array($subdomain, ['www', 'app', 'mail', 'admin', 'blog', 'user', 'contact', 'payment', 'payments', 'billing', 'invoice', 'business', 'owner'])) {
$subdomain = null;
}
if ($subdomain) {
diff --git a/app/Http/Controllers/ActivityController.php b/app/Http/Controllers/ActivityController.php
index 9704b3adaaad..39419f227df6 100644
--- a/app/Http/Controllers/ActivityController.php
+++ b/app/Http/Controllers/ActivityController.php
@@ -20,14 +20,7 @@ class ActivityController extends BaseController
->addColumn('activities.id', function ($model) { return Utils::timestampToDateTimeString(strtotime($model->created_at)); })
->addColumn('message', function ($model) { return Utils::decodeActivity($model->message); })
->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); })
- ->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? self::wrapAdjustment($model->adjustment, $model->currency_id) : ''; })
+ ->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id) : ''; })
->make();
}
-
- private function wrapAdjustment($adjustment, $currencyId)
- {
- $class = $adjustment <= 0 ? 'success' : 'default';
- $adjustment = Utils::formatMoney($adjustment, $currencyId);
- return "
$adjustment
";
- }
}
diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php
index 5ced7948658e..7d186e29c37b 100644
--- a/app/Http/Controllers/AppController.php
+++ b/app/Http/Controllers/AppController.php
@@ -94,7 +94,7 @@ class AppController extends BaseController
"MAIL_USERNAME={$mail['username']}\n".
"MAIL_FROM_NAME={$mail['from']['name']}\n".
"MAIL_PASSWORD={$mail['password']}\n\n".
- "PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'";
+ "#PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'";
// Write Config Settings
$fp = fopen(base_path()."/.env", 'w');
diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php
index 27e0a1de90fa..2dd1eef286f6 100644
--- a/app/Http/Controllers/InvoiceApiController.php
+++ b/app/Http/Controllers/InvoiceApiController.php
@@ -181,6 +181,10 @@ class InvoiceApiController extends Controller
// initialize the line items
if (isset($data['product_key']) || isset($data['cost']) || isset($data['notes']) || isset($data['qty'])) {
$data['invoice_items'] = [self::prepareItem($data)];
+
+ // make sure the tax isn't applied twice (for the invoice and the line item)
+ unset($data['invoice_items'][0]['tax_name']);
+ unset($data['invoice_items'][0]['tax_rate']);
} else {
foreach ($data['invoice_items'] as $index => $item) {
$data['invoice_items'][$index] = self::prepareItem($item);
diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php
index 948a21532f0e..1c20642d8795 100644
--- a/app/Http/Controllers/InvoiceController.php
+++ b/app/Http/Controllers/InvoiceController.php
@@ -76,28 +76,6 @@ class InvoiceController extends BaseController
return View::make('list', $data);
}
- public function clientIndex()
- {
- $invitationKey = Session::get('invitation_key');
- if (!$invitationKey) {
- app()->abort(404);
- }
-
- $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first();
- $account = $invitation->account;
- $color = $account->primary_color ? $account->primary_color : '#0b4d78';
-
- $data = [
- 'color' => $color,
- 'hideLogo' => $account->isWhiteLabel(),
- 'title' => trans('texts.invoices'),
- 'entityType' => ENTITY_INVOICE,
- 'columns' => Utils::trans(['invoice_number', 'invoice_date', 'invoice_total', 'balance_due', 'due_date']),
- ];
-
- return View::make('public_list', $data);
- }
-
public function getDatatable($clientPublicId = null)
{
$accountId = Auth::user()->account_id;
@@ -106,25 +84,6 @@ class InvoiceController extends BaseController
return $this->invoiceRepo->getDatatable($accountId, $clientPublicId, ENTITY_INVOICE, $search);
}
- public function getClientDatatable()
- {
- $search = Input::get('sSearch');
- $invitationKey = Session::get('invitation_key');
- $invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
-
- if (!$invitation || $invitation->is_deleted) {
- return [];
- }
-
- $invoice = $invitation->invoice;
-
- if (!$invoice || $invoice->is_deleted) {
- return [];
- }
-
- return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_INVOICE, $search);
- }
-
public function getRecurringDatatable($clientPublicId = null)
{
$query = $this->invoiceRepo->getRecurringInvoices(Auth::user()->account_id, $clientPublicId, Input::get('sSearch'));
@@ -172,42 +131,22 @@ class InvoiceController extends BaseController
public function view($invitationKey)
{
- $invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
-
- if (!$invitation) {
- app()->abort(404, trans('texts.invoice_not_found'));
- }
-
+ $invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey);
$invoice = $invitation->invoice;
-
- if (!$invoice || $invoice->is_deleted) {
- app()->abort(404, trans('texts.invoice_not_found'));
- }
-
- $invoice->load('user', 'invoice_items', 'invoice_design', 'account.country', 'client.contacts', 'client.country');
$client = $invoice->client;
- $account = $client->account;
+ $account = $invoice->account;
- if (!$client || $client->is_deleted) {
+ if (!$account->checkSubdomain(Request::server('HTTP_HOST'))) {
app()->abort(404, trans('texts.invoice_not_found'));
}
- if ($account->subdomain) {
- $server = explode('.', Request::server('HTTP_HOST'));
- $subdomain = $server[0];
-
- if (!in_array($subdomain, ['app', 'www']) && $subdomain != $account->subdomain) {
- return View::make('invoices.deleted');
- }
- }
-
if (!Input::has('phantomjs') && !Session::has($invitationKey) && (!Auth::check() || Auth::user()->account_id != $invoice->account_id)) {
Activity::viewInvoice($invitation);
Event::fire(new InvoiceViewed($invoice));
}
- Session::set($invitationKey, true);
- Session::set('invitation_key', $invitationKey);
+ Session::set($invitationKey, true); // track this invitation has been seen
+ Session::set('invitation_key', $invitationKey); // track current invitation
$account->loadLocalizationSettings($client);
@@ -226,27 +165,16 @@ class InvoiceController extends BaseController
'first_name',
'last_name',
'email',
- 'phone', ]);
-
- // Determine payment options
- $paymentTypes = [];
- if ($client->getGatewayToken()) {
- $paymentTypes[] = [
- 'url' => URL::to("payment/{$invitation->invitation_key}/token"), 'label' => trans('texts.use_card_on_file')
- ];
- }
- foreach(Gateway::$paymentTypes as $type) {
- if ($account->getGatewayByType($type)) {
- $typeLink = strtolower(str_replace('PAYMENT_TYPE_', '', $type));
- $paymentTypes[] = [
- 'url' => URL::to("/payment/{$invitation->invitation_key}/{$typeLink}"), 'label' => trans('texts.'.strtolower($type))
- ];
- }
- }
+ 'phone',
+ ]);
+ $paymentTypes = $this->getPaymentTypes($client, $invitation);
$paymentURL = '';
if (count($paymentTypes)) {
$paymentURL = $paymentTypes[0]['url'];
+ if (!$account->isGatewayConfigured(GATEWAY_PAYPAL_EXPRESS)) {
+ $paymentURL = URL::to($paymentURL);
+ }
}
$showApprove = $invoice->quote_invoice_id ? false : true;
@@ -271,6 +199,34 @@ class InvoiceController extends BaseController
return View::make('invoices.view', $data);
}
+ private function getPaymentTypes($client, $invitation)
+ {
+ $paymentTypes = [];
+ $account = $client->account;
+
+ if ($client->getGatewayToken()) {
+ $paymentTypes[] = [
+ 'url' => URL::to("payment/{$invitation->invitation_key}/token"), 'label' => trans('texts.use_card_on_file')
+ ];
+ }
+ foreach(Gateway::$paymentTypes as $type) {
+ if ($account->getGatewayByType($type)) {
+ $typeLink = strtolower(str_replace('PAYMENT_TYPE_', '', $type));
+ $url = URL::to("/payment/{$invitation->invitation_key}/{$typeLink}");
+
+ // PayPal doesn't allow being run in an iframe so we need to open in new tab
+ if ($type === PAYMENT_TYPE_PAYPAL && $account->iframe_url) {
+ $url = 'javascript:window.open("'.$url.'", "_blank")';
+ }
+ $paymentTypes[] = [
+ 'url' => $url, 'label' => trans('texts.'.strtolower($type))
+ ];
+ }
+ }
+
+ return $paymentTypes;
+ }
+
public function edit($publicId, $clone = false)
{
$invoice = Invoice::scope($publicId)->withTrashed()->with('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items')->firstOrFail();
@@ -468,121 +424,138 @@ class InvoiceController extends BaseController
{
$action = Input::get('action');
$entityType = Input::get('entityType');
+ $input = json_decode(Input::get('data'));
if (in_array($action, ['archive', 'delete', 'mark', 'restore'])) {
return InvoiceController::bulk($entityType);
}
- $input = json_decode(Input::get('data'));
- $invoice = $input->invoice;
-
- if ($errors = $this->invoiceRepo->getErrors($invoice)) {
+ if ($errors = $this->invoiceRepo->getErrors($input->invoice)) {
Session::flash('error', trans('texts.invoice_error'));
return Redirect::to("{$entityType}s/create")
->withInput()->withErrors($errors);
} else {
- $this->taxRateRepo->save($input->tax_rates);
-
- $clientData = (array) $invoice->client;
- $client = $this->clientRepo->save($invoice->client->public_id, $clientData);
-
- $invoiceData = (array) $invoice;
- $invoiceData['client_id'] = $client->id;
- $invoice = $this->invoiceRepo->save($publicId, $invoiceData, $entityType);
-
- $account = Auth::user()->account;
- if ($account->invoice_taxes != $input->invoice_taxes
- || $account->invoice_item_taxes != $input->invoice_item_taxes
- || $account->invoice_design_id != $input->invoice->invoice_design_id
- || $account->show_item_taxes != $input->show_item_taxes) {
- $account->invoice_taxes = $input->invoice_taxes;
- $account->invoice_item_taxes = $input->invoice_item_taxes;
- $account->invoice_design_id = $input->invoice->invoice_design_id;
- $account->show_item_taxes = $input->show_item_taxes;
- $account->save();
- }
-
- $client->load('contacts');
- $sendInvoiceIds = [];
-
- foreach ($client->contacts as $contact) {
- if ($contact->send_invoice || count($client->contacts) == 1) {
- $sendInvoiceIds[] = $contact->id;
- }
- }
-
- foreach ($client->contacts as $contact) {
- $invitation = Invitation::scope()->whereContactId($contact->id)->whereInvoiceId($invoice->id)->first();
-
- if (in_array($contact->id, $sendInvoiceIds) && !$invitation) {
- $invitation = Invitation::createNew();
- $invitation->invoice_id = $invoice->id;
- $invitation->contact_id = $contact->id;
- $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
- $invitation->save();
- } elseif (!in_array($contact->id, $sendInvoiceIds) && $invitation) {
- $invitation->delete();
- }
- }
-
+ $invoice = $this->saveInvoice($publicId, $input, $entityType);
+ $url = "{$entityType}s/".$invoice->public_id.'/edit';
$message = trans($publicId ? "texts.updated_{$entityType}" : "texts.created_{$entityType}");
+
+ // check if we created a new client with the invoice
if ($input->invoice->client->public_id == '-1') {
$message = $message.' '.trans('texts.and_created_client');
-
- $url = URL::to('clients/'.$client->public_id);
+ $url = URL::to('clients/'.$input->invoice->client->public_id);
Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT, $url);
}
- if ($invoice->account->pdf_email_attachment && !$invoice->is_recurring) {
- $pdfUpload = Input::get('pdfupload');
- if (!empty($pdfUpload) && strpos($pdfUpload, 'data:application/pdf;base64,') === 0) {
- $invoice->updateCachedPDF($pdfUpload);
- }
- }
-
if ($action == 'clone') {
return $this->cloneInvoice($publicId);
} elseif ($action == 'convert') {
return $this->convertQuote($publicId);
} elseif ($action == 'email') {
- if (Auth::user()->confirmed && !Auth::user()->isDemo()) {
- if ($invoice->is_recurring) {
- if ($invoice->shouldSendToday()) {
- $invoice = $this->invoiceRepo->createRecurringInvoice($invoice);
- // in case auto-bill is enabled
- if ($invoice->isPaid()) {
- $response = true;
- } else {
- $response = $this->mailer->sendInvoice($invoice);
- }
- } else {
- $response = trans('texts.recurring_too_soon');
- }
- } else {
- $response = $this->mailer->sendInvoice($invoice);
- }
- if ($response === true) {
- $message = trans("texts.emailed_{$entityType}");
- Session::flash('message', $message);
- } else {
- Session::flash('error', $response);
- }
- } else {
- $errorMessage = trans(Auth::user()->registered ? 'texts.confirmation_required' : 'texts.registration_required');
- Session::flash('error', $errorMessage);
- Session::flash('message', $message);
- }
- } else {
- Session::flash('message', $message);
+ return $this->emailInvoice($invoice, Input::get('pdfupload'));
}
-
- $url = "{$entityType}s/".$invoice->public_id.'/edit';
-
+
+ Session::flash('message', $message);
return Redirect::to($url);
}
}
+ private function emailInvoice($invoice, $pdfUpload)
+ {
+ $entityType = $invoice->getEntityType();
+ $pdfUpload = Utils::decodePDF($pdfUpload);
+
+ if (!Auth::user()->confirmed) {
+ $errorMessage = trans(Auth::user()->registered ? 'texts.confirmation_required' : 'texts.registration_required');
+ Session::flash('error', $errorMessage);
+ Session::flash('message', $message);
+ return Redirect::to($url);
+ }
+
+ if ($invoice->is_recurring) {
+ $response = $this->emailRecurringInvoice($invoice);
+ } else {
+ $response = $this->mailer->sendInvoice($invoice, false, $pdfUpload);
+ }
+
+ if ($response === true) {
+ $message = trans("texts.emailed_{$entityType}");
+ Session::flash('message', $message);
+ } else {
+ Session::flash('error', $response);
+ }
+
+ return Redirect::to("{$entityType}s/{$invoice->public_id}/edit");
+ }
+
+ private function emailRecurringInvoice(&$invoice)
+ {
+ if (!$invoice->shouldSendToday()) {
+ return trans('texts.recurring_too_soon');
+ }
+
+ // switch from the recurring invoice to the generated invoice
+ $invoice = $this->invoiceRepo->createRecurringInvoice($invoice);
+
+ // in case auto-bill is enabled then a receipt has been sent
+ if ($invoice->isPaid()) {
+ return true;
+ } else {
+ return $this->mailer->sendInvoice($invoice);
+ }
+ }
+
+ private function saveInvoice($publicId, $input, $entityType)
+ {
+ $invoice = $input->invoice;
+
+ $this->taxRateRepo->save($input->tax_rates);
+
+ $clientData = (array) $invoice->client;
+ $client = $this->clientRepo->save($invoice->client->public_id, $clientData);
+
+ $invoiceData = (array) $invoice;
+ $invoiceData['client_id'] = $client->id;
+ $invoice = $this->invoiceRepo->save($publicId, $invoiceData, $entityType);
+
+ $account = Auth::user()->account;
+ if ($account->invoice_taxes != $input->invoice_taxes
+ || $account->invoice_item_taxes != $input->invoice_item_taxes
+ || $account->invoice_design_id != $input->invoice->invoice_design_id
+ || $account->show_item_taxes != $input->show_item_taxes) {
+ $account->invoice_taxes = $input->invoice_taxes;
+ $account->invoice_item_taxes = $input->invoice_item_taxes;
+ $account->invoice_design_id = $input->invoice->invoice_design_id;
+ $account->show_item_taxes = $input->show_item_taxes;
+ $account->save();
+ }
+
+ $client->load('contacts');
+ $sendInvoiceIds = [];
+
+ foreach ($client->contacts as $contact) {
+ if ($contact->send_invoice || count($client->contacts) == 1) {
+ $sendInvoiceIds[] = $contact->id;
+ }
+ }
+
+ foreach ($client->contacts as $contact) {
+ $invitation = Invitation::scope()->whereContactId($contact->id)->whereInvoiceId($invoice->id)->first();
+
+ if (in_array($contact->id, $sendInvoiceIds) && !$invitation) {
+ $invitation = Invitation::createNew();
+ $invitation->invoice_id = $invoice->id;
+ $invitation->contact_id = $contact->id;
+ $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH);
+ $invitation->save();
+ } elseif (!in_array($contact->id, $sendInvoiceIds) && $invitation) {
+ $invitation->delete();
+ }
+ }
+
+ return $invoice;
+ }
+
/**
* Display the specified resource.
*
diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php
index 326f0be4ad82..daa32853ae03 100644
--- a/app/Http/Controllers/PaymentController.php
+++ b/app/Http/Controllers/PaymentController.php
@@ -47,28 +47,6 @@ class PaymentController extends BaseController
));
}
- public function clientIndex()
- {
- $invitationKey = Session::get('invitation_key');
- if (!$invitationKey) {
- app()->abort(404);
- }
-
- $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first();
- $account = $invitation->account;
- $color = $account->primary_color ? $account->primary_color : '#0b4d78';
-
- $data = [
- 'color' => $color,
- 'hideLogo' => $account->isWhiteLabel(),
- 'entityType' => ENTITY_PAYMENT,
- 'title' => trans('texts.payments'),
- 'columns' => Utils::trans(['invoice', 'transaction_reference', 'method', 'payment_amount', 'payment_date'])
- ];
-
- return View::make('public_list', $data);
- }
-
public function getDatatable($clientPublicId = null)
{
$payments = $this->paymentRepo->find($clientPublicId, Input::get('sSearch'));
@@ -114,33 +92,6 @@ class PaymentController extends BaseController
->make();
}
- public function getClientDatatable()
- {
- $search = Input::get('sSearch');
- $invitationKey = Session::get('invitation_key');
- $invitation = Invitation::where('invitation_key', '=', $invitationKey)->with('contact.client')->first();
-
- if (!$invitation) {
- return [];
- }
-
- $invoice = $invitation->invoice;
-
- if (!$invoice || $invoice->is_deleted) {
- return [];
- }
-
- $payments = $this->paymentRepo->findForContact($invitation->contact->id, Input::get('sSearch'));
-
- return Datatable::query($payments)
- ->addColumn('invoice_number', function ($model) { return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number) : $model->invoice_number; })
- ->addColumn('transaction_reference', function ($model) { return $model->transaction_reference ? $model->transaction_reference : 'Manual entry'; })
- ->addColumn('payment_type', function ($model) { return $model->payment_type ? $model->payment_type : ($model->account_gateway_id ? 'Online payment' : ''); })
- ->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); })
- ->addColumn('payment_date', function ($model) { return Utils::dateToString($model->payment_date); })
- ->make();
- }
-
public function create($clientPublicId = 0, $invoicePublicId = 0)
{
$invoices = Invoice::scope()
@@ -549,14 +500,16 @@ class PaymentController extends BaseController
$invitation = Invitation::with('invoice.client.currency', 'invoice.client.account.account_gateways.gateway')->where('transaction_reference', '=', $token)->firstOrFail();
$invoice = $invitation->invoice;
+ $client = $invoice->client;
+ $account = $client->account;
- $accountGateway = $invoice->client->account->getGatewayByType(Session::get('payment_type'));
+ $accountGateway = $account->getGatewayByType(Session::get('payment_type'));
$gateway = $this->paymentService->createGateway($accountGateway);
// Check for Dwolla payment error
if ($accountGateway->isGateway(GATEWAY_DWOLLA) && Input::get('error')) {
$this->error('Dwolla', Input::get('error_description'), $accountGateway);
- return Redirect::to('view/'.$invitation->invitation_key);
+ return Redirect::to($invitation->getLink());
}
try {
@@ -569,20 +522,20 @@ class PaymentController extends BaseController
$payment = $this->paymentService->createPayment($invitation, $ref, $payerId);
Session::flash('message', trans('texts.applied_payment'));
- return Redirect::to('view/'.$invitation->invitation_key);
+ return Redirect::to($invitation->getLink());
} else {
$this->error('offsite', $response->getMessage(), $accountGateway);
- return Redirect::to('view/'.$invitation->invitation_key);
+ return Redirect::to($invitation->getLink());
}
} else {
$payment = $this->paymentService->createPayment($invitation, $token, $payerId);
Session::flash('message', trans('texts.applied_payment'));
- return Redirect::to('view/'.$invitation->invitation_key);
+ return Redirect::to($invitation->getLink());
}
} catch (\Exception $e) {
$this->error('Offsite-uncaught', false, $accountGateway, $e);
- return Redirect::to('view/'.$invitation->invitation_key);
+ return Redirect::to($invitation->getLink());
}
}
diff --git a/app/Http/Controllers/PublicClientController.php b/app/Http/Controllers/PublicClientController.php
new file mode 100644
index 000000000000..187a4eed9dd0
--- /dev/null
+++ b/app/Http/Controllers/PublicClientController.php
@@ -0,0 +1,163 @@
+invoiceRepo = $invoiceRepo;
+ $this->paymentRepo = $paymentRepo;
+ }
+
+ public function dashboard()
+ {
+ $invitation = $this->getInvitation();
+ $account = $invitation->account;
+ $invoice = $invitation->invoice;
+ $client = $invoice->client;
+ $color = $account->primary_color ? $account->primary_color : '#0b4d78';
+
+ $data = [
+ 'color' => $color,
+ 'account' => $account,
+ 'client' => $client,
+ ];
+
+ return response()->view('invited.dashboard', $data);
+ }
+
+ public function activityDatatable()
+ {
+ $invitation = $this->getInvitation();
+ $invoice = $invitation->invoice;
+
+ $query = DB::table('activities')
+ ->join('clients', 'clients.id', '=', 'activities.client_id')
+ ->where('activities.client_id', '=', $invoice->client_id)
+ ->where('activities.adjustment', '!=', 0)
+ ->select('activities.id', 'activities.message', 'activities.created_at', 'clients.currency_id', 'activities.balance', 'activities.adjustment');
+
+ return Datatable::query($query)
+ ->addColumn('activities.id', function ($model) { return Utils::timestampToDateTimeString(strtotime($model->created_at)); })
+ ->addColumn('message', function ($model) { return strip_tags(Utils::decodeActivity($model->message)); })
+ ->addColumn('balance', function ($model) { return Utils::formatMoney($model->balance, $model->currency_id); })
+ ->addColumn('adjustment', function ($model) { return $model->adjustment != 0 ? Utils::wrapAdjustment($model->adjustment, $model->currency_id) : ''; })
+ ->make();
+ }
+
+ public function invoiceIndex()
+ {
+ $invitation = $this->getInvitation();
+ $account = $invitation->account;
+ $color = $account->primary_color ? $account->primary_color : '#0b4d78';
+
+ $data = [
+ 'color' => $color,
+ 'hideLogo' => $account->isWhiteLabel(),
+ 'title' => trans('texts.invoices'),
+ 'entityType' => ENTITY_INVOICE,
+ 'columns' => Utils::trans(['invoice_number', 'invoice_date', 'invoice_total', 'balance_due', 'due_date']),
+ ];
+
+ return response()->view('public_list', $data);
+ }
+
+ public function invoiceDatatable()
+ {
+ $invitation = $this->getInvitation();
+
+ return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_INVOICE, Input::get('sSearch'));
+ }
+
+
+ public function paymentIndex()
+ {
+ $invitation = $this->getInvitation();
+ $account = $invitation->account;
+ $color = $account->primary_color ? $account->primary_color : '#0b4d78';
+
+ $data = [
+ 'color' => $color,
+ 'hideLogo' => $account->isWhiteLabel(),
+ 'entityType' => ENTITY_PAYMENT,
+ 'title' => trans('texts.payments'),
+ 'columns' => Utils::trans(['invoice', 'transaction_reference', 'method', 'payment_amount', 'payment_date'])
+ ];
+
+ return response()->view('public_list', $data);
+ }
+
+ public function paymentDatatable()
+ {
+ $invitation = $this->getInvitation();
+ $payments = $this->paymentRepo->findForContact($invitation->contact->id, Input::get('sSearch'));
+
+ return Datatable::query($payments)
+ ->addColumn('invoice_number', function ($model) { return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number) : $model->invoice_number; })
+ ->addColumn('transaction_reference', function ($model) { return $model->transaction_reference ? $model->transaction_reference : 'Manual entry'; })
+ ->addColumn('payment_type', function ($model) { return $model->payment_type ? $model->payment_type : ($model->account_gateway_id ? 'Online payment' : ''); })
+ ->addColumn('amount', function ($model) { return Utils::formatMoney($model->amount, $model->currency_id); })
+ ->addColumn('payment_date', function ($model) { return Utils::dateToString($model->payment_date); })
+ ->make();
+ }
+
+ public function quoteIndex()
+ {
+ $invitation = $this->getInvitation();
+ $account = $invitation->account;
+ $color = $account->primary_color ? $account->primary_color : '#0b4d78';
+
+ $data = [
+ 'color' => $color,
+ 'hideLogo' => $account->isWhiteLabel(),
+ 'title' => trans('texts.quotes'),
+ 'entityType' => ENTITY_QUOTE,
+ 'columns' => Utils::trans(['quote_number', 'quote_date', 'quote_total', 'due_date']),
+ ];
+
+ return response()->view('public_list', $data);
+ }
+
+
+ public function quoteDatatable()
+ {
+ $invitation = $this->getInvitation();
+
+ return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_QUOTE, Input::get('sSearch'));
+ }
+
+ private function getInvitation()
+ {
+ $invitationKey = session('invitation_key');
+
+ if (!$invitationKey) {
+ app()->abort(404);
+ }
+
+ $invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
+
+ if (!$invitation || $invitation->is_deleted) {
+ app()->abort(404);
+ }
+
+ $invoice = $invitation->invoice;
+
+ if (!$invoice || $invoice->is_deleted) {
+ app()->abort(404);
+ }
+
+ return $invitation;
+ }
+
+}
\ No newline at end of file
diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php
index 07acaa7eb0b0..81445cc089db 100644
--- a/app/Http/Controllers/QuoteController.php
+++ b/app/Http/Controllers/QuoteController.php
@@ -67,28 +67,6 @@ class QuoteController extends BaseController
return View::make('list', $data);
}
- public function clientIndex()
- {
- $invitationKey = Session::get('invitation_key');
- if (!$invitationKey) {
- app()->abort(404);
- }
-
- $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first();
- $account = $invitation->account;
- $color = $account->primary_color ? $account->primary_color : '#0b4d78';
-
- $data = [
- 'color' => $color,
- 'hideLogo' => $account->isWhiteLabel(),
- 'title' => trans('texts.quotes'),
- 'entityType' => ENTITY_QUOTE,
- 'columns' => Utils::trans(['quote_number', 'quote_date', 'quote_total', 'due_date']),
- ];
-
- return View::make('public_list', $data);
- }
-
public function getDatatable($clientPublicId = null)
{
$accountId = Auth::user()->account_id;
@@ -97,25 +75,6 @@ class QuoteController extends BaseController
return $this->invoiceRepo->getDatatable($accountId, $clientPublicId, ENTITY_QUOTE, $search);
}
- public function getClientDatatable()
- {
- $search = Input::get('sSearch');
- $invitationKey = Session::get('invitation_key');
- $invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
-
- if (!$invitation || $invitation->is_deleted) {
- return [];
- }
-
- $invoice = $invitation->invoice;
-
- if (!$invoice || $invoice->is_deleted) {
- return [];
- }
-
- return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_QUOTE, $search);
- }
-
public function create($clientPublicId = 0)
{
if (!Utils::isPro()) {
diff --git a/app/Http/Controllers/old/HomeController.php b/app/Http/Controllers/old/HomeController.php
deleted file mode 100644
index 2050070ab5ef..000000000000
--- a/app/Http/Controllers/old/HomeController.php
+++ /dev/null
@@ -1,36 +0,0 @@
-middleware('auth');
- }
-
- /**
- * Show the application dashboard to the user.
- *
- * @return Response
- */
- public function index()
- {
- return view('home');
- }
-
-}
diff --git a/app/Http/Controllers/old/WelcomeController.php b/app/Http/Controllers/old/WelcomeController.php
deleted file mode 100644
index c7da91c94522..000000000000
--- a/app/Http/Controllers/old/WelcomeController.php
+++ /dev/null
@@ -1,36 +0,0 @@
-middleware('guest');
- }
-
- /**
- * Show the application welcome screen to the user.
- *
- * @return Response
- */
- public function index()
- {
- return view('welcome');
- }
-
-}
diff --git a/app/Http/routes.php b/app/Http/routes.php
index 2ec246b7ce42..1c914e18267c 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -48,12 +48,14 @@ Route::get('approve/{invitation_key}', 'QuoteController@approve');
Route::get('payment/{invitation_key}/{payment_type?}', 'PaymentController@show_payment');
Route::post('payment/{invitation_key}', 'PaymentController@do_payment');
Route::get('complete', 'PaymentController@offsite_payment');
-Route::get('client/quotes', 'QuoteController@clientIndex');
-Route::get('client/invoices', 'InvoiceController@clientIndex');
-Route::get('client/payments', 'PaymentController@clientIndex');
-Route::get('api/client.quotes', array('as'=>'api.client.quotes', 'uses'=>'QuoteController@getClientDatatable'));
-Route::get('api/client.invoices', array('as'=>'api.client.invoices', 'uses'=>'InvoiceController@getClientDatatable'));
-Route::get('api/client.payments', array('as'=>'api.client.payments', 'uses'=>'PaymentController@getClientDatatable'));
+Route::get('client/quotes', 'PublicClientController@quoteIndex');
+Route::get('client/invoices', 'PublicClientController@invoiceIndex');
+Route::get('client/payments', 'PublicClientController@paymentIndex');
+Route::get('client/dashboard', 'PublicClientController@dashboard');
+Route::get('api/client.quotes', array('as'=>'api.client.quotes', 'uses'=>'PublicClientController@quoteDatatable'));
+Route::get('api/client.invoices', array('as'=>'api.client.invoices', 'uses'=>'PublicClientController@invoiceDatatable'));
+Route::get('api/client.payments', array('as'=>'api.client.payments', 'uses'=>'PublicClientController@paymentDatatable'));
+Route::get('api/client.activity', array('as'=>'api.client.activity', 'uses'=>'PublicClientController@activityDatatable'));
Route::get('license', 'PaymentController@show_license_payment');
Route::post('license', 'PaymentController@do_license_payment');
diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php
index 4c50b1059955..65cbfb645a24 100644
--- a/app/Libraries/Utils.php
+++ b/app/Libraries/Utils.php
@@ -94,11 +94,6 @@ class Utils
return isset($_ENV[DEMO_ACCOUNT_ID]) ? $_ENV[DEMO_ACCOUNT_ID] : false;
}
- public static function isDemo()
- {
- return Auth::check() && Auth::user()->isDemo();
- }
-
public static function getNewsFeedResponse($userType = false)
{
if (!$userType) {
@@ -634,6 +629,11 @@ class Utils
];
}
+ public static function isEmpty($value)
+ {
+ return !$value || $value == '0.00' || $value == '0,00';
+ }
+
public static function startsWith($haystack, $needle)
{
return $needle === "" || strpos($haystack, $needle) === 0;
@@ -672,7 +672,8 @@ class Utils
fwrite($output, "\n");
}
- public static function getFirst($values) {
+ public static function getFirst($values)
+ {
if (is_array($values)) {
return count($values) ? $values[0] : false;
} else {
@@ -681,7 +682,8 @@ class Utils
}
// nouns in German and French should be uppercase
- public static function transFlowText($key) {
+ public static function transFlowText($key)
+ {
$str = trans("texts.$key");
if (!in_array(App::getLocale(), ['de', 'fr'])) {
$str = strtolower($str);
@@ -689,7 +691,8 @@ class Utils
return $str;
}
- public static function getSubdomainPlaceholder() {
+ public static function getSubdomainPlaceholder()
+ {
$parts = parse_url(SITE_URL);
$subdomain = '';
if (isset($parts['host'])) {
@@ -701,7 +704,8 @@ class Utils
return $subdomain;
}
- public static function getDomainPlaceholder() {
+ public static function getDomainPlaceholder()
+ {
$parts = parse_url(SITE_URL);
$domain = '';
if (isset($parts['host'])) {
@@ -719,7 +723,8 @@ class Utils
return $domain;
}
- public static function replaceSubdomain($domain, $subdomain) {
+ public static function replaceSubdomain($domain, $subdomain)
+ {
$parsedUrl = parse_url($domain);
$host = explode('.', $parsedUrl['host']);
if (count($host) > 0) {
@@ -729,11 +734,61 @@ class Utils
return $domain;
}
- public static function splitName($name) {
+ public static function splitName($name)
+ {
$name = trim($name);
$lastName = (strpos($name, ' ') === false) ? '' : preg_replace('#.*\s([\w-]*)$#', '$1', $name);
- $firstName = trim( preg_replace('#'.$lastName.'#', '', $name ) );
+ $firstName = trim(preg_replace('#'.$lastName.'#', '', $name));
return array($firstName, $lastName);
}
+ public static function decodePDF($string)
+ {
+ $string = str_replace('data:application/pdf;base64,', '', $string);
+ return base64_decode($string);
+ }
+
+ public static function cityStateZip($city, $state, $postalCode, $swap)
+ {
+ $str = $city;
+
+ if ($state) {
+ if ($str) {
+ $str .= ', ';
+ }
+ $str .= $state;
+ }
+
+ if ($swap) {
+ return $postalCode . ' ' . $str;
+ } else {
+ return $str . ' ' . $postalCode;
+ }
+ }
+
+ public static function formatWebsite($website)
+ {
+ if (!$website) {
+ return '';
+ }
+
+ $link = $website;
+ $title = $website;
+ $prefix = 'http://';
+
+ if (strlen($link) > 7 && substr($link, 0, 7) === $prefix) {
+ $title = substr($title, 7);
+ } else {
+ $link = $prefix.$link;
+ }
+
+ return link_to($link, $title, array('target' => '_blank'));
+ }
+
+ public static function wrapAdjustment($adjustment, $currencyId)
+ {
+ $class = $adjustment <= 0 ? 'success' : 'default';
+ $adjustment = Utils::formatMoney($adjustment, $currencyId);
+ return "$adjustment
";
+ }
}
diff --git a/app/Listeners/HandleUserSettingsChanged.php b/app/Listeners/HandleUserSettingsChanged.php
index 993e30141db0..42598334990f 100644
--- a/app/Listeners/HandleUserSettingsChanged.php
+++ b/app/Listeners/HandleUserSettingsChanged.php
@@ -6,6 +6,7 @@ use App\Events\UserSettingsChanged;
use App\Ninja\Repositories\AccountRepository;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;
+use App\Ninja\Mailers\UserMailer;
class HandleUserSettingsChanged {
@@ -14,9 +15,10 @@ class HandleUserSettingsChanged {
*
* @return void
*/
- public function __construct(AccountRepository $accountRepo)
+ public function __construct(AccountRepository $accountRepo, UserMailer $userMailer)
{
$this->accountRepo = $accountRepo;
+ $this->userMailer = $userMailer;
}
/**
@@ -27,12 +29,19 @@ class HandleUserSettingsChanged {
*/
public function handle(UserSettingsChanged $event)
{
- if (Auth::check()) {
- $account = Auth::user()->account;
- $account->loadLocalizationSettings();
+ if (!Auth::check()) {
+ return;
+ }
- $users = $this->accountRepo->loadAccounts(Auth::user()->id);
- Session::put(SESSION_USER_ACCOUNTS, $users);
+ $account = Auth::user()->account;
+ $account->loadLocalizationSettings();
+
+ $users = $this->accountRepo->loadAccounts(Auth::user()->id);
+ Session::put(SESSION_USER_ACCOUNTS, $users);
+
+ if ($event->user && $event->user->isEmailBeingChanged()) {
+ $this->userMailer->sendConfirmation($event->user);
+ Session::flash('warning', trans('texts.verify_email'));
}
}
diff --git a/app/Models/Account.php b/app/Models/Account.php
index 5d64c68deefb..58295bdd3c8e 100644
--- a/app/Models/Account.php
+++ b/app/Models/Account.php
@@ -114,6 +114,12 @@ class Account extends Eloquent
return $user->getDisplayName();
}
+ public function getCityState()
+ {
+ $swap = $this->country && $this->country->swap_postal_code;
+ return Utils::cityStateZip($this->city, $this->state, $this->postal_code, $swap);
+ }
+
public function getMomentDateTimeFormat()
{
$format = $this->datetime_format ? $this->datetime_format->format_moment : DEFAULT_DATETIME_MOMENT_FORMAT;
@@ -158,12 +164,10 @@ class Account extends Eloquent
return false;
}
- /*
public function hasLogo()
{
- file_exists($this->getLogoPath());
+ return file_exists($this->getLogoPath());
}
- */
public function getLogoPath()
{
@@ -426,11 +430,13 @@ class Account extends Eloquent
public function getEmailSubject($entityType)
{
- $field = "email_subject_{$entityType}";
- $value = $this->$field;
+ if ($this->isPro()) {
+ $field = "email_subject_{$entityType}";
+ $value = $this->$field;
- if ($value) {
- return $value;
+ if ($value) {
+ return $value;
+ }
}
return $this->getDefaultEmailSubject($entityType);
@@ -455,13 +461,15 @@ class Account extends Eloquent
public function getEmailTemplate($entityType, $message = false)
{
- $field = "email_template_{$entityType}";
- $template = $this->$field;
+ if ($this->isPro()) {
+ $field = "email_template_{$entityType}";
+ $template = $this->$field;
- if ($template) {
- return $template;
+ if ($template) {
+ return $template;
+ }
}
-
+
return $this->getDefaultEmailTemplate($entityType, $message);
}
@@ -503,6 +511,43 @@ class Account extends Eloquent
return $url;
}
+
+ public function checkSubdomain($host)
+ {
+ if (!$this->subdomain) {
+ return true;
+ }
+
+ $server = explode('.', $host);
+ $subdomain = $server[0];
+
+ if (!in_array($subdomain, ['app', 'www']) && $subdomain != $this->subdomain) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function showCustomField($field, $entity)
+ {
+ if ($this->isPro()) {
+ return $this->$field ? true : false;
+ }
+
+ if (!$entity) {
+ return false;
+ }
+
+ // convert (for example) 'custom_invoice_label1' to 'invoice.custom_value1'
+ $field = str_replace(['invoice_', 'label'], ['', 'value'], $field);
+
+ return Utils::isEmpty($entity->$field) ? false : true;
+ }
+
+ public function attatchPDF()
+ {
+ return $this->isPro() && $this->pdf_email_attachment;
+ }
}
Account::updated(function ($account) {
diff --git a/app/Models/Client.php b/app/Models/Client.php
index 4cc960f77ecf..7fa606bd7664 100644
--- a/app/Models/Client.php
+++ b/app/Models/Client.php
@@ -1,5 +1,6 @@
getDisplayName();
}
+ public function getCityState()
+ {
+ $swap = $this->country && $this->country->swap_postal_code;
+ return Utils::cityStateZip($this->city, $this->state, $this->postal_code, $swap);
+ }
+
public function getEntityType()
{
return ENTITY_CLIENT;
@@ -113,25 +120,6 @@ class Client extends EntityModel
return false;
}
- public function getWebsite()
- {
- if (!$this->website) {
- return '';
- }
-
- $link = $this->website;
- $title = $this->website;
- $prefix = 'http://';
-
- if (strlen($link) > 7 && substr($link, 0, 7) === $prefix) {
- $title = substr($title, 7);
- } else {
- $link = $prefix.$link;
- }
-
- return link_to($link, $title, array('target' => '_blank'));
- }
-
public function getDateCreated()
{
if ($this->created_at == '0000-00-00 00:00:00') {
diff --git a/app/Models/Invitation.php b/app/Models/Invitation.php
index b42bcfbaa80b..2d3c58f439e2 100644
--- a/app/Models/Invitation.php
+++ b/app/Models/Invitation.php
@@ -36,13 +36,15 @@ class Invitation extends EntityModel
$url = SITE_URL;
$iframe_url = $this->account->iframe_url;
-
- if ($iframe_url) {
- return "{$iframe_url}/?{$this->invitation_key}";
- } elseif ($this->account->subdomain) {
- $url = Utils::replaceSubdomain($url, $this->account->subdomain);
+
+ if ($this->account->isPro()) {
+ if ($iframe_url) {
+ return "{$iframe_url}/?{$this->invitation_key}";
+ } elseif ($this->account->subdomain) {
+ $url = Utils::replaceSubdomain($url, $this->account->subdomain);
+ }
}
-
+
return "{$url}/view/{$this->invitation_key}";
}
diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php
index 9233d3da2188..f407cc3a972f 100644
--- a/app/Models/Invoice.php
+++ b/app/Models/Invoice.php
@@ -285,37 +285,36 @@ class Invoice extends EntityModel
return false;
}
- public function updateCachedPDF($encodedString = false)
+ public function getPDFString()
{
- if (!$encodedString && env('PHANTOMJS_CLOUD_KEY')) {
- $invitation = $this->invitations[0];
- $link = $invitation->getLink();
-
- $curl = curl_init();
- $jsonEncodedData = json_encode([
- 'targetUrl' => "{$link}?phantomjs=true",
- 'requestType' => 'raw',
- 'delayTime' => 3000,
- ]);
-
- $opts = [
- CURLOPT_URL => PHANTOMJS_CLOUD . env('PHANTOMJS_CLOUD_KEY'),
- CURLOPT_RETURNTRANSFER => true,
- CURLOPT_CUSTOMREQUEST => 'POST',
- CURLOPT_POST => 1,
- CURLOPT_POSTFIELDS => $jsonEncodedData,
- CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: '.strlen($jsonEncodedData)],
- ];
-
- curl_setopt_array($curl, $opts);
- $encodedString = strip_tags(curl_exec($curl));
- curl_close($curl);
- }
-
- $encodedString = str_replace('data:application/pdf;base64,', '', $encodedString);
- if ($encodedString = base64_decode($encodedString)) {
- file_put_contents($this->getPDFPath(), $encodedString);
+ if (!env('PHANTOMJS_CLOUD_KEY')) {
+ return false;
}
+
+ $invitation = $this->invitations[0];
+ $link = $invitation->getLink();
+
+ $curl = curl_init();
+ $jsonEncodedData = json_encode([
+ 'targetUrl' => "{$link}?phantomjs=true",
+ 'requestType' => 'raw',
+ 'delayTime' => 1000,
+ ]);
+
+ $opts = [
+ CURLOPT_URL => PHANTOMJS_CLOUD . env('PHANTOMJS_CLOUD_KEY'),
+ CURLOPT_RETURNTRANSFER => true,
+ CURLOPT_CUSTOMREQUEST => 'POST',
+ CURLOPT_POST => 1,
+ CURLOPT_POSTFIELDS => $jsonEncodedData,
+ CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Content-Length: '.strlen($jsonEncodedData)],
+ ];
+
+ curl_setopt_array($curl, $opts);
+ $encodedString = strip_tags(curl_exec($curl));
+ curl_close($curl);
+
+ return Utils::decodePDF($encodedString);
}
}
diff --git a/app/Models/User.php b/app/Models/User.php
index de750d4e71dc..1a469db403aa 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -96,11 +96,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return $this->account->isPro();
}
- public function isDemo()
- {
- return $this->account->id == Utils::getDemoAccountId();
- }
-
public function maxInvoiceDesignId()
{
return $this->isPro() ? 11 : (Utils::isNinja() ? COUNT_FREE_DESIGNS : COUNT_FREE_DESIGNS_SELF_HOST);
@@ -135,27 +130,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
{
return Session::get(SESSION_COUNTER, 0);
}
-
- /*
- public function getPopOverText()
- {
- if (!Utils::isNinja() || !Auth::check() || Session::has('error')) {
- return false;
- }
-
- $count = self::getRequestsCount();
-
- if ($count == 1 || $count % 5 == 0) {
- if (!Utils::isRegistered()) {
- return trans('texts.sign_up_to_save');
- } elseif (!Auth::user()->account->name) {
- return trans('texts.set_name');
- }
- }
-
- return false;
- }
- */
public function afterSave($success = true, $forced = false)
{
@@ -209,6 +183,12 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
if ($user->password != $user->getOriginal('password')) {
$user->failed_logins = 0;
}
+
+ // if the user changes their email then they need to reconfirm it
+ if ($user->isEmailBeingChanged()) {
+ $user->confirmed = 0;
+ $user->confirmation_code = str_random(RANDOM_KEY_LENGTH);
+ }
}
public static function onUpdatedUser($user)
@@ -219,7 +199,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
event(new UserSignedUp());
}
- event(new UserSettingsChanged());
+ event(new UserSettingsChanged($user));
+ }
+
+ public function isEmailBeingChanged()
+ {
+ return Utils::isNinjaProd()
+ && $this->email != $this->getOriginal('email')
+ && $this->getOriginal('confirmed');
}
}
diff --git a/app/Ninja/Mailers/ContactMailer.php b/app/Ninja/Mailers/ContactMailer.php
index e7200609c529..7cb322e01dcd 100644
--- a/app/Ninja/Mailers/ContactMailer.php
+++ b/app/Ninja/Mailers/ContactMailer.php
@@ -13,7 +13,7 @@ use App\Events\InvoiceSent;
class ContactMailer extends Mailer
{
- public function sendInvoice(Invoice $invoice, $reminder = false)
+ public function sendInvoice(Invoice $invoice, $reminder = false, $pdfString = false)
{
$invoice->load('invitations', 'client.language', 'account');
$entityType = $invoice->getEntityType();
@@ -26,18 +26,17 @@ class ContactMailer extends Mailer
}
$account->loadLocalizationSettings($client);
-
- if ($account->pdf_email_attachment) {
- $invoice->updateCachedPDF();
- }
-
$emailTemplate = $account->getEmailTemplate($reminder ?: $entityType);
$emailSubject = $account->getEmailSubject($reminder ?: $entityType);
$sent = false;
+ if ($account->attatchPDF() && !$pdfString) {
+ $pdfString = $invoice->getPDFString();
+ }
+
foreach ($invoice->invitations as $invitation) {
- if ($this->sendInvitation($invitation, $invoice, $emailTemplate, $emailSubject)) {
+ if ($this->sendInvitation($invitation, $invoice, $emailTemplate, $emailSubject, $pdfString)) {
$sent = true;
}
}
@@ -51,7 +50,7 @@ class ContactMailer extends Mailer
return $sent ?: trans('texts.email_error');
}
- private function sendInvitation($invitation, $invoice, $body, $subject)
+ private function sendInvitation($invitation, $invoice, $body, $subject, $pdfString)
{
$client = $invoice->client;
$account = $invoice->account;
@@ -80,11 +79,18 @@ class ContactMailer extends Mailer
'amount' => $invoice->getRequestedAmount()
];
- $data['body'] = $this->processVariables($body, $variables);
- $data['link'] = $invitation->getLink();
- $data['entityType'] = $invoice->getEntityType();
- $data['invoiceId'] = $invoice->id;
- $data['invitation'] = $invitation;
+ $data = [
+ 'body' => $this->processVariables($body, $variables),
+ 'link' => $invitation->getLink(),
+ 'entityType' => $invoice->getEntityType(),
+ 'invoiceId' => $invoice->id,
+ 'invitation' => $invitation,
+ ];
+
+ if ($account->attatchPDF()) {
+ $data['pdfString'] = $pdfString;
+ $data['pdfFileName'] = $invoice->getFileName();
+ }
$subject = $this->processVariables($subject, $variables);
$fromEmail = $user->email;
@@ -131,13 +137,16 @@ class ContactMailer extends Mailer
$data = [
'body' => $this->processVariables($emailTemplate, $variables)
];
- $subject = $this->processVariables($emailSubject, $variables);
- $data['invoice_id'] = $payment->invoice->id;
- if ($invoice->account->pdf_email_attachment) {
- $invoice->updateCachedPDF();
+ if ($account->attatchPDF()) {
+ $data['pdfString'] = $invoice->getPDFString();
+ $data['pdfFileName'] = $invoice->getFileName();
}
+ $subject = $this->processVariables($emailSubject, $variables);
+ $data['invoice_id'] = $payment->invoice->id;
+ $invoice->updateCachedPDF();
+
if ($user->email && $contact->email) {
$this->sendTo($contact->email, $user->email, $accountName, $subject, $view, $data);
}
diff --git a/app/Ninja/Mailers/Mailer.php b/app/Ninja/Mailers/Mailer.php
index dfe44015d24a..c258216b33ea 100644
--- a/app/Ninja/Mailers/Mailer.php
+++ b/app/Ninja/Mailers/Mailer.php
@@ -31,14 +31,8 @@ class Mailer
->subject($subject);
// Attach the PDF to the email
- if (isset($data['invoiceId'])) {
- $invoice = Invoice::with('account')->where('id', '=', $data['invoiceId'])->first();
- if ($invoice->account->pdf_email_attachment && file_exists($invoice->getPDFPath())) {
- $message->attach(
- $invoice->getPDFPath(),
- array('as' => $invoice->getFileName(), 'mime' => 'application/pdf')
- );
- }
+ if (!empty($data['pdfString']) && !empty($data['pdfFileName'])) {
+ $message->attachData($data['pdfString'], $data['pdfFileName']);
}
});
@@ -54,7 +48,7 @@ class Mailer
$invitation = $data['invitation'];
// Track the Postmark message id
- if (isset($_ENV['POSTMARK_API_TOKEN'])) {
+ if (isset($_ENV['POSTMARK_API_TOKEN']) && $response) {
$json = $response->json();
$invitation->message_id = $json['MessageID'];
}
diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php
index ea5d2251240e..69a9b137d929 100644
--- a/app/Ninja/Repositories/InvoiceRepository.php
+++ b/app/Ninja/Repositories/InvoiceRepository.php
@@ -285,7 +285,7 @@ class InvoiceRepository
if (!$publicId) {
$invoice->client_id = $data['client_id'];
- $invoice->is_recurring = $data['is_recurring'] && !Utils::isDemo() ? true : false;
+ $invoice->is_recurring = $data['is_recurring'] ? true : false;
}
if ($invoice->is_recurring) {
@@ -576,6 +576,28 @@ class InvoiceRepository
return count($invoices);
}
+ public function findInvoiceByInvitation($invitationKey)
+ {
+ $invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
+ if (!$invitation) {
+ app()->abort(404, trans('texts.invoice_not_found'));
+ }
+
+ $invoice = $invitation->invoice;
+ if (!$invoice || $invoice->is_deleted) {
+ app()->abort(404, trans('texts.invoice_not_found'));
+ }
+
+ $invoice->load('user', 'invoice_items', 'invoice_design', 'account.country', 'client.contacts', 'client.country');
+ $client = $invoice->client;
+
+ if (!$client || $client->is_deleted) {
+ app()->abort(404, trans('texts.invoice_not_found'));
+ }
+
+ return $invitation;
+ }
+
public function findOpenInvoices($clientId)
{
return Invoice::scope()
@@ -666,10 +688,6 @@ class InvoiceRepository
}
}
- if ($recurInvoice->account->pdf_email_attachment) {
- $invoice->updateCachedPDF();
- }
-
return $invoice;
}
diff --git a/bootstrap/app.php b/bootstrap/app.php
index f50a3f720632..354e5dd90538 100644
--- a/bootstrap/app.php
+++ b/bootstrap/app.php
@@ -52,4 +52,10 @@ $app->singleton(
|
*/
+/*
+if (strstr($_SERVER['HTTP_USER_AGENT'], 'PhantomJS') && Utils::isNinjaDev()) {
+ $app->loadEnvironmentFrom('.env.testing');
+}
+*/
+
return $app;
diff --git a/composer.lock b/composer.lock
index fa625eb6b2cd..7c1534c5c2ea 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1646,12 +1646,12 @@
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
- "reference": "44c9a6bb292e50cf8a1e4b5030c7954c2709c089"
+ "reference": "e6c9cd03d6b2a870e74da03332feeb97d477fc87"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Intervention/image/zipball/44c9a6bb292e50cf8a1e4b5030c7954c2709c089",
- "reference": "44c9a6bb292e50cf8a1e4b5030c7954c2709c089",
+ "url": "https://api.github.com/repos/Intervention/image/zipball/e6c9cd03d6b2a870e74da03332feeb97d477fc87",
+ "reference": "e6c9cd03d6b2a870e74da03332feeb97d477fc87",
"shasum": ""
},
"require": {
@@ -1700,7 +1700,7 @@
"thumbnail",
"watermark"
],
- "time": "2015-08-30 15:37:50"
+ "time": "2015-10-12 08:42:50"
},
{
"name": "ircmaxell/password-compat",
@@ -2312,12 +2312,12 @@
"source": {
"type": "git",
"url": "https://github.com/lokielse/omnipay-alipay.git",
- "reference": "87622e8549b50773a8db83c93c3ad9a22e618991"
+ "reference": "cbfbee089e0a84a58c73e9d3794894b81a6a82d6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/lokielse/omnipay-alipay/zipball/87622e8549b50773a8db83c93c3ad9a22e618991",
- "reference": "87622e8549b50773a8db83c93c3ad9a22e618991",
+ "url": "https://api.github.com/repos/lokielse/omnipay-alipay/zipball/cbfbee089e0a84a58c73e9d3794894b81a6a82d6",
+ "reference": "cbfbee089e0a84a58c73e9d3794894b81a6a82d6",
"shasum": ""
},
"require": {
@@ -2353,7 +2353,7 @@
"payment",
"purchase"
],
- "time": "2015-09-15 16:43:43"
+ "time": "2015-10-07 09:33:48"
},
{
"name": "maximebf/debugbar",
@@ -6199,16 +6199,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "2.2.3",
+ "version": "2.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f"
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef1ca6835468857944d5c3b48fa503d5554cff2f",
- "reference": "ef1ca6835468857944d5c3b48fa503d5554cff2f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
+ "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
"shasum": ""
},
"require": {
@@ -6257,7 +6257,7 @@
"testing",
"xunit"
],
- "time": "2015-09-14 06:51:16"
+ "time": "2015-10-06 15:47:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -6439,16 +6439,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "4.8.10",
+ "version": "4.8.12",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "463163747474815c5ccd4ae12b5b355ec12158e8"
+ "reference": "00194eb95989190a73198390ceca081ad3441a7f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/463163747474815c5ccd4ae12b5b355ec12158e8",
- "reference": "463163747474815c5ccd4ae12b5b355ec12158e8",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/00194eb95989190a73198390ceca081ad3441a7f",
+ "reference": "00194eb95989190a73198390ceca081ad3441a7f",
"shasum": ""
},
"require": {
@@ -6507,7 +6507,7 @@
"testing",
"xunit"
],
- "time": "2015-10-01 09:14:30"
+ "time": "2015-10-12 03:36:47"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -6799,16 +6799,16 @@
},
{
"name": "sebastian/global-state",
- "version": "1.0.0",
+ "version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01"
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
- "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
+ "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
"shasum": ""
},
"require": {
@@ -6846,7 +6846,7 @@
"keywords": [
"global state"
],
- "time": "2014-10-06 09:23:50"
+ "time": "2015-10-12 03:26:01"
},
{
"name": "sebastian/recursion-context",
diff --git a/config/queue.php b/config/queue.php
index 9c39a13644a1..30e8e8b9d10b 100644
--- a/config/queue.php
+++ b/config/queue.php
@@ -59,10 +59,10 @@ return [
'iron' => [
'driver' => 'iron',
- 'host' => 'mq-aws-us-east-1.iron.io',
- 'token' => 'your-token',
- 'project' => 'your-project-id',
- 'queue' => 'your-queue-name',
+ 'host' => env('QUEUE_HOST', 'mq-aws-us-east-1.iron.io'),
+ 'token' => env('QUEUE_TOKEN'),
+ 'project' => env('QUEUE_PROJECT'),
+ 'queue' => env('QUEUE_NAME'),
'encrypt' => true,
],
diff --git a/public/css/bootstrap.splash.css b/public/css/bootstrap.splash.css
deleted file mode 100644
index f4d6a1e3b90e..000000000000
--- a/public/css/bootstrap.splash.css
+++ /dev/null
@@ -1,11 +0,0 @@
-/*!
- * Bootstrap v3.0.3
- *
- * Copyright 2013 Twitter, Inc
- * Licensed under the Apache License v2.0
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Designed and built with all the love in the world @twitter by @mdo and @fat.
- */
-
-article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}audio,canvas,video{display:inline-block;}audio:not([controls]){display:none;height:0;}[hidden],template{display:none;}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;}body{margin:0;}a{background:transparent;}a:focus{outline:thin dotted;}a:active,a:hover{outline:0;}h1{font-size:2em;margin:0.67em 0;}abbr[title]{border-bottom:1px dotted;}b,strong{font-weight:bold;}dfn{font-style:italic;}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}mark{background:#ff0;color:#000;}code,kbd,pre,samp{font-family:monospace, serif;font-size:1em;}pre{white-space:pre-wrap;}q{quotes:"\201C" "\201D" "\2018" "\2019";}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sup{top:-0.5em;}sub{bottom:-0.25em;}img{border:0;}svg:not(:root){overflow:hidden;}figure{margin:0;}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}legend{border:0;padding:0;}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;}button,input{line-height:normal;}button,select{text-transform:none;}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}button[disabled],html input[disabled]{cursor:default;}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}textarea{overflow:auto;vertical-align:top;}table{border-collapse:collapse;border-spacing:0;}@media print{*{text-shadow:none !important;color:#000 !important;background:transparent !important;box-shadow:none !important;} a,a:visited{text-decoration:underline;} a[href]:after{content:" (" attr(href) ")";} abbr[title]:after{content:" (" attr(title) ")";} a[href^="javascript:"]:after,a[href^="#"]:after{content:"";} pre,blockquote{border:1px solid #999;page-break-inside:avoid;} thead{display:table-header-group;} tr,img{page-break-inside:avoid;} img{max-width:100% !important;} @page {margin:2cm .5cm;}p,h2,h3{orphans:3;widows:3;} h2,h3{page-break-after:avoid;} select{background:#fff !important;} .navbar{display:none;} .table td,.table th{background-color:#fff !important;} .btn>.caret,.dropup>.btn>.caret{border-top-color:#000 !important;} .label{border:1px solid #000;} .table{border-collapse:collapse !important;} .table-bordered th,.table-bordered td{border:1px solid #ddd !important;}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#4f4747;background-color:#f1f1f1;}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;}a{color:#2299c0;text-decoration:none;}a:hover,a:focus{color:#16657f;text-decoration:underline;}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}img{vertical-align:middle;}.img-responsive{display:block;max-width:100%;height:auto;}.img-rounded{border-radius:6px;}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#f1f1f1;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;display:inline-block;max-width:100%;height:auto;}.img-circle{border-radius:50%;}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee;}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);border:0;}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;color:inherit;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:normal;line-height:1;color:#999999;}h1,h2,h3{margin-top:20px;margin-bottom:10px;}h1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%;}h4,h5,h6{margin-top:10px;margin-bottom:10px;}h4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%;}h1,.h1{font-size:36px;}h2,.h2{font-size:30px;}h3,.h3{font-size:24px;}h4,.h4{font-size:18px;}h5,.h5{font-size:14px;}h6,.h6{font-size:12px;}p{margin:0 0 10px;}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4;}@media (min-width:768px){.lead{font-size:21px;}}small,.small{font-size:85%;}cite{font-style:normal;}.text-muted{color:#999999;}.text-primary{color:#edd71e;}.text-primary:hover{color:#c8b410;}.text-warning{color:#8a6d3b;}.text-warning:hover{color:#66512c;}.text-danger{color:#a94442;}.text-danger:hover{color:#843534;}.text-success{color:#3c763d;}.text-success:hover{color:#2b542c;}.text-info{color:#31708f;}.text-info:hover{color:#245269;}.text-left{text-align:left;}.text-right{text-align:right;}.text-center{text-align:center;}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee;}ul,ol{margin-top:0;margin-bottom:10px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:0;}.list-unstyled{padding-left:0;list-style:none;}.list-inline{padding-left:0;list-style:none;}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px;}.list-inline>li:first-child{padding-left:0;}dl{margin-top:0;margin-bottom:20px;}dt,dd{line-height:1.428571429;}dt{font-weight:bold;}dd{margin-left:0;}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;} .dl-horizontal dd{margin-left:180px;}.dl-horizontal dd:before,.dl-horizontal dd:after{content:" ";display:table;} .dl-horizontal dd:after{clear:both;} .dl-horizontal dd:before,.dl-horizontal dd:after{content:" ";display:table;} .dl-horizontal dd:after{clear:both;}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999;}.initialism{font-size:90%;text-transform:uppercase;}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25;}blockquote p:last-child{margin-bottom:0;}blockquote small,blockquote .small{display:block;line-height:1.428571429;color:#999999;}blockquote small:before,blockquote .small:before{content:'\2014 \00A0';}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small,blockquote.pull-right .small{text-align:right;}blockquote.pull-right small:before,blockquote.pull-right .small:before{content:'';}blockquote.pull-right small:after,blockquote.pull-right .small:after{content:'\00A0 \2014';}blockquote:before,blockquote:after{content:"";}address{margin-bottom:20px;font-style:normal;line-height:1.428571429;}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace;}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px;}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333333;background-color:#f5f5f5;border:1px solid #cccccc;border-radius:4px;}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0;}.pre-scrollable{max-height:340px;overflow-y:scroll;}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;}.container:before,.container:after{content:" ";display:table;}.container:after{clear:both;}.container:before,.container:after{content:" ";display:table;}.container:after{clear:both;}@media (min-width:768px){.container{width:750px;}}@media (min-width:992px){.container{width:970px;}}@media (min-width:1200px){.container{width:1170px;}}.row{margin-left:-15px;margin-right:-15px;}.row:before,.row:after{content:" ";display:table;}.row:after{clear:both;}.row:before,.row:after{content:" ";display:table;}.row:after{clear:both;}.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px;}.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12{float:left;}.col-xs-12{width:100%;}.col-xs-11{width:91.66666666666666%;}.col-xs-10{width:83.33333333333334%;}.col-xs-9{width:75%;}.col-xs-8{width:66.66666666666666%;}.col-xs-7{width:58.333333333333336%;}.col-xs-6{width:50%;}.col-xs-5{width:41.66666666666667%;}.col-xs-4{width:33.33333333333333%;}.col-xs-3{width:25%;}.col-xs-2{width:16.666666666666664%;}.col-xs-1{width:8.333333333333332%;}.col-xs-pull-12{right:100%;}.col-xs-pull-11{right:91.66666666666666%;}.col-xs-pull-10{right:83.33333333333334%;}.col-xs-pull-9{right:75%;}.col-xs-pull-8{right:66.66666666666666%;}.col-xs-pull-7{right:58.333333333333336%;}.col-xs-pull-6{right:50%;}.col-xs-pull-5{right:41.66666666666667%;}.col-xs-pull-4{right:33.33333333333333%;}.col-xs-pull-3{right:25%;}.col-xs-pull-2{right:16.666666666666664%;}.col-xs-pull-1{right:8.333333333333332%;}.col-xs-pull-0{right:0%;}.col-xs-push-12{left:100%;}.col-xs-push-11{left:91.66666666666666%;}.col-xs-push-10{left:83.33333333333334%;}.col-xs-push-9{left:75%;}.col-xs-push-8{left:66.66666666666666%;}.col-xs-push-7{left:58.333333333333336%;}.col-xs-push-6{left:50%;}.col-xs-push-5{left:41.66666666666667%;}.col-xs-push-4{left:33.33333333333333%;}.col-xs-push-3{left:25%;}.col-xs-push-2{left:16.666666666666664%;}.col-xs-push-1{left:8.333333333333332%;}.col-xs-push-0{left:0%;}.col-xs-offset-12{margin-left:100%;}.col-xs-offset-11{margin-left:91.66666666666666%;}.col-xs-offset-10{margin-left:83.33333333333334%;}.col-xs-offset-9{margin-left:75%;}.col-xs-offset-8{margin-left:66.66666666666666%;}.col-xs-offset-7{margin-left:58.333333333333336%;}.col-xs-offset-6{margin-left:50%;}.col-xs-offset-5{margin-left:41.66666666666667%;}.col-xs-offset-4{margin-left:33.33333333333333%;}.col-xs-offset-3{margin-left:25%;}.col-xs-offset-2{margin-left:16.666666666666664%;}.col-xs-offset-1{margin-left:8.333333333333332%;}.col-xs-offset-0{margin-left:0%;}@media (min-width:768px){.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12{float:left;} .col-sm-12{width:100%;} .col-sm-11{width:91.66666666666666%;} .col-sm-10{width:83.33333333333334%;} .col-sm-9{width:75%;} .col-sm-8{width:66.66666666666666%;} .col-sm-7{width:58.333333333333336%;} .col-sm-6{width:50%;} .col-sm-5{width:41.66666666666667%;} .col-sm-4{width:33.33333333333333%;} .col-sm-3{width:25%;} .col-sm-2{width:16.666666666666664%;} .col-sm-1{width:8.333333333333332%;} .col-sm-pull-12{right:100%;} .col-sm-pull-11{right:91.66666666666666%;} .col-sm-pull-10{right:83.33333333333334%;} .col-sm-pull-9{right:75%;} .col-sm-pull-8{right:66.66666666666666%;} .col-sm-pull-7{right:58.333333333333336%;} .col-sm-pull-6{right:50%;} .col-sm-pull-5{right:41.66666666666667%;} .col-sm-pull-4{right:33.33333333333333%;} .col-sm-pull-3{right:25%;} .col-sm-pull-2{right:16.666666666666664%;} .col-sm-pull-1{right:8.333333333333332%;} .col-sm-pull-0{right:0%;} .col-sm-push-12{left:100%;} .col-sm-push-11{left:91.66666666666666%;} .col-sm-push-10{left:83.33333333333334%;} .col-sm-push-9{left:75%;} .col-sm-push-8{left:66.66666666666666%;} .col-sm-push-7{left:58.333333333333336%;} .col-sm-push-6{left:50%;} .col-sm-push-5{left:41.66666666666667%;} .col-sm-push-4{left:33.33333333333333%;} .col-sm-push-3{left:25%;} .col-sm-push-2{left:16.666666666666664%;} .col-sm-push-1{left:8.333333333333332%;} .col-sm-push-0{left:0%;} .col-sm-offset-12{margin-left:100%;} .col-sm-offset-11{margin-left:91.66666666666666%;} .col-sm-offset-10{margin-left:83.33333333333334%;} .col-sm-offset-9{margin-left:75%;} .col-sm-offset-8{margin-left:66.66666666666666%;} .col-sm-offset-7{margin-left:58.333333333333336%;} .col-sm-offset-6{margin-left:50%;} .col-sm-offset-5{margin-left:41.66666666666667%;} .col-sm-offset-4{margin-left:33.33333333333333%;} .col-sm-offset-3{margin-left:25%;} .col-sm-offset-2{margin-left:16.666666666666664%;} .col-sm-offset-1{margin-left:8.333333333333332%;} .col-sm-offset-0{margin-left:0%;}}@media (min-width:992px){.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12{float:left;} .col-md-12{width:100%;} .col-md-11{width:91.66666666666666%;} .col-md-10{width:83.33333333333334%;} .col-md-9{width:75%;} .col-md-8{width:66.66666666666666%;} .col-md-7{width:58.333333333333336%;} .col-md-6{width:50%;} .col-md-5{width:41.66666666666667%;} .col-md-4{width:33.33333333333333%;} .col-md-3{width:25%;} .col-md-2{width:16.666666666666664%;} .col-md-1{width:8.333333333333332%;} .col-md-pull-12{right:100%;} .col-md-pull-11{right:91.66666666666666%;} .col-md-pull-10{right:83.33333333333334%;} .col-md-pull-9{right:75%;} .col-md-pull-8{right:66.66666666666666%;} .col-md-pull-7{right:58.333333333333336%;} .col-md-pull-6{right:50%;} .col-md-pull-5{right:41.66666666666667%;} .col-md-pull-4{right:33.33333333333333%;} .col-md-pull-3{right:25%;} .col-md-pull-2{right:16.666666666666664%;} .col-md-pull-1{right:8.333333333333332%;} .col-md-pull-0{right:0%;} .col-md-push-12{left:100%;} .col-md-push-11{left:91.66666666666666%;} .col-md-push-10{left:83.33333333333334%;} .col-md-push-9{left:75%;} .col-md-push-8{left:66.66666666666666%;} .col-md-push-7{left:58.333333333333336%;} .col-md-push-6{left:50%;} .col-md-push-5{left:41.66666666666667%;} .col-md-push-4{left:33.33333333333333%;} .col-md-push-3{left:25%;} .col-md-push-2{left:16.666666666666664%;} .col-md-push-1{left:8.333333333333332%;} .col-md-push-0{left:0%;} .col-md-offset-12{margin-left:100%;} .col-md-offset-11{margin-left:91.66666666666666%;} .col-md-offset-10{margin-left:83.33333333333334%;} .col-md-offset-9{margin-left:75%;} .col-md-offset-8{margin-left:66.66666666666666%;} .col-md-offset-7{margin-left:58.333333333333336%;} .col-md-offset-6{margin-left:50%;} .col-md-offset-5{margin-left:41.66666666666667%;} .col-md-offset-4{margin-left:33.33333333333333%;} .col-md-offset-3{margin-left:25%;} .col-md-offset-2{margin-left:16.666666666666664%;} .col-md-offset-1{margin-left:8.333333333333332%;} .col-md-offset-0{margin-left:0%;}}@media (min-width:1200px){.col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12{float:left;} .col-lg-12{width:100%;} .col-lg-11{width:91.66666666666666%;} .col-lg-10{width:83.33333333333334%;} .col-lg-9{width:75%;} .col-lg-8{width:66.66666666666666%;} .col-lg-7{width:58.333333333333336%;} .col-lg-6{width:50%;} .col-lg-5{width:41.66666666666667%;} .col-lg-4{width:33.33333333333333%;} .col-lg-3{width:25%;} .col-lg-2{width:16.666666666666664%;} .col-lg-1{width:8.333333333333332%;} .col-lg-pull-12{right:100%;} .col-lg-pull-11{right:91.66666666666666%;} .col-lg-pull-10{right:83.33333333333334%;} .col-lg-pull-9{right:75%;} .col-lg-pull-8{right:66.66666666666666%;} .col-lg-pull-7{right:58.333333333333336%;} .col-lg-pull-6{right:50%;} .col-lg-pull-5{right:41.66666666666667%;} .col-lg-pull-4{right:33.33333333333333%;} .col-lg-pull-3{right:25%;} .col-lg-pull-2{right:16.666666666666664%;} .col-lg-pull-1{right:8.333333333333332%;} .col-lg-pull-0{right:0%;} .col-lg-push-12{left:100%;} .col-lg-push-11{left:91.66666666666666%;} .col-lg-push-10{left:83.33333333333334%;} .col-lg-push-9{left:75%;} .col-lg-push-8{left:66.66666666666666%;} .col-lg-push-7{left:58.333333333333336%;} .col-lg-push-6{left:50%;} .col-lg-push-5{left:41.66666666666667%;} .col-lg-push-4{left:33.33333333333333%;} .col-lg-push-3{left:25%;} .col-lg-push-2{left:16.666666666666664%;} .col-lg-push-1{left:8.333333333333332%;} .col-lg-push-0{left:0%;} .col-lg-offset-12{margin-left:100%;} .col-lg-offset-11{margin-left:91.66666666666666%;} .col-lg-offset-10{margin-left:83.33333333333334%;} .col-lg-offset-9{margin-left:75%;} .col-lg-offset-8{margin-left:66.66666666666666%;} .col-lg-offset-7{margin-left:58.333333333333336%;} .col-lg-offset-6{margin-left:50%;} .col-lg-offset-5{margin-left:41.66666666666667%;} .col-lg-offset-4{margin-left:33.33333333333333%;} .col-lg-offset-3{margin-left:25%;} .col-lg-offset-2{margin-left:16.666666666666664%;} .col-lg-offset-1{margin-left:8.333333333333332%;} .col-lg-offset-0{margin-left:0%;}}.clearfix:before,.clearfix:after{content:" ";display:table;}.clearfix:after{clear:both;}.center-block{display:block;margin-left:auto;margin-right:auto;}.pull-right{float:right !important;}.pull-left{float:left !important;}.hide{display:none !important;}.show{display:block !important;}.invisible{visibility:hidden;}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}.hidden{display:none !important;visibility:hidden !important;}.affix{position:fixed;}@-ms-viewport{width:device-width;}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none !important;}@media (max-width:767px){.visible-xs{display:block !important;}table.visible-xs{display:table;} tr.visible-xs{display:table-row !important;} th.visible-xs,td.visible-xs{display:table-cell !important;}}@media (min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block !important;}table.visible-xs.visible-sm{display:table;} tr.visible-xs.visible-sm{display:table-row !important;} th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell !important;}}@media (min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block !important;}table.visible-xs.visible-md{display:table;} tr.visible-xs.visible-md{display:table-row !important;} th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell !important;}}@media (min-width:1200px){.visible-xs.visible-lg{display:block !important;}table.visible-xs.visible-lg{display:table;} tr.visible-xs.visible-lg{display:table-row !important;} th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell !important;}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none !important;}@media (max-width:767px){.visible-sm.visible-xs{display:block !important;}table.visible-sm.visible-xs{display:table;} tr.visible-sm.visible-xs{display:table-row !important;} th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell !important;}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block !important;}table.visible-sm{display:table;} tr.visible-sm{display:table-row !important;} th.visible-sm,td.visible-sm{display:table-cell !important;}}@media (min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block !important;}table.visible-sm.visible-md{display:table;} tr.visible-sm.visible-md{display:table-row !important;} th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell !important;}}@media (min-width:1200px){.visible-sm.visible-lg{display:block !important;}table.visible-sm.visible-lg{display:table;} tr.visible-sm.visible-lg{display:table-row !important;} th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell !important;}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none !important;}@media (max-width:767px){.visible-md.visible-xs{display:block !important;}table.visible-md.visible-xs{display:table;} tr.visible-md.visible-xs{display:table-row !important;} th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell !important;}}@media (min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block !important;}table.visible-md.visible-sm{display:table;} tr.visible-md.visible-sm{display:table-row !important;} th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell !important;}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block !important;}table.visible-md{display:table;} tr.visible-md{display:table-row !important;} th.visible-md,td.visible-md{display:table-cell !important;}}@media (min-width:1200px){.visible-md.visible-lg{display:block !important;}table.visible-md.visible-lg{display:table;} tr.visible-md.visible-lg{display:table-row !important;} th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell !important;}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none !important;}@media (max-width:767px){.visible-lg.visible-xs{display:block !important;}table.visible-lg.visible-xs{display:table;} tr.visible-lg.visible-xs{display:table-row !important;} th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell !important;}}@media (min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block !important;}table.visible-lg.visible-sm{display:table;} tr.visible-lg.visible-sm{display:table-row !important;} th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell !important;}}@media (min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block !important;}table.visible-lg.visible-md{display:table;} tr.visible-lg.visible-md{display:table-row !important;} th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell !important;}}@media (min-width:1200px){.visible-lg{display:block !important;}table.visible-lg{display:table;} tr.visible-lg{display:table-row !important;} th.visible-lg,td.visible-lg{display:table-cell !important;}}.hidden-xs{display:block !important;}table.hidden-xs{display:table;}tr.hidden-xs{display:table-row !important;}th.hidden-xs,td.hidden-xs{display:table-cell !important;}@media (max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none !important;}}@media (min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm,tr.hidden-xs.hidden-sm,th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none !important;}}@media (min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md,tr.hidden-xs.hidden-md,th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none !important;}}@media (min-width:1200px){.hidden-xs.hidden-lg,tr.hidden-xs.hidden-lg,th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none !important;}}.hidden-sm{display:block !important;}table.hidden-sm{display:table;}tr.hidden-sm{display:table-row !important;}th.hidden-sm,td.hidden-sm{display:table-cell !important;}@media (max-width:767px){.hidden-sm.hidden-xs,tr.hidden-sm.hidden-xs,th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none !important;}}@media (min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none !important;}}@media (min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md,tr.hidden-sm.hidden-md,th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none !important;}}@media (min-width:1200px){.hidden-sm.hidden-lg,tr.hidden-sm.hidden-lg,th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none !important;}}.hidden-md{display:block !important;}table.hidden-md{display:table;}tr.hidden-md{display:table-row !important;}th.hidden-md,td.hidden-md{display:table-cell !important;}@media (max-width:767px){.hidden-md.hidden-xs,tr.hidden-md.hidden-xs,th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none !important;}}@media (min-width:768px) and (max-width:991px){.hidden-md.hidden-sm,tr.hidden-md.hidden-sm,th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none !important;}}@media (min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none !important;}}@media (min-width:1200px){.hidden-md.hidden-lg,tr.hidden-md.hidden-lg,th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none !important;}}.hidden-lg{display:block !important;}table.hidden-lg{display:table;}tr.hidden-lg{display:table-row !important;}th.hidden-lg,td.hidden-lg{display:table-cell !important;}@media (max-width:767px){.hidden-lg.hidden-xs,tr.hidden-lg.hidden-xs,th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none !important;}}@media (min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm,tr.hidden-lg.hidden-sm,th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none !important;}}@media (min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md,tr.hidden-lg.hidden-md,th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none !important;}}@media (min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none !important;}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none !important;}@media print{.visible-print{display:block !important;}table.visible-print{display:table;} tr.visible-print{display:table-row !important;} th.visible-print,td.visible-print{display:table-cell !important;} .hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none !important;}}
\ No newline at end of file
diff --git a/public/css/built.css b/public/css/built.css
index 22367aad6388..ca50e4b7f2a6 100644
--- a/public/css/built.css
+++ b/public/css/built.css
@@ -2464,6 +2464,11 @@ table.dataTable tbody th, table.dataTable tbody td {
padding: 10px;
}
+table.data-table tr {
+ border-bottom: 1px solid #d0d0d0;
+ border-top: 1px solid #d0d0d0;
+}
+
.datepicker {
padding: 4px !important;
margin-top: 1px;
diff --git a/public/css/built.public.css b/public/css/built.public.css
index 05f86e3361a6..3c54cc6ace64 100644
--- a/public/css/built.public.css
+++ b/public/css/built.public.css
@@ -779,4 +779,181 @@ div.DTFC_LeftBodyWrapper tbody tr:first-child td {
div.DTFC_LeftFootWrapper table {
border-top: none;
-}
\ No newline at end of file
+}
+body {
+ font-family: 'Roboto', sans-serif;
+ font-size: 14px;
+ background-color: #f8f8f8;
+}
+
+
+@media screen and (min-width: 700px) {
+ .navbar-header {
+ padding-top: 16px;
+ padding-bottom: 16px;
+ }
+ .navbar li a {
+ padding: 31px 20px 31px 20px;
+ }
+}
+
+#footer {
+ text-align: center
+}
+
+#footer .top {
+ background: #2e2b2b;
+ font-size: 12px;
+ font-weight: 900;
+ text-transform: uppercase;
+ padding: 40px 0 27px;
+}
+
+#footer .top li {
+ display: inline-block;
+ margin: 0 30px 10px;
+}
+
+#footer .top a {
+ color: #fff;
+ text-decoration: none;
+}
+
+#footer .bottom {
+ border-top: 1px solid #5f5d5d;
+ background: #211f1f;
+ font-size: 11px;
+ font-weight: 400;
+ color: #636262;
+ padding: 28px 0;
+}
+
+#footer .bottom a {
+ color: #636262;
+}
+
+#footer .menu-item-31 a:before {
+ content: '';
+ display: inline-block;
+ width: 9px;
+ height: 15px;
+ background: url({{ asset('images/social/facebook.svg') }}) no-repeat;
+ margin: 0 6px 0 0;
+ position: relative;
+ top: 3px;
+}
+
+#footer .menu-item-32 a:before {
+ content: '';
+ display: inline-block;
+ width: 19px;
+ height: 16px;
+ background: url({{ asset('images/social/twitter.svg') }}) no-repeat;
+ margin: 0 6px 0 0;
+ position: relative;
+ top: 3px;
+}
+
+#footer .menu-item-33 a:before {
+ content: '';
+ display: inline-block;
+ width: 19px;
+ height: 16px;
+ background: url({{ asset('images/social/github.png') }}) no-repeat;
+ margin: 0 6px 0 0;
+ position: relative;
+ top: 3px;
+}
+
+/* Hide bootstrap sort header icons */
+table.data-table thead .sorting:after { content: '' !important }
+table.data-table thead .sorting_asc:after { content: '' !important }
+table.data-table thead .sorting_desc:after { content: '' !important}
+table.data-table thead .sorting_asc_disabled:after { content: '' !important }
+table.data-table thead .sorting_desc_disabled:after { content: '' !important }
+
+.dataTables_length {
+ padding-left: 20px;
+ padding-top: 8px;
+}
+
+.dataTables_length label {
+ font-weight: 500;
+}
+
+@media screen and (min-width: 700px) {
+ #footer .top {
+ padding: 27px 0;
+ }
+
+ #footer .bottom {
+ padding: 25px 0;
+ }
+}
+
+
+
+table.dataTable { border-radius: 3px; border-collapse: collapse;
+/*border-spacing: 0;*/}
+table.dataTable thead > tr > th, table.invoice-table thead > tr > th {
+ color:#fff;
+}
+th:first-child {
+ border-radius: 3px 0 0 0;
+ border-left: none;
+}
+th:last-child {
+ border-radius: 0 3px 0 0;
+}
+
+tr {border: none;}
+td {
+ padding-top: 16px !important;
+ padding-bottom: 16px !important;
+}
+
+/*th {border-left: 1px solid #d26b26; }*/
+th {border-left: 1px solid #FFFFFF; }
+.table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td, .table>tbody>tr>td, .table>tfoot>tr>td {
+ vertical-align: middle;
+ border-top: none;
+ border-bottom: 1px solid #dfe0e1;
+}
+table.dataTable.no-footer {
+ border-bottom: none;
+}
+.table-striped>tbody>tr:nth-child(odd)>td,
+.table-striped>tbody>tr:nth-child(odd)>th {
+ background-color: #FDFDFD;
+}
+table.table thead .sorting_asc {
+ background: url('../images/sort_asc.png') no-repeat 90% 50%;
+}
+table.table thead .sorting_desc {
+ background: url('../images/sort_desc.png') no-repeat 90% 50%;
+}
+table.dataTable thead th, table.dataTable thead td, table.invoice-table thead th, table.invoice-table thead td {
+ padding: 12px 10px;
+}
+table.dataTable tbody th, table.dataTable tbody td {
+ padding: 10px;
+}
+
+.dataTables_wrapper {
+ padding-top: 16px;
+}
+
+table.table thead > tr > th {
+ border-bottom-width: 0px;
+}
+
+table td {
+ max-width: 250px;
+}
+.pagination>li:first-child>a, .pagination>li:first-child>span {
+ border-bottom-left-radius: 3px;
+ border-top-left-radius: 3px;
+}
+
+/* hide table sorting indicators */
+table.data-table thead .sorting { background: url('') no-repeat center right; }
\ No newline at end of file
diff --git a/public/css/public.style.css b/public/css/public.style.css
new file mode 100644
index 000000000000..59444f3e8b69
--- /dev/null
+++ b/public/css/public.style.css
@@ -0,0 +1,177 @@
+body {
+ font-family: 'Roboto', sans-serif;
+ font-size: 14px;
+ background-color: #f8f8f8;
+}
+
+
+@media screen and (min-width: 700px) {
+ .navbar-header {
+ padding-top: 16px;
+ padding-bottom: 16px;
+ }
+ .navbar li a {
+ padding: 31px 20px 31px 20px;
+ }
+}
+
+#footer {
+ text-align: center
+}
+
+#footer .top {
+ background: #2e2b2b;
+ font-size: 12px;
+ font-weight: 900;
+ text-transform: uppercase;
+ padding: 40px 0 27px;
+}
+
+#footer .top li {
+ display: inline-block;
+ margin: 0 30px 10px;
+}
+
+#footer .top a {
+ color: #fff;
+ text-decoration: none;
+}
+
+#footer .bottom {
+ border-top: 1px solid #5f5d5d;
+ background: #211f1f;
+ font-size: 11px;
+ font-weight: 400;
+ color: #636262;
+ padding: 28px 0;
+}
+
+#footer .bottom a {
+ color: #636262;
+}
+
+#footer .menu-item-31 a:before {
+ content: '';
+ display: inline-block;
+ width: 9px;
+ height: 15px;
+ background: url({{ asset('images/social/facebook.svg') }}) no-repeat;
+ margin: 0 6px 0 0;
+ position: relative;
+ top: 3px;
+}
+
+#footer .menu-item-32 a:before {
+ content: '';
+ display: inline-block;
+ width: 19px;
+ height: 16px;
+ background: url({{ asset('images/social/twitter.svg') }}) no-repeat;
+ margin: 0 6px 0 0;
+ position: relative;
+ top: 3px;
+}
+
+#footer .menu-item-33 a:before {
+ content: '';
+ display: inline-block;
+ width: 19px;
+ height: 16px;
+ background: url({{ asset('images/social/github.png') }}) no-repeat;
+ margin: 0 6px 0 0;
+ position: relative;
+ top: 3px;
+}
+
+/* Hide bootstrap sort header icons */
+table.table thead .sorting:after { content: '' !important }
+table.table thead .sorting_asc:after { content: '' !important }
+table.table thead .sorting_desc:after { content: '' !important }
+table.table thead .sorting_asc_disabled:after { content: '' !important }
+table.table thead .sorting_desc_disabled:after { content: '' !important }
+
+.dataTables_length {
+ padding-left: 20px;
+ padding-top: 8px;
+}
+
+.dataTables_length label {
+ font-weight: 500;
+}
+
+@media screen and (min-width: 700px) {
+ #footer .top {
+ padding: 27px 0;
+ }
+
+ #footer .bottom {
+ padding: 25px 0;
+ }
+}
+
+
+
+table.dataTable { border-radius: 3px; border-collapse: collapse;
+/*border-spacing: 0;*/}
+table.dataTable thead > tr > th, table.invoice-table thead > tr > th {
+ color:#fff;
+}
+th:first-child {
+ border-radius: 3px 0 0 0;
+ border-left: none;
+}
+th:last-child {
+ border-radius: 0 3px 0 0;
+}
+
+tr {border: none;}
+td {
+ padding-top: 16px !important;
+ padding-bottom: 16px !important;
+}
+
+/*th {border-left: 1px solid #d26b26; }*/
+th {border-left: 1px solid #FFFFFF; }
+.table>thead>tr>th, .table>tbody>tr>th, .table>tfoot>tr>th, .table>thead>tr>td, .table>tbody>tr>td, .table>tfoot>tr>td {
+ vertical-align: middle;
+ border-top: none;
+ border-bottom: 1px solid #dfe0e1;
+}
+table.dataTable.no-footer {
+ border-bottom: none;
+}
+.table-striped>tbody>tr:nth-child(odd)>td,
+.table-striped>tbody>tr:nth-child(odd)>th {
+ background-color: #FDFDFD;
+}
+table.table thead .sorting_asc {
+ background: url('../images/sort_asc.png') no-repeat 90% 50%;
+}
+table.table thead .sorting_desc {
+ background: url('../images/sort_desc.png') no-repeat 90% 50%;
+}
+table.dataTable thead th, table.dataTable thead td, table.invoice-table thead th, table.invoice-table thead td {
+ padding: 12px 10px;
+}
+table.dataTable tbody th, table.dataTable tbody td {
+ padding: 10px;
+}
+
+.dataTables_wrapper {
+ padding-top: 16px;
+}
+
+table.table thead > tr > th {
+ border-bottom-width: 0px;
+}
+
+table td {
+ max-width: 250px;
+}
+.pagination>li:first-child>a, .pagination>li:first-child>span {
+ border-bottom-left-radius: 3px;
+ border-top-left-radius: 3px;
+}
+
+/* hide table sorting indicators */
+table.data-table thead .sorting { background: url('') no-repeat center right; }
\ No newline at end of file
diff --git a/public/css/splash.css b/public/css/splash.css
deleted file mode 100644
index bfa1be306403..000000000000
--- a/public/css/splash.css
+++ /dev/null
@@ -1,1378 +0,0 @@
-body {
- font-family: Roboto, sans-serif;
- line-height: 1.6;
- background-color: #fff;
- overflow-x: hidden;
- color: #2e2b2b;
-}
-.center-block {
- margin: 0 auto !important;
- float: none;
-}
-.valgin {padding: 0; margin: 0;}
-h1,
-h2,
-.btn {
- font-family: Roboto, sans-serif;
- font-weight: 900;
- line-height: 1.1;
- color: #2e2b2b;
-}
-h1 {
- font-size: 56px;
- text-transform: uppercase;
- color: #fff;
-}
-h1 img {
- margin-right: 10px;
- margin-top: -10px;
-}
-h2 {
- font-size: 25px;
-}
-h3 {
- font-size: 16px;
- margin-top: 0;
- font-weight: 700;
- font-family: Roboto, sans-serif;
-}
-.headline {
- border-bottom: 1px solid #eee;
- padding-bottom: 10px;
- margin-bottom: 15px;
-}
-.thin {
- font-weight: 300;
-}
-p.first {
- font-size: 17px;
-}
-a,
-a .cta h2,
-.socicon,
-.btn,
-a img
-{
- -webkit-transition: all .3s ease-in-out;
- -moz-transition: all .3s ease-in-out;
- -o-transition: all .3s ease-in-out;
- transition: all .3s ease-in-out;
-}
-a:hover {
- text-decoration: none;
-}
-.blue-text {
- color: #2299c0;
-}
-.center {
- text-align: center;
-}
-.white-bg {
- background-color: #fff;
-}
-.form-group {
-margin-bottom: 25px;
-}
-.form-group .glyphicon {
- position: absolute;
-top: 28px;
-left: 15px;
-display: block;
-width: 50px;
-height: 50px;
-line-height: 50px;
-text-align: center;
- color: #bfbfbf;
-}
-.form-control.with-icon {padding-left: 50px !important;}
-
-/* Navigation */
-
-.navbar {
- background: #211f1f;
- padding: 40px 0;
- border: none;
- border-radius: 0;
-}
-.navbar-brand {
- padding: 0;
- line-height: 1;
- height: auto;
-}
- .navbar>.container .navbar-brand {
- margin-left: 0 !important;
- }
-ul.navbar-nav {
- float: right;
- list-style-type: none;
- margin: 0;
- padding: 0;
-}
-ul.navbar-nav li {
- display: inline;
- font-family: Roboto, sans-serif;
- font-weight: 900;
- text-transform: uppercase;
- height: 26px;
- line-height: 26px;
-}
-ul.navbar-nav li a {
- color: #fff;
- margin-left: 45px;
-}
-ul.navbar-nav .glyphicon {
- color: #ebbe09;
-}
-ul.navbar-nav li:last-child a {
- color: #ebbe09;
- margin-left: 5px;
-}
-ul.navbar-nav li:last-child {
- border-left: 1px solid #4f4b4b;
- padding-left: 45px;
- margin-left: 45px;
-}
-ul.navbar-nav li:first-child a {
- border-left: none;
- margin: 0;
- padding-left: 0;
-}
-ul.navbar-nav li a:hover {
- color: #ebbe09;
- text-decoration: none;
-}
-
-.navbar-nav>li {
- float: right;
-}
-.navbar-nav>li>a {
- padding: 0;
- display: inline-block;
-}
-.nav>li>a:hover, .nav>li>a:focus {
- background-color: transparent;
-}
-z.container>.navbar-collapse {
- margin-right: -15px;
-}
-.navbar-top {
- padding: 5px 0 0 0;
- background: #fff;
- border-top: 1px solid #211f1f;
-}
-.navbar-top ul {
- float: right;
- margin: 0;
-}
-.navbar-top ul li {
- display: inline-block;
- font-size: 12px;
- text-transform: uppercase;
- margin-left: 30px;
- height: 40px;
- line-height: 40px;
- vertical-align: middle;
- float: left;
-}
-.navbar-top ul li .socicon {
- text-transform: none;
- margin-top: 1px;
-}
-.navbar-top ul li a .socicon {
- font-size: 13px;
- color: #a6a5a5;
- display: inline-block;
-}
-.navbar-top ul li a .socicon:hover {
- color: #ebbe09;
-}
-.navbar-top ul li a {
- color: #2e2b2b;
-}
-.navbar-top ul li a:hover {
- color: #ebbe09;
-}
-
-
-a .cta h2 {
- width: 100%;
- height: 63px;
- line-height: 63px;
- background: #edd71e;
- display: inline-block;
- color: #1a1818;
- text-align: center;
- float: left;
- margin: 0;
- text-transform: uppercase;
- font-size: 20px;
- font-weight: 900;
-}
-a .cta h2 span {
- width: 63px;
- height: 63px;
- line-height: 63px;
- color: #fff;
- background: #ebbe09;
- text-align: center;
- float: right;
- font-weight: 700;
- font-size: 20px;
- font-family: Roboto, sans-serif;
- -webkit-transition: all .1s ease-in-out;
- -moz-transition: all .1s ease-in-out;
- -o-transition: all .1s ease-in-out;
- transition: all .1s ease-in-out;
-}
-a .cta:hover span {
- font-size: 40px;
- background: #f2c40a;
-}
-.hero h1 {
- margin: 0;
-}
-.hero {
- text-align: center;
- padding: 150px 0;
- background-repeat: no-repeat;
- background-position: center center;
- background-size: cover;
-}
-.hero4 {
- padding: 150px 0;
- background-repeat: no-repeat;
- background-position: center center;
- background-size: cover;
-}
-.hero5 {
- text-align: center;
- padding: 150px 0;
- background-repeat: no-repeat;
- background-position: center center;
- background-size: cover;
-}
-.hero1.background {
- background-repeat: no-repeat;
- background-position: center center;
- /*background-attachment: fixed;*/
- background-size: cover;
- min-height: 500px;
-}
-.hero1 {padding: 0;}
-.hero1 h1 {
- font-size: 45px;
- margin-top: 20px;
- margin-bottom: 10px;
- color: #1a1818;
-}
-.hero .caption-side {
- background: #fff;
- width: 50%;
- padding-right: 15px;
- position: absolute;
- left: 0;
- height: 212px;
- margin-top: 100px;
-}
-.hero .caption {
- width: 61.5%;
- background: #fff;
- padding-right: 15px;
- position: relative;
- padding: 10px 35px 20px 35px;
- height: 212px;
- border-left: 1px dotted #ccc;
- margin-top: 100px;
- text-align: left;
- color: #1a1818;
-}
-.hero-secure p {font-size: 20px; text-transform: uppercase; color: #fff;}
-.hero-secure p img { vertical-align: baseline; padding-right: 5px;}
-section.features-splash,
-section.upper-footer {
- margin: 70px 0;
-}
-section.features, section.about, section.team, section.testi {
- margin: 0;
- padding: 100px 0;
-}
-section.secure {
- padding: 50px 0 100px 0;
-}
-section.features1 {
- padding-bottom: 0;
-}
-section.features3, section.features5 {
- padding-bottom: 100px;
-}
-section.features1 .col-md-5, section.features4 .col-md-5{
- padding-bottom: 100px;
-}
-section.features4 {
- padding-bottom: 0;
-}
-
-section.features.upper-footer {
- background-color: #fad129;
- padding: 40px 0;
- text-align: center;
- }
-section.features.upper-footer a .cta h2 {
- background-color: #211f1f;
- color: #fff;
- padding: 0;
- }
-section.features.upper-footer h2.thin {
- line-height: 63px;
- float: right;
- margin:0;
- }
-
-section.features4, section.team, .card {
-background-color: #f4f3f3;
-}
-section.features4 .col-md-7 img {
-float: right;
- margin-right: 40px;
-}
-section.features1 .col-md-7 img, section.features3 .col-md-7 img {
- margin-left: 40px;
-}
-.upper-footer {
- background-color: #f8f8f8;
- border-top: 1px solid #e6e6e6;
-}
-
-section.upper-footer.white-bg {
- margin: 0;
- padding: 60px 0;
-}
-section.features-splash .box {
- padding: 20px;
- text-align: center;
-}
-/*Icons*/
-
-section.features-splash .icon {
- background: #2599c0;
- width: 94px;
- height: 94px;
- border: 8px solid #1d8db3;
- text-align: center;
- display: table;
- margin: 0 auto;
-}
-section.features .icon {
- background: #2599c0;
- width: 35px;
- height: 35px;
- border: 4px solid #1d8db3;
- text-align: center;
- display: table;
- float: left;
- line-height: 1;
-}
-
-section.testi.blue {
- background-size: auto;
- background-repeat:no-repeat;
- background-position:bottom;
-}
-
-.twitter-tweet {margin: 0 auto !important; margin-bottom: 30px !important;}
-
-.icon.open {
- background: #32ba8d !important;
- border-color: #28ae82 !important;
-}
-.icon.secure {
- background: #2e2b2b !important;
- border-color: #161414 !important;
-}
-section.features .icon.free img {
- width: 23px;
-}
-section.features .icon.open img {
- width: 23px;
-}
-section.features .icon.pdf img {
- width: 16px;
- float: none;
-}
-section.features .icon.pay img {
- width: 23px;
-}
-section.blue .icon.free {
- background-color: #fff;
- border-color: #fff;
-}
-section.features-splash .two .box h2 {
- color: #32ba8d;
-}
-.icon.pdf {
- background: #d2462d !important;
- border-color: #c23b23 !important;
-}
-section.features-splash .three .box h2 {
- color: #d2462d;
-}
-.icon.pay {
- background: #fad129 !important;
- border-color: #f0c824 !important;
-}
-section.features-splash .four .box h2 {
- color: #f0c824;
-}
-section.features-splash h2 {
- margin: 20px 0 15px;
- color: #2599c0;
-}
-section.features h2 {
- display: inline-block;
- margin-top: 5px;
- padding-left: 15px;
- color: #1a1818;
-}
-.icon .img-wrap {
- display: table-cell;
- vertical-align: middle;
- height: 100%;
- padding: 0;
-}
-.icon img {
- vertical-align: middle;
-}
-section.blue {
- background-image: url('../images/bg-blue.jpg');
- background-color: #2387a9;
- background-size: cover;
- color: #fff;
- padding: 140px 0;
-}
-section.blue .col-md-7 {
- text-align: left;
-}
-section.blue h1 span {
- font-size: 30px;
- display: block;
-}
-section.blue h1 {
- color: #fff;
- line-height: 1.2;
- margin-bottom: 20px;
- margin-top: 30px;
- font-size: 65px;
-}
-section.blue h2 {
- color: #fff;
-}
-section.blue a {
- color: #ffffff;
- text-decoration: underline;
-}
-section.blue p {
- margin-top: 15px;
-}
-section.blue img {
- max-width: 100%;
-}
-section.plans {
- padding: 70px 0;
-}
-section.team h2,
-section.plans h2 {
- font-size: 25px;
- margin: 0 0 25px;
- text-transform: none;
-}
-section.team .col-md-3 h2 {
- margin-top: 20px;
- margin-bottom: 3px;
- font-size: 20px;
-}
-section.about .screendump {
- height: 220px;
-}
-section.about.white-bg .col-md-5 {
- padding-right: 43px;
- padding-left: 15px;
-}
-section.about img,
-section.team img {
- width: 100%;
- min-width: 100%;
-}
-section.team .col-md-3 {
- margin-top: 25px;
- padding: 0 20px;
-}
-section.team .col-md-3 p {
- font-size: 12px;
- margin-bottom: 20px;
-}
-section.team .social {
- margin: 3px 3px 0 3px;
-}
-section.team .social.blue {background-color: #2599c0;}
-section.team .social.green {background-color: #30ab82;}
-section.team .social.red {background-color: #d2462d;}
-section.team .social.yellow {background-color: #ebbe09;}
-section.team .social img {
- margin: 12px 7px;
- height: 15px;
- display: inline-block;
- width: auto;
- min-width: 1px;
- padding: 0;
-}
-section.team .img-team:before {
- -webkit-box-shadow: inset 0 0 10px 0 rgba(255, 255, 255, 0.3);
- box-shadow: inset 0 0 0 7px rgba(255, 255, 255, 0.3);
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- content: "";
-}
-section.team .img-team {
- z-index: 1000; position: relative;
-}
-section.team .img-team img {}
-section.contact .address .glyphicon, section.contact .address .socicon {
- background: #edd71e;
- height: 40px;
- width: 40px;
- line-height: 40px;
- text-align: center;
- border-radius: 50px;
- color: #1a1818;
- margin-right: 15px;
- display: inline-block;
-}
-
-section.contact .address p {
- margin-top: 20px;
-}
-section.contact .address span.push {
- margin-left: 55px;
- line-height: 25px;
-}
-
-section.contact .form-control, section.secure .form-control, footer.footer .form-control {
- display: block;
- width: 100%;
- height: 50px;
- padding: 6px 12px;
- font-size: 14px;
- line-height: 1.42857143;
- color: #555;
- background-color: #fff;
- background-image: none;
- border: 1px solid #e0e0e1;
- border-radius: 0;
- -webkit-box-shadow: inset 0px 0px 8px 5px rgba(50, 50, 50, 0.25);
- -moz-box-shadow: inset 0px 0px 8px 5px rgba(50, 50, 50, 0.25);
- box-shadow: inset 0px 0px 5px 2px rgba(50, 50, 50, 0.05);
- -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
- transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
-}
-section.contact textarea.form-control {
- height: auto;
-}
-section.contact form {
- margin-top: 30px;
-}
-
-section.secure label { text-transform: uppercase; font-size: 12px; font-weight: 800; margin-bottom: 10px; display: block;}
-
-section.secure .card {padding: 30px; margin-bottom: 50px;}
-section.secure .card p {padding-top: 26px; padding-right: 15px; line-height: 50px;}
-section.secure .info {padding-top: 30px;}
-
-
-
-section.faq {
- padding: 70px 0;
-}
-section.faq a.expander {
- display: block;
- font-size: 18px;
- font-family: Roboto, sans-serif;
- font-weight: 700;
- margin-bottom: 10px;
-}
-/*section.faq .content{display:none;}*/
-section.faq .question {
- padding-bottom: 20px;
- margin-bottom: 30px;
- border-bottom: 1px solid #e0e0e0;
-}
-section.faq .contact-box {
- margin-top: 30px;
- padding: 40px;
- color: #4f4747;
- background: #fad129;
-}
-section.faq .contact-box h2 {
- text-transform: uppercase;
- display: block;
- float: left;
- width: 60%;
- margin-top: 0;
- margin-bottom: 0;
- padding: 2px 0;
-}
-section.faq .contact-box img {
- float: left;
- display: block;
- margin-right: 20px;
- margin-left: 30px;
- height: 57px;
-}
-section.faq .contact-box .col-md-8 {
- padding-left: 5px;
-}
-section.faq .contact-box h2 {
- border-right: 1px solid #e4bf28;
-}
-
-section.faq .contact-box a {
- color: #2e2b2b;
-}
-section.faq .contact-box p {
-
-}
-
-.btn-primary {
- color: #fff;
- background-color: #2299c0;
- border: none;
- text-align: center;
- border-radius: 0;
- height: 63px;
- line-height: 63px;
- padding: 0;
- width: 100%;
- text-align: center;
-}
-.btn-primary:hover {
- background-color: #2299c0;
-}
-
-.btn.green {
- background-color: #30ab82;
-}
-.btn.green:hover {
- background-color: #2daa81;
-}
-.btn-lg {
-font-size: 18px;
-}
-section.contact button span.glyphicon {
- background-color: transparent;
- color: #fff;
- float: right;
-}
-section.contact .btn span.glyphicon {
- background-color: #1e84a5;
- height: 63px;
- line-height: 63px;
- width: 63px;
- margin-top: -1px;
- -webkit-transition: all .1s ease-in-out;
- -moz-transition: all .1s ease-in-out;
- -o-transition: all .1s ease-in-out;
- transition: all .1s ease-in-out;
-}
-section.contact .btn:hover span.glyphicon {
- font-size: 25px;
-}
-section.contact textarea:focus, section.secure textarea:focus,
-select:focus,
-input[type=text]:focus,
-input[type=password]:focus,
-input[type=datetime]:focus,
-input[type=datetime-local]:focus,
-input[type=date]:focus,
-input[type=month]:focus,
-input[type=time]:focus,
-input[type=week]:focus,
-input[type=number]:focus,
-input[type=email]:focus,
-input[type=url]:focus,
-input[type=search]:focus,
-input[type=tel]:focus,
-input[type=color]:focus,
-.uneditable-input:focus {
-
-}
-section.contact address {
- display: inline-block;
-}
-footer.footer {
- background: #211f1f;
- padding: 50px 0;
- text-align: center;
-}
-footer.footer h3 { text-align: left; color: #fff; padding-bottom: 12px; margin-bottom: 25px; border-bottom: 1px solid #2c2a2a;}
-footer.footer hr {
-margin-top: 25px;
-margin-bottom: 25px;
-border: 0;
-border-top: 1px solid #2c2a2a;
-}
-footer.footer .glyphicon {margin-right: 8px; color: #ebbe09; width: 15px; font-size: 14px;}
-footer ul.navbar-vertical {
- margin: 0;
- padding: 0;
- margin-bottom: 30px;
-}
-footer ul.navbar-vertical li {
- display: block;
- padding: 2px 0;
-}
-footer ul.navbar-vertical li a {
- color: #a3a2a2;
- font-size: 12px;
- font-weight: 800;
- text-transform: uppercase;
-}
-footer ul.navbar-vertical li a:hover {
- color: #e5e5e5;
-}
-
-footer.footer .social {
- margin-bottom: 30px;
- width: 100%;
- clear: both;
- text-align: center;
-}
-
-footer.footer .social img {
- margin: 0 3px;
-}
-footer.footer .social a img:hover {
- opacity: 0.6;
-}
-
-footer.footer .social .row1 {
- margin-bottom: -8px;
-}
-
-footer.footer form#mad_mimi_signup_form button {
- position: absolute;
- right: 0;
- top: 0;
- width: 50px;
- height: 50px;
- background: #b7b7b6;
- border: none;
- padding: 0;
- border-radius: 0;
- text-align: center;
- margin-bottom: 30px;
-}
-footer.footer form#mad_mimi_signup_form button:hover {
- background: #7b7a79;
-}
-footer.footer form#mad_mimi_signup_form button .glyphicon {
- position: static;
- color: #fff;
- font-size: 15px;
-width: auto;
- margin: 0;
-}
-footer.footer form#mad_mimi_signup_form .form-group {
- position: relative;
-}
-footer.footer form#mad_mimi_signup_form input {
- padding-right: 60px;
- background: #393636;
- border: none;
- color: #b7b7b6;
-}
-
-/* Fonts */
-
-.socicon {
- font-family: 'socicon' !important;
-}
-@font-face {
- font-family: socicon;
- src: url(../fonts/socicon-webfont.eot);
- src: url(../fonts/socicon-webfont.eot?#iefix) format(embedded-opentype), url(../fonts/socicon-webfont.woff) format(woff), url(../fonts/socicon-webfont.ttf) format(truetype), url(../fonts/socicon-webfont.svg#sociconregular) format(svg);
- font-weight: 400;
- font-style: normal;
-}
-
-@media (max-width: 768px) {
-
- /* Responsive actions */
- .hidden-desktop {
- display: block !important;
- }
- .hidden-phone {
- display: none !important;
- }
-
- /* Typo */
- p {
- font-size: 12px;
- }
- p.first {
- font-size: 14px;
- margin: 0;
- }
- h1 {
- font-size: 30px;
- }
- h2 {
- font-size: 20px;
- }
- .headline h2 {
- margin-top: 0;
- }
- .headline {
- border-bottom: none;
- padding-bottom: 0;
- margin-bottom: 15px;
- }
- section.team h2, section.plans h2 {
- font-size: 20px;
- margin: 0 0 15px;
- }
-
- /* Mobile navigation */
- .navbar {
- text-align: center;
- padding: 0;
- }
- .navbar-header {
- padding: 15px 0;
- }
- ul.navbar-nav {
- width: 100%;
- }
- .navbar li.hidden-desktop {
- font-weight: 400;
- font-size: 11px;
- }
- ul.navbar-nav li {
- float: none;
- margin: 0;
- height: 30px;
- line-height: 30px;
- font-size: 12px;
- display: block !important;
- }
- ul.navbar-nav li a {
- margin: 0;
- display: inline;
- width: 100%;
- float: none;
- padding: 0;
- }
- ul.navbar-nav li:first-child {
- margin-top: 12px;
- }
- ul.navbar-nav li:first-child a {
- margin: 0;
- padding: 0;
- }
- ul.navbar-nav li:last-child {
- border-left: none;
- padding-left: 0;
- margin-left: 0;
- margin-bottom: 12px;
- }
- .navbar-collapse {
- border-top: none;
- box-shadow: none;
- background: #282525;
- }
- .navbar-toggle {
- border: 1px solid #ddd;
- margin: 0;
- }
- .navbar-toggle .icon-bar {
- background: #ddd;
- }
-
- ul.navbar-list {
- float: none;
- margin-top: 10px;
- }
- .navbar-brand {
- margin-top: 6px;
- }
- .container>.navbar-header {
- margin: 0;
- }
-
- /* Sections */
- section.features, section.blue, section, section.secure, section.about, section.team, section.contact, section.faq, section.testi, section.plans {
- padding: 40px 0;
- margin: 0 !important;
- }
-
- section.features-splash .icon {
- width: 50px;
- height: 50px;
- border: 4px solid #1d8db3;
- }
- section.features-splash .icon img {
- width: 30px;
- }
-
- section.about .col-md-5 {
- padding-left: 15px !important;
- }
- section.faq .question {
- padding-bottom: 10px;
- margin-bottom: 20px;
- }
- section.faq a.expander {
- font-size: 14px;
- }
- section.faq .contact-box {
- margin-top: 20px;
- padding: 25px;
- text-align: center;
- }
- section.faq .contact-box h2 {
- float: none;
- width: 100%;
- margin: 10px 0;
- }
- section.faq .contact-box img {
- float: none;
- display: inline-block;
- margin-right: 0;
- margin-left: 0;
- height: 57px;
- }
- section.faq .contact-box .col-md-8 {
- padding-left: 15px;
- }
- section.faq .contact-box h2 {
- border-right: none;
- }
- section.faq .contact-box p {
- margin: 0;
- }
- section.plans .plans-table {
- margin-top: 30px;
- font-size: 12px;
- }
- .plans-table .free .cell {
- border-left: 1px solid #dfe0e1;
- border-right: 1px solid #dfe0e1;
- }
- .plans-table .free .cell:first-child {
- border-left: 1px solid #9b9b9b;
- border-right: 1px solid #9b9b9b;
- }
- section.plans .plans-table .cell {
- display: block;
- width: 100%;
- }
- section.plans .plans-table span {
- display: inline-block !important;
- }
- section.plans .plans-table .hidden-desktop {
- display: inline-block !important;
- margin-bottom: 0;
- margin-right: 10px;
- }
- section.plans .plans-table .cell {
- height: auto;
- padding: 14px 0;
- }
- section.plans .plans-table .free .cell {
- padding-right: 0;
- }
- section.plans .plans-table .free .cell:first-child {
- margin-right: 0;
- }
- section.plans .plans-table .cell .cta {
- margin-bottom: 0 !important;
- }
- section.plans .plans-table .pro {
- margin-top: 30px;
- }
- .plans-table .pro .cell:last-child, .plans-table .free .cell:last-child {
- padding: 14px 0 0 0 !important;
- }
- .plans-table .pro .cell:last-child p {
- margin: 0;
- padding: 0;
- }
- section.about img {
- margin-top: 20px;
- }
- section.team .img-team {
- width: 60%;
- min-width: 60%;
- margin: 0 auto;
- }
-
- section.team .col-md-3:last-child p:last-child {
- margin-bottom: 0;
- }
-
- /* Heros */
- .hero1.background {
- min-height: 100px;
- }
- .hero .caption {
- width: 100%;
- background: #fff;
- padding: 10px 35px 20px 35px;
- height: auto;
- border-left: none;
- margin-top: 0px;
- margin-bottom: 10px;
- text-align: center;
- }
- .hero .caption-side {
- display:none;
- }
- .hero1 h1 {
- font-size: 30px;
- }
- .hero{
- padding: 50px 0;
- }
- .background {
- background-attachment: scroll;
- background-size: cover;
- background-position: bottom center;
- background-repeat: repeat;
- min-height: 1px;
- padding: 50px 0;
- }
- section.upper-footer.white-bg {
- padding: 30px 0;
- }
- section.features .col-md-3 .box {
- margin-bottom: 10px;
- }
-
-
- section.secure .info {
- padding-top: 0;
- }
- section.secure .card {
- padding: 15px;
- margin-bottom: 40px;
- }
- section.secure .card p {
- padding-top: 0;
- padding-right: 15px;
- line-height: 1;
- }
- section.blue h1 {
- line-height: 1.2;
- margin-bottom: 20px;
- margin-top: 0;
- font-size: 30px;
- }
- section.blue h1 span {
-font-size: 20px;
-}
- section.features-splash .box {
-padding: 20px 0 0 0;
-}
- section.features-splash {
-margin-top: -20px !important;
-}
- section.features .col-md-7 img{
- max-width: 100%;
- margin: 0;
- }
- section.features.blue .col-md-7 img, section.features4 .col-md-7 img {
- margin-bottom: 30px;
- }
- section.features1 .col-md-7 img, section.features3 .col-md-7 img, section.features5 .col-md-7 img {
- margin-top: 30px;
- }
- section.features1 .col-md-5, section.features4 .col-md-5, section.features5 .col-md-5 {
-padding-bottom:
- 0;
-}
- section.features.upper-footer {
-text-align: center;
-padding: 20px 0 40px 0;
-}
- section.features.upper-footer h2.thin {
-line-height: 63px;
-float: none;
-
-}
-.nitinh-vAlign{
- position: static !important;
- }
- section.blue .col-md-6 h1 {
- border-left: none;
- border-right: none;
- border-top: 1px dotted #46b9df;
- padding: 30px 0;
- }
- section.blue .col-md-6 h1 span {
- font-size: 25px;
- font-weight: 100;
- display: block;
- text-transform: lowercase;
- }
- section.contact .address {
- margin: 0;
- text-align: center;
- }
- section.contact .address p {
- text-align: center;
- }
- section.contact .address .glyphicon, section.contact .address .socicon {
- display: block;
- margin: 0 auto 7px;
- float: none;
- }
- section.contact .address span.push {
- margin-left: 0;
- }
- section.contact .btn {
- margin-bottom: 5px;
- }
- section.about p {
- margin-bottom: 0;
- margin-top: 10px;
- }
- section.about .screendump {
- margin-top: 25px;
- }
- section.about.white-bg .screendump {
- margin-top: 0;
- margin-top: 0;
- margin-bottom: 20px;
- }
- #contact_form {
- margin: 0;
- }
- #feedbackForm {
- margin-top: 15px;
- }
-
- /* Footer */
- footer .navbar-inner {
- float: none;
- }
- footer ul.navbar-list:last-child {
- height: auto;
- }
- footer .social {
- float: none;
- margin-bottom: 10px;
- }
- footer .social .socicon {
- margin-right: 8px;
- }
-}
-.github {
- background-image: url(../images/GitHub.png);
- background-size: contain;
- background-repeat: no-repeat;
- width: 40px;
- height: 40px;
- display: inline-block;
- margin-right: 10px;
- float: left;
-}
-div.fb_iframe_widget {
- display: inline;
-}
-div.fb_iframe_widget > span {
- vertical-align: top !important;
-}
-::selection {
- color: #fff;
- background: #2e2b2b;
-}
-::-moz-selection {
- color: #fff;
- background: #2e2b2b;
-}
-.plans-table {
- text-align: center;
- margin: 0 auto;
- float: none;
- margin-top: 60px;
-}
-.plans-table .free,
-.plans-table .desc {
- padding: 0;
-}
-.plans-table .free .cell {
- padding-right: 15px;
-}
-.plans-table .desc .cell {
- text-align: right;
- padding-right: 15px;
- border-left: 1px solid #dfe0e1;
- font-size: 13px;
- font-weight: 800;
-}
-.plans-table .pro .cell {
- border-left: 1px solid #cccccc;
- border-right: 1px solid #cccccc;
-}
-.plans-table .cell {
- background-color: #fff;
- border-top: 1px solid #dfe0e1;
- padding: 18px 0;
- font-family: Roboto, sans-serif;
- height: 60px;
-}
-.plans-table .cell:nth-child(odd) {
- background-color: #fbfbfb;
-}
-.plans-table .pro .cell:nth-child(odd) {
- background-color: #f4f4f4;
-}
-.plans-table .pro {
- background-color: #2299c0;
- overflow: hidden;
- padding: 0;
- -webkit-box-shadow: 0px 0px 15px 0px rgba(0, 5, 5, 0.2);
- -moz-box-shadow: 0px 0px 15px 0px rgba(0, 5, 5, 0.2);
- box-shadow: 0px 0px 15px 0px rgba(0, 5, 5, 0.2);
-}
-.plans-table .free .cell:first-child,
-.plans-table .pro .cell:first-child {
- color: #fff;
- text-transform: uppercase;
- font-size: 24px;
- font-weight: 800;
- line-height: 60px;
- padding: 0;
- position: relative;
- bottom: -1px;
- border: none;
-}
-.plans-table .free .cell:first-child {
- background-color: #9b9b9b;
- margin-right: 15px;
- padding-right: 0;
-}
-.plans-table .free,
-.plans-table .desc, .plans-table .pro {
- border-bottom: 1px solid #dfe0e1;
-}
-.plans-table .pro .cell:first-child {
- background-color: #2299c0;
-}
-.plans-table .pro .cell:last-child {
- padding: 0;
-}
-.plans-table .desc .cell:first-child {
- background-color: transparent;
- border: none;
-}
-
-.compare-table .glyphicon,
-.plans-table .glyphicon {
- color: #fff;
- border-radius: 50px;
- padding: 5px;
- font-size: 10px;
-}
-.compare-table .glyphicon-remove,
-.plans-table .glyphicon-remove {
- background-color: #da4830;
-}
-.compare-table .glyphicon-ok,
-.plans-table .glyphicon-ok {
- background-color: #35c156;
-}
-.plans-table .glyphicon-star {
- border-radius: 0;
- background-color: #2e2b2b;
- display: block;
- width: 60px;
- height: 30px;
- position: absolute;
- top: -5px;
- right: -20px;
- -webkit-transform: rotate(45deg);
- -moz-transform: rotate(45deg);
- -o-transform: rotate(45deg);
- transform: rotate(45deg);
- padding: 13px 0 0 1px;
-}
-.plans-table .price {
- padding: 0;
-}
-.plans-table .free .price p {
- color: #35c156;
-}
-.plans-table .pro .price p {
- color: #2299c0;
-}
-.plans-table .price p {
- font-size: 40px;
- text-transform: uppercase;
- font-weight: 800;
- margin: 0;
- line-height: 55px;
-}
-.plans-table .price p span {
- font-size: 16px;
- text-transform: none;
- font-weight: 400;
-}
-.plans-table a .cta h2 {
- background: #2299c0;
- color: #fff;
- margin: 0;
-}
-.plans-table a .cta h2 span {
- background: #1e84a5;
-}
-
-
-table.compare-table td {
- height: 70px;
- vertical-align: middle !important;
-}
-table.compare-table th {
- height: 70px;
- vertical-align: middle !important;
- text-align: center;
- color: white;
-}
-table.compare-table td:first-child {
- text-align: left;
-}
-table.compare-table-free th {
- background-color: #0b4d78;
-}
-table.compare-table-paid th {
- background-color: #e37329;
-}
-
-
-@media (min-width: 992px) {
- .hide-desktop {display: none !important;}
-}
-
-@media (max-width: 992px) {
- .hide-phone {
- display: none !important;
- }
-}
-
-/* Hide bootstrap sort header icons */
-table.table thead .sorting:after { content: '' !important }
-table.table thead .sorting_asc:after { content: '' !important }
-table.table thead .sorting_desc:after { content: '' !important}
-table.table thead .sorting_asc_disabled:after { content: '' !important }
-table.table thead .sorting_desc_disabled:after { content: '' !important }
\ No newline at end of file
diff --git a/public/css/style.css b/public/css/style.css
index ddabc40c4928..b9714e2da294 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -114,6 +114,11 @@ table.dataTable tbody th, table.dataTable tbody td {
padding: 10px;
}
+table.data-table tr {
+ border-bottom: 1px solid #d0d0d0;
+ border-top: 1px solid #d0d0d0;
+}
+
.datepicker {
padding: 4px !important;
margin-top: 1px;
diff --git a/public/js/built.js b/public/js/built.js
index 3b1be8b9d74f..df28ee641dd5 100644
--- a/public/js/built.js
+++ b/public/js/built.js
@@ -31988,9 +31988,13 @@ NINJA.accountAddress = function(invoice) {
{text: account.address2},
{text: cityStatePostal},
{text: account.country ? account.country.name : ''},
- {text: invoice.account.custom_value1 ? invoice.account.custom_label1 + ' ' + invoice.account.custom_value1 : false},
- {text: invoice.account.custom_value2 ? invoice.account.custom_label2 + ' ' + invoice.account.custom_value2 : false}
];
+
+ if (invoice.is_pro) {
+ data.push({text: invoice.account.custom_value1 ? invoice.account.custom_label1 + ' ' + invoice.account.custom_value1 : false});
+ data.push({text: invoice.account.custom_value2 ? invoice.account.custom_label2 + ' ' + invoice.account.custom_value2 : false});
+ }
+
return NINJA.prepareDataList(data, 'accountAddress');
}
diff --git a/public/js/pdf.pdfmake.js b/public/js/pdf.pdfmake.js
index fb0588113fc5..2980f26fa97e 100644
--- a/public/js/pdf.pdfmake.js
+++ b/public/js/pdf.pdfmake.js
@@ -415,9 +415,13 @@ NINJA.accountAddress = function(invoice) {
{text: account.address2},
{text: cityStatePostal},
{text: account.country ? account.country.name : ''},
- {text: invoice.account.custom_value1 ? invoice.account.custom_label1 + ' ' + invoice.account.custom_value1 : false},
- {text: invoice.account.custom_value2 ? invoice.account.custom_label2 + ' ' + invoice.account.custom_value2 : false}
];
+
+ if (invoice.is_pro) {
+ data.push({text: invoice.account.custom_value1 ? invoice.account.custom_label1 + ' ' + invoice.account.custom_value1 : false});
+ data.push({text: invoice.account.custom_value2 ? invoice.account.custom_label2 + ' ' + invoice.account.custom_value2 : false});
+ }
+
return NINJA.prepareDataList(data, 'accountAddress');
}
diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php
index 34fe4f51939f..1c1aa173ae6c 100644
--- a/resources/lang/da/texts.php
+++ b/resources/lang/da/texts.php
@@ -815,5 +815,9 @@
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
\ No newline at end of file
diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php
index 0ab602f7279c..b570c290ddbc 100644
--- a/resources/lang/de/texts.php
+++ b/resources/lang/de/texts.php
@@ -814,5 +814,9 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index 84e9e16fc785..8e6cc99cc112 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -769,7 +769,7 @@ return array(
'iframe_url' => 'Website',
'iframe_url_help1' => 'Copy the following code to a page on your site.',
- 'iframe_url_help2' => 'Currently only supported with on-site gateways (ie, Stripe and Authorize.net). You can test the feature by clicking \'View as recipient\' for an invoice.',
+ 'iframe_url_help2' => 'You can test the feature by clicking \'View as recipient\' for an invoice.',
'auto_bill' => 'Auto Bill',
'military_time' => '24 Hour Time',
@@ -814,5 +814,10 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+ 'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
+
);
diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php
index 4b8071a8fd71..bec202bb0722 100644
--- a/resources/lang/es/texts.php
+++ b/resources/lang/es/texts.php
@@ -792,5 +792,9 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php
index af97cee24fd6..b8b9ea552357 100644
--- a/resources/lang/es_ES/texts.php
+++ b/resources/lang/es_ES/texts.php
@@ -814,5 +814,9 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
\ No newline at end of file
diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php
index d97faea24311..d37ed36bfe6f 100644
--- a/resources/lang/fr/texts.php
+++ b/resources/lang/fr/texts.php
@@ -806,5 +806,9 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php
index dd014c28161c..25e1163ef5b4 100644
--- a/resources/lang/fr_CA/texts.php
+++ b/resources/lang/fr_CA/texts.php
@@ -807,5 +807,9 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php
index a3022fd5d9da..495c16da9bb5 100644
--- a/resources/lang/it/texts.php
+++ b/resources/lang/it/texts.php
@@ -808,5 +808,9 @@ return array(
'notification_invoice_bounced_subject' => 'Unable to deliver Invoice :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
);
diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php
index baa7f7c9e3dd..78f1d3f375ad 100644
--- a/resources/lang/lt/texts.php
+++ b/resources/lang/lt/texts.php
@@ -815,6 +815,10 @@ return array(
'notification_invoice_bounced_subject' => 'Unable to deliver Invoice :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
);
diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php
index ae0f3691c751..087ff544e72d 100644
--- a/resources/lang/nb_NO/texts.php
+++ b/resources/lang/nb_NO/texts.php
@@ -814,4 +814,8 @@ return array(
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
+
);
\ No newline at end of file
diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php
index e72ec1aefc20..9813923b9f22 100644
--- a/resources/lang/nl/texts.php
+++ b/resources/lang/nl/texts.php
@@ -808,5 +808,9 @@ return array(
'notification_invoice_bounced_subject' => 'Unable to deliver Invoice :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
);
diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php
index 29f7084859aa..8bcfab53c6c1 100644
--- a/resources/lang/pt_BR/texts.php
+++ b/resources/lang/pt_BR/texts.php
@@ -808,5 +808,9 @@ return array(
'notification_invoice_bounced_subject' => 'Unable to deliver Invoice :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
);
diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php
index 5754ba7647e0..34c670c66d75 100644
--- a/resources/lang/sv/texts.php
+++ b/resources/lang/sv/texts.php
@@ -811,5 +811,9 @@ return array(
'notification_invoice_bounced_subject' => 'Unable to deliver Invoice :invoice',
'notification_quote_bounced' => 'We were unable to deliver Quote :invoice to :contact.',
'notification_quote_bounced_subject' => 'Unable to deliver Quote :invoice',
+
+ 'custom_invoice_link' => 'Custom Invoice Link',
+ 'total_invoiced' => 'Total Invoiced',
+ 'open_balance' => 'Open Balance',
);
diff --git a/resources/views/accounts/details.blade.php b/resources/views/accounts/details.blade.php
index ccbda5019553..b47f544140a6 100644
--- a/resources/views/accounts/details.blade.php
+++ b/resources/views/accounts/details.blade.php
@@ -42,7 +42,7 @@
{!! Former::text('work_phone') !!}
{!! Former::file('logo')->max(2, 'MB')->accept('image')->inlineHelp(trans('texts.logo_help')) !!}
- @if (file_exists($account->getLogoPath()))
+ @if ($account->hasLogo())
{!! HTML::image($account->getLogoPath().'?no_cache='.time(), 'Logo', ['width' => 200]) !!}
{{ trans('texts.remove_logo') }}
diff --git a/resources/views/accounts/email_templates.blade.php b/resources/views/accounts/email_templates.blade.php
deleted file mode 100644
index 71c5a2fcd021..000000000000
--- a/resources/views/accounts/email_templates.blade.php
+++ /dev/null
@@ -1,187 +0,0 @@
-@extends('accounts.nav')
-
-@section('head')
- @parent
-
-
-
-@stop
-
-@section('content')
- @parent
- @include('accounts.nav_advanced')
-
- {!! Former::open()->addClass('col-md-10 col-md-offset-1 warn-on-exit') !!}
- {!! Former::populateField('email_template_invoice', $invoiceEmail) !!}
- {!! Former::populateField('email_template_quote', $quoteEmail) !!}
- {!! Former::populateField('email_template_payment', $paymentEmail) !!}
-
-
-
-
{!! trans('texts.email_templates') !!}
-
-
-
-
-
-
-
-
-
-
-
- {!! Former::textarea('email_template_invoice')->raw() !!}
-
-
-
-
-
-
-
-
- {!! Former::textarea('email_template_quote')->raw() !!}
-
-
-
-
-
-
-
-
-
- {!! Former::textarea('email_template_payment')->raw() !!}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{!! trans('texts.reminder_emails') !!}
-
-
-
-
-
-
-
-
-
-
-
- {!! Former::textarea('email_template_invoice')->raw() !!}
-
-
-
-
-
-
-
-
- {!! Former::textarea('email_template_quote')->raw() !!}
-
-
-
-
-
-
-
-
-
- {!! Former::textarea('email_template_payment')->raw() !!}
-
-
-
-
-
-
-
-
-
-
-
-
-
- @if (Auth::user()->isPro())
-
- {!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
-
- @else
-
- @endif
-
- {!! Former::close() !!}
-
-
-
-@stop
diff --git a/resources/views/accounts/invoice_settings.blade.php b/resources/views/accounts/invoice_settings.blade.php
index ea878b361bfc..590373bcef60 100644
--- a/resources/views/accounts/invoice_settings.blade.php
+++ b/resources/views/accounts/invoice_settings.blade.php
@@ -4,6 +4,9 @@
@parent
+
+@stop
+
+@section('content')
+
+
+
+
+
+ @if ($account->hasLogo())
+ {!! HTML::image($account->getLogoPath()) !!}
+ @endif
+
+
+ @if ($account->address1)
+ {{ $account->address1 }}
+ @endif
+ @if ($account->address2)
+ {{ $account->address2 }}
+ @endif
+ @if ($account->getCityState())
+ {{ $account->getCityState() }}
+ @endif
+
+
+ @if ($account->work_phone)
+ {{ $account->work_phone }}
+ @endif
+ @if ($account->work_email)
+ {!! HTML::mailto($account->work_email, $account->work_email) !!}
+ @endif
+
+
+
+
+
+
+
+
+ {{ trans('texts.total_invoiced') }}
+
+
+ {{ Utils::formatMoney($client->paid_to_date + $client->balance, $client->currency_id ?: $account->currency_id) }}
+
+
+
+
+
+
+
+ {{ trans('texts.paid_to_date') }}
+
+
+ {{ Utils::formatMoney($client->paid_to_date, $client->currency_id ?: $account->currency_id) }}
+
+
+
+
+
+
+
+ {{ trans('texts.open_balance') }}
+
+
+ {{ Utils::formatMoney($client->balance, $client->currency_id ?: $account->currency_id) }}
+
+
+
+
+
+ {!! Datatable::table()
+ ->addColumn(
+ trans('texts.date'),
+ trans('texts.message'),
+ trans('texts.balance'),
+ trans('texts.adjustment'))
+ ->setUrl(route('api.client.activity'))
+ ->setOptions('bFilter', false)
+ ->setOptions('aaSorting', [['0', 'desc']])
+ ->setOptions('sPaginationType', 'bootstrap')
+ ->render('datatable') !!}
+
+
+
+@stop
\ No newline at end of file
diff --git a/resources/views/invoices/edit.blade.php b/resources/views/invoices/edit.blade.php
index 126f65d2ab6f..593745585cb5 100644
--- a/resources/views/invoices/edit.blade.php
+++ b/resources/views/invoices/edit.blade.php
@@ -104,7 +104,7 @@
@endif
- @if ($account->custom_invoice_text_label1 || $invoice && $account->custom_text_value1)
+ @if ($account->showCustomField('custom_invoice_text_label1', $invoice))
{!! Former::text('custom_text_value1')->label($account->custom_invoice_text_label1)->data_bind("value: custom_text_value1, valueUpdate: 'afterkeydown'") !!}
@endif
@@ -115,7 +115,7 @@
@elseif ($invoice && isset($lastSent) && $lastSent)
- {!! trans('texts.last_sent_on', ['date' => link_to('/invoices/'.$lastSent->public_id, Utils::dateToString($invoice->last_sent_date))]) !!}
+ {!! trans('texts.last_sent_on', ['date' => link_to('/invoices/'.$lastSent->public_id, Utils::dateToString($invoice->last_sent_date), ['id' => 'lastSent'])]) !!}
@endif
@endif
@@ -141,7 +141,7 @@
->addOption(trans('texts.discount_amount'), '1')->data_bind("value: is_amount_discount")->raw()
) !!}
- @if ($account->custom_invoice_text_label2 || $invoice && $account->custom_text_value2)
+ @if ($account->showCustomField('custom_invoice_text_label2', $invoice))
{!! Former::text('custom_text_value2')->label($account->custom_invoice_text_label2)->data_bind("value: custom_text_value2, valueUpdate: 'afterkeydown'") !!}
@endif
@@ -261,7 +261,7 @@
|
- @if (($account->custom_invoice_label1 || ($invoice && floatval($invoice->custom_value1)) != 0) && $account->custom_invoice_taxes1)
+ @if ($account->showCustomField('custom_invoice_label1', $invoice) && $account->custom_invoice_taxes1)
|
|
@@ -270,7 +270,7 @@
@endif
- @if (($account->custom_invoice_label2 || ($invoice && floatval($invoice->custom_value2)) != 0) && $account->custom_invoice_taxes2)
+ @if ($account->showCustomField('custom_invoice_label2', $invoice) && $account->custom_invoice_taxes2)
|
|
@@ -298,7 +298,7 @@
|
- @if (($account->custom_invoice_label1 || ($invoice && floatval($invoice->custom_value1)) != 0) && !$account->custom_invoice_taxes1)
+ @if ($account->showCustomField('custom_invoice_label1', $invoice) && !$account->custom_invoice_taxes1)
|
|
@@ -307,7 +307,7 @@
@endif
- @if (($account->custom_invoice_label2 || ($invoice && floatval($invoice->custom_value2)) != 0) && !$account->custom_invoice_taxes2)
+ @if ($account->showCustomField('custom_invoice_label2', $invoice) && !$account->custom_invoice_taxes2)
|
|
diff --git a/resources/views/invoices/pdf.blade.php b/resources/views/invoices/pdf.blade.php
index 311346274752..3dcd365f9e6b 100644
--- a/resources/views/invoices/pdf.blade.php
+++ b/resources/views/invoices/pdf.blade.php
@@ -72,10 +72,11 @@
@endif
var NINJA = NINJA || {};
- NINJA.primaryColor = "{{ $account->primary_color }}";
- NINJA.secondaryColor = "{{ $account->secondary_color }}";
- NINJA.fontSize = {{ $account->font_size }};
-
+ @if (Utils::isPro())
+ NINJA.primaryColor = "{{ $account->primary_color }}";
+ NINJA.secondaryColor = "{{ $account->secondary_color }}";
+ NINJA.fontSize = {{ $account->font_size }};
+ @endif
var invoiceLabels = {!! json_encode($account->getInvoiceLabels()) !!};
if (window.invoice) {
diff --git a/resources/views/invoices/view.blade.php b/resources/views/invoices/view.blade.php
index 64fdac4f76e4..9b96c0d44103 100644
--- a/resources/views/invoices/view.blade.php
+++ b/resources/views/invoices/view.blade.php
@@ -33,7 +33,7 @@
@if (count($paymentTypes) > 1)
{!! DropdownButton::success(trans('texts.pay_now'))->withContents($paymentTypes)->large() !!}
@else
- {!! link_to(URL::to($paymentURL), trans('texts.pay_now'), ['class' => 'btn btn-success btn-lg']) !!}
+ {{ trans('texts.pay_now') }}
@endif
@else
{!! Button::normal('Download PDF')->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}
diff --git a/resources/views/partials/fb_pixel_checkout.blade.php b/resources/views/partials/fb_pixel_checkout.blade.php
deleted file mode 100644
index 66c36c883203..000000000000
--- a/resources/views/partials/fb_pixel_checkout.blade.php
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/views/public/header.blade.php b/resources/views/public/header.blade.php
index 36752c2fd4d5..2375f27301c8 100644
--- a/resources/views/public/header.blade.php
+++ b/resources/views/public/header.blade.php
@@ -1,123 +1,7 @@
@extends('master')
@section('head')
-
-
-
-
+
@stop
@section('body')
@@ -184,6 +68,9 @@ table.table thead .sorting_desc_disabled:after { content: '' !important }
@if (!isset($hideHeader) || !$hideHeader)
+ -
+ {!! link_to('/client/dashboard', trans('texts.dashboard') ) !!}
+
-
{!! link_to('/client/quotes', trans('texts.quotes') ) !!}
diff --git a/resources/views/public_list.blade.php b/resources/views/public_list.blade.php
index 3689b273daba..a5868073cb4d 100644
--- a/resources/views/public_list.blade.php
+++ b/resources/views/public_list.blade.php
@@ -3,80 +3,25 @@
@section('content')
@@ -86,7 +31,7 @@
diff --git a/storage/pdfcache/.gitignore b/storage/pdfcache/.gitignore
deleted file mode 100755
index c96a04f008ee..000000000000
--- a/storage/pdfcache/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*
-!.gitignore
\ No newline at end of file
diff --git a/tests/_support/AcceptanceTester.php b/tests/_support/AcceptanceTester.php
index ac8fe46eb605..fd89ac0d0de0 100644
--- a/tests/_support/AcceptanceTester.php
+++ b/tests/_support/AcceptanceTester.php
@@ -31,7 +31,7 @@ class AcceptanceTester extends \Codeception\Actor
$I->amOnPage('/login');
$I->fillField(['name' => 'email'], Fixtures::get('username'));
$I->fillField(['name' => 'password'], Fixtures::get('password'));
- $I->click('Let\'s go');
+ $I->click('Login');
//$I->saveSessionSnapshot('login');
}
diff --git a/tests/_support/FunctionalTester.php b/tests/_support/FunctionalTester.php
index 173b7a82e7a6..87e4f0234c27 100644
--- a/tests/_support/FunctionalTester.php
+++ b/tests/_support/FunctionalTester.php
@@ -27,11 +27,10 @@ class FunctionalTester extends \Codeception\Actor
function checkIfLogin(\FunctionalTester $I)
{
//if ($I->loadSessionSnapshot('login')) return;
-
$I->amOnPage('/login');
$I->fillField(['name' => 'email'], Fixtures::get('username'));
$I->fillField(['name' => 'password'], Fixtures::get('password'));
- $I->click('Let\'s go');
+ $I->click('#loginButton');
//$I->saveSessionSnapshot('login');
}
diff --git a/tests/_support/_generated/FunctionalTesterActions.php b/tests/_support/_generated/FunctionalTesterActions.php
index 06431340137a..cffb7b2e0c8b 100644
--- a/tests/_support/_generated/FunctionalTesterActions.php
+++ b/tests/_support/_generated/FunctionalTesterActions.php
@@ -1,4 +1,4 @@
-First
+ * Second
+ * Third
+ * ```
+ *
+ * ```php
+ * grabMultiple('a');
+ *
+ * // would return ['#first', '#second', '#third']
+ * $aLinks = $I->grabMultiple('a', 'href');
+ * ?>
+ * ```
+ *
+ * @param $cssOrXpath
+ * @param $attribute
+ * @return string[]
* @see \Codeception\Lib\InnerBrowser::grabMultiple()
*/
public function grabMultiple($cssOrXpath, $attribute = null) {
@@ -1972,6 +1993,30 @@ trait FunctionalTesterActions
}
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Switch to iframe or frame on the page.
+ *
+ * Example:
+ * ``` html
+ *