From 7db4fd8cd07a7cf387cf507f9f2071b014b61580 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 29 Jul 2015 10:01:03 +0300 Subject: [PATCH 01/16] Fix #379 Error after /setup: business.js missing but required? --- database/seeds/PaymentLibrariesSeeder.php | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/database/seeds/PaymentLibrariesSeeder.php b/database/seeds/PaymentLibrariesSeeder.php index 8f36a42fa2d6..73eb34c0e438 100644 --- a/database/seeds/PaymentLibrariesSeeder.php +++ b/database/seeds/PaymentLibrariesSeeder.php @@ -147,17 +147,21 @@ class PaymentLibrariesSeeder extends Seeder 'Photo', ]; - foreach ($designs as $design) { + for ($i=0; $ifirst(); - if (!$record) { - $record = new InvoiceDesign; - $record->name = $design; + if (file_exists($fileName)) { + $pdfmake = file_get_contents($fileName); + if ($pdfmake) { + $record = InvoiceDesign::whereName($design)->first(); + if (!$record) { + $record = new InvoiceDesign; + $record->id = $i + 1; + $record->name = $design; + } + $record->pdfmake = $pdfmake; + $record->save(); } - $record->pdfmake = $pdfmake; - $record->save(); } } } From abe3eb6367c4625d853f27f43fed641c4ea87215 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 29 Jul 2015 10:52:10 +0300 Subject: [PATCH 02/16] Standardized headers across html emails --- resources/views/emails/confirm_html.blade.php | 6 ++++- resources/views/emails/invoice_html.blade.php | 6 ++++- .../views/emails/invoice_paid_html.blade.php | 2 +- .../views/emails/invoice_sent_html.blade.php | 2 +- .../emails/invoice_viewed_html.blade.php | 2 +- .../license_confirmation_html.blade.php | 24 +++++++++---------- .../payment_confirmation_html.blade.php | 10 ++++---- .../emails/quote_approved_html.blade.php | 2 +- 8 files changed, 31 insertions(+), 23 deletions(-) diff --git a/resources/views/emails/confirm_html.blade.php b/resources/views/emails/confirm_html.blade.php index e2e94d7fda51..fe4b73a847aa 100644 --- a/resources/views/emails/confirm_html.blade.php +++ b/resources/views/emails/confirm_html.blade.php @@ -1,4 +1,8 @@ - + + + + + @if (false && !$invitationMessage) @include('emails.confirm_action', ['user' => $user]) diff --git a/resources/views/emails/invoice_html.blade.php b/resources/views/emails/invoice_html.blade.php index 92f5f1a3f9b0..a0d2526a6e26 100644 --- a/resources/views/emails/invoice_html.blade.php +++ b/resources/views/emails/invoice_html.blade.php @@ -1,4 +1,8 @@ - + + + + + @if (false) @include('emails.view_action', ['link' => $link, 'entityType' => $entityType]) diff --git a/resources/views/emails/invoice_paid_html.blade.php b/resources/views/emails/invoice_paid_html.blade.php index 001ab0796e21..07e478b0338d 100644 --- a/resources/views/emails/invoice_paid_html.blade.php +++ b/resources/views/emails/invoice_paid_html.blade.php @@ -1,5 +1,5 @@ - + diff --git a/resources/views/emails/invoice_sent_html.blade.php b/resources/views/emails/invoice_sent_html.blade.php index 5ee266c7d203..3426820e1db3 100644 --- a/resources/views/emails/invoice_sent_html.blade.php +++ b/resources/views/emails/invoice_sent_html.blade.php @@ -1,5 +1,5 @@ - + diff --git a/resources/views/emails/invoice_viewed_html.blade.php b/resources/views/emails/invoice_viewed_html.blade.php index 957b6bff8efa..60fd6faaae65 100644 --- a/resources/views/emails/invoice_viewed_html.blade.php +++ b/resources/views/emails/invoice_viewed_html.blade.php @@ -1,5 +1,5 @@ - + diff --git a/resources/views/emails/license_confirmation_html.blade.php b/resources/views/emails/license_confirmation_html.blade.php index 172e299e3f77..f7950158958c 100644 --- a/resources/views/emails/license_confirmation_html.blade.php +++ b/resources/views/emails/license_confirmation_html.blade.php @@ -1,18 +1,18 @@ - - - - - + + + + + - {{ $client }},

+ {{ $client }},

- {{ trans('texts.payment_message', ['amount' => $amount]) }}

+ {{ trans('texts.payment_message', ['amount' => $amount]) }}

- {{ $license }}

+ {{ $license }}

- {{ trans('texts.email_signature') }}
- {{ $account }} - - + {{ trans('texts.email_signature') }}
+ {{ $account }} + + \ No newline at end of file diff --git a/resources/views/emails/payment_confirmation_html.blade.php b/resources/views/emails/payment_confirmation_html.blade.php index 4459df93e100..7e944a2f39fb 100644 --- a/resources/views/emails/payment_confirmation_html.blade.php +++ b/resources/views/emails/payment_confirmation_html.blade.php @@ -1,7 +1,7 @@ - - - - - {!! $body !!} + + + + +{!! $body !!} diff --git a/resources/views/emails/quote_approved_html.blade.php b/resources/views/emails/quote_approved_html.blade.php index a9daf05981d8..4f1396a1a81b 100644 --- a/resources/views/emails/quote_approved_html.blade.php +++ b/resources/views/emails/quote_approved_html.blade.php @@ -1,5 +1,5 @@ - + From 914334511ee59a8100fa9088e42c95339eddbcaa Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Wed, 29 Jul 2015 22:55:12 +0300 Subject: [PATCH 03/16] Enhancements to the dashboard --- app/Http/Controllers/AccountController.php | 2 +- app/Http/Controllers/AppController.php | 4 +- app/Http/Controllers/DashboardController.php | 83 +++++++++++++++----- app/Http/Controllers/PaymentController.php | 1 + app/Http/Controllers/UserController.php | 9 ++- app/Models/Client.php | 14 +++- app/Models/Invoice.php | 7 +- public/css/built.css | 5 +- public/css/style.css | 5 +- public/js/built.js | 6 +- resources/lang/en/texts.php | 5 +- resources/views/dashboard.blade.php | 73 ++++++++++++----- resources/views/payments/payment.blade.php | 2 +- resources/views/tasks/edit.blade.php | 9 +-- resources/views/user_account.blade.php | 6 +- storage/templates/bold.js | 4 +- storage/templates/clean.js | 19 ++--- storage/templates/modern.js | 6 +- storage/templates/plain.js | 6 +- 19 files changed, 175 insertions(+), 91 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 204e270c7e3a..b781e41887d2 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -211,7 +211,7 @@ class AccountController extends BaseController $client->work_email = ''; $invoice->invoice_number = $account->getNextInvoiceNumber(); - $invoice->invoice_date = date_create()->format('Y-m-d'); + $invoice->invoice_date = Utils::fromSqlDate(date('Y-m-d')); $invoice->account = json_decode($account->toJson()); $invoice->amount = $invoice->balance = 100; diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php index dac4b85ccbbb..91d716cf253d 100644 --- a/app/Http/Controllers/AppController.php +++ b/app/Http/Controllers/AppController.php @@ -88,7 +88,9 @@ class AppController extends BaseController "MAIL_HOST={$mail['host']}\n". "MAIL_USERNAME={$mail['username']}\n". "MAIL_FROM_NAME={$mail['from']['name']}\n". - "MAIL_PASSWORD={$mail['password']}\n"; + "MAIL_PASSWORD={$mail['password']}\n\n". + "ADMIN_USER_ID=1\n". + "ALLOW_NEW_ACCOUNTS\n"; // Write Config Settings $fp = fopen(base_path()."/.env", 'w'); diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index e286b885cbf6..292f09336be2 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -5,6 +5,7 @@ use DB; use View; use App\Models\Activity; use App\Models\Invoice; +use App\Models\Payment; class DashboardController extends BaseController { @@ -50,41 +51,81 @@ class DashboardController extends BaseController ->groupBy(DB::raw('CASE WHEN clients.currency_id IS NULL THEN CASE WHEN accounts.currency_id IS NULL THEN 1 ELSE accounts.currency_id END ELSE clients.currency_id END')) ->get(); - + $select = DB::raw('SUM(clients.balance) as value, clients.currency_id as currency_id'); + $balances = DB::table('accounts') + ->select($select) + ->leftJoin('clients', 'accounts.id', '=', 'clients.account_id') + ->where('accounts.id', '=', Auth::user()->account_id) + ->where('clients.is_deleted', '=', false) + ->groupBy('accounts.id') + ->groupBy(DB::raw('CASE WHEN clients.currency_id IS NULL THEN CASE WHEN accounts.currency_id IS NULL THEN 1 ELSE accounts.currency_id END ELSE clients.currency_id END')) + ->get(); $activities = Activity::where('activities.account_id', '=', Auth::user()->account_id) ->where('activity_type_id', '>', 0) - ->orderBy('created_at', 'desc')->take(14)->get(); + ->orderBy('created_at', 'desc') + ->take(50) + ->get(); - $pastDue = Invoice::scope()->whereHas('client', function($query) { - $query->where('deleted_at', '=', null); - }) - ->where('due_date', '<', date('Y-m-d')) - ->where('balance', '>', 0) - ->where('is_recurring', '=', false) - ->where('is_quote', '=', false) - ->where('is_deleted', '=', false) - ->orderBy('due_date', 'asc')->take(6)->get(); + $pastDue = DB::table('invoices') + ->leftJoin('clients', 'clients.id', '=', 'invoices.client_id') + ->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id') + ->where('invoices.account_id', '=', Auth::user()->account_id) + ->where('clients.deleted_at', '=', null) + ->where('contacts.deleted_at', '=', null) + ->where('invoices.is_recurring', '=', false) + ->where('invoices.is_quote', '=', false) + ->where('invoices.balance', '>', 0) + ->where('invoices.is_deleted', '=', false) + ->where('contacts.is_primary', '=', true) + ->where('invoices.due_date', '<', date('Y-m-d')) + ->select(['invoices.due_date', 'invoices.balance', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id']) + ->orderBy('invoices.due_date', 'asc') + ->take(50) + ->get(); + + $upcoming = DB::table('invoices') + ->leftJoin('clients', 'clients.id', '=', 'invoices.client_id') + ->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id') + ->where('invoices.account_id', '=', Auth::user()->account_id) + ->where('clients.deleted_at', '=', null) + ->where('contacts.deleted_at', '=', null) + ->where('invoices.is_recurring', '=', false) + ->where('invoices.is_quote', '=', false) + ->where('invoices.balance', '>', 0) + ->where('invoices.is_deleted', '=', false) + ->where('contacts.is_primary', '=', true) + ->where('invoices.due_date', '>=', date('Y-m-d')) + ->orderBy('invoices.due_date', 'asc') + ->take(50) + ->select(['invoices.due_date', 'invoices.balance', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id']) + ->get(); + + $payments = DB::table('payments') + ->leftJoin('clients', 'clients.id', '=', 'payments.client_id') + ->leftJoin('contacts', 'contacts.client_id', '=', 'clients.id') + ->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id') + ->where('payments.account_id', '=', Auth::user()->account_id) + ->where('clients.deleted_at', '=', null) + ->where('contacts.deleted_at', '=', null) + ->where('contacts.is_primary', '=', true) + ->select(['payments.payment_date', 'payments.amount', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id']) + ->orderBy('payments.payment_date', 'asc') + ->take(50) + ->get(); - $upcoming = Invoice::scope()->whereHas('client', function($query) { - $query->where('deleted_at', '=', null); - }) - ->where('due_date', '>=', date('Y-m-d')) - ->where('balance', '>', 0) - ->where('is_recurring', '=', false) - ->where('is_quote', '=', false) - ->where('is_deleted', '=', false) - ->orderBy('due_date', 'asc')->take(6)->get(); $data = [ + 'account' => Auth::user()->account, 'paidToDate' => $paidToDate, + 'balances' => $balances, 'averageInvoice' => $averageInvoice, - //'billedClients' => $metrics ? $metrics->billed_clients : 0, 'invoicesSent' => $metrics ? $metrics->invoices_sent : 0, 'activeClients' => $metrics ? $metrics->active_clients : 0, 'activities' => $activities, 'pastDue' => $pastDue, 'upcoming' => $upcoming, + 'payments' => $payments, 'title' => trans('texts.dashboard'), ]; diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 6248a8e6917b..8b70a780bdfe 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -336,6 +336,7 @@ class PaymentController extends BaseController 'acceptedCreditCardTypes' => $acceptedCreditCardTypes, 'countries' => Cache::get('countries'), 'currencyId' => $client->getCurrencyId(), + 'currencyCode' => $client->currency->code, 'account' => $client->account, 'hideLogo' => $account->isWhiteLabel(), 'showAddress' => $accountGateway->show_address, diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index dedd752190fb..d90c821414e1 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -95,7 +95,7 @@ class UserController extends BaseController $user->force_pdfjs = true; $user->save(); - Session::flash('message', trans('texts.security.updated_settings')); + Session::flash('message', trans('texts.updated_settings')); return Redirect::to('/dashboard'); } @@ -132,9 +132,12 @@ class UserController extends BaseController */ public function create() { - if (!Auth::user()->confirmed) { + if (!Auth::user()->registered) { Session::flash('error', trans('texts.register_to_add_user')); - + return Redirect::to('company/advanced_settings/user_management'); + } + if (!Auth::user()->confirmed) { + Session::flash('error', trans('texts.confirmation_required')); return Redirect::to('company/advanced_settings/user_management'); } diff --git a/app/Models/Client.php b/app/Models/Client.php index f2357742e0bd..a9b6c8fe95d3 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -76,14 +76,16 @@ class Client extends EntityModel { return $this->name; } - + public function getDisplayName() { if ($this->name) { return $this->name; } - - $this->load('contacts'); + + if (!$this->contacts || !count($this->contacts)) { + $this->load('contacts'); + } $contact = $this->contacts()->first(); @@ -152,11 +154,15 @@ class Client extends EntityModel public function getCurrencyId() { + if ($this->currency_id) { + return $this->currency_id; + } + if (!$this->account) { $this->load('account'); } - return $this->currency_id ?: ($this->account->currency_id ?: DEFAULT_CURRENCY); + return $this->account->currency_id ?: DEFAULT_CURRENCY; } } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 27c0999c7a2c..a1f01a5b5040 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -69,9 +69,14 @@ class Invoice extends EntityModel return storage_path() . '/pdfcache/cache-' . $this->id . '.pdf'; } + public static function calcLink($invoice) + { + return link_to('invoices/' . $invoice->public_id, $invoice->invoice_number); + } + public function getLink() { - return link_to('invoices/'.$this->public_id, $this->invoice_number); + return self::calcLink($this); } public function getEntityType() diff --git a/public/css/built.css b/public/css/built.css index ab4839c61fd8..11b6949e6a52 100644 --- a/public/css/built.css +++ b/public/css/built.css @@ -2839,15 +2839,12 @@ background-clip: padding-box; .dashboard .panel-body {padding: 0;} -.dashboard .table-striped>tbody>tr>td, .table-striped>tbody>tr>th { background-color: #fbfbfb;} -.dashboard .table-striped>tbody>tr:nth-child(odd)>tr, .table-striped>tbody>tr:nth-child(odd)>th { -background-color: #fff; -} .dashboard th { border-left: none; background-color: #fbfbfb; border-bottom: 1px solid #dfe0e1; } + .dashboard table.table thead > tr > th { border-bottom-width: 1px; } diff --git a/public/css/style.css b/public/css/style.css index 6c31f3041907..3ce1b63ae67a 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -489,15 +489,12 @@ background-clip: padding-box; .dashboard .panel-body {padding: 0;} -.dashboard .table-striped>tbody>tr>td, .table-striped>tbody>tr>th { background-color: #fbfbfb;} -.dashboard .table-striped>tbody>tr:nth-child(odd)>tr, .table-striped>tbody>tr:nth-child(odd)>th { -background-color: #fff; -} .dashboard th { border-left: none; background-color: #fbfbfb; border-bottom: 1px solid #dfe0e1; } + .dashboard table.table thead > tr > th { border-bottom-width: 1px; } diff --git a/public/js/built.js b/public/js/built.js index 8902b492b635..fc0fa403d399 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -29434,12 +29434,12 @@ for(n=[],r=[],s=0,f=t.rows[0].cells.length,c=t.clientWidth;f>s;)l=t.rows[0].cell t.events.push(["addFonts",function(t){var e,n,i,o,a,u="Unicode";for(n in t.fonts)t.fonts.hasOwnProperty(n)&&(e=t.fonts[n],i=s[u][e.PostScriptName],i&&(o=e.metadata[u]?e.metadata[u]:e.metadata[u]={},o.widths=i.widths,o.kerning=i.kerning),a=r[u][e.PostScriptName],a&&(o=e.metadata[u]?e.metadata[u]:e.metadata[u]={},o.encoding=a,a.codePages&&a.codePages.length&&(e.encoding=a.codePages[0])))}])}(n.API),function(t){"use strict";t.putTotalPages=function(t){for(var e=new RegExp(t,"g"),n=1;n<=this.internal.getNumberOfPages();n++)for(var r=0;ru;u++)s+=String.fromCharCode(i[u]);n.push(s)}else if("Blob"===e(t)||"File"===e(t)){if(!o)throw new a("NOT_READABLE_ERR");var l=new o;n.push(l.readAsBinaryString(t))}else t instanceof r?"base64"===t.encoding&&m?n.push(m(t.data)):"URI"===t.encoding?n.push(decodeURIComponent(t.data)):"raw"===t.encoding&&n.push(t.data):("string"!=typeof t&&(t+=""),n.push(unescape(encodeURIComponent(t))))},s.getBlob=function(t){return arguments.length||(t=null),new r(this.data.join(""),t,"raw")},s.toString=function(){return"[object BlobBuilder]"},i.slice=function(t,e,n){var s=arguments.length;return 3>s&&(n=null),new r(this.data.slice(t,s>1?e:this.data.length),n,this.encoding)},i.toString=function(){return"[object Blob]"},i.close=function(){this.size=0,delete this.data},n}(t);t.Blob=function(t,e){var r=e?e.type||"":"",s=new n;if(t)for(var i=0,o=t.length;o>i;i++)s.append(t[i]);return s.getBlob(r)}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content||this);var r=r||"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob&&navigator.msSaveOrOpenBlob.bind(navigator)||function(t){"use strict";if("undefined"==typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var e=t.document,n=function(){return t.URL||t.webkitURL||t},r=e.createElementNS("http://www.w3.org/1999/xhtml","a"),s="download"in r,i=function(n){var r=e.createEvent("MouseEvents");r.initMouseEvent("click",!0,!1,t,0,0,0,0,0,!1,!1,!1,!1,0,null),n.dispatchEvent(r)},o=t.webkitRequestFileSystem,a=t.requestFileSystem||o||t.mozRequestFileSystem,u=function(e){(t.setImmediate||t.setTimeout)(function(){throw e},0)},c="application/octet-stream",l=0,f=10,d=function(e){var r=function(){"string"==typeof e?n().revokeObjectURL(e):e.remove()};t.chrome?r():setTimeout(r,f)},h=function(t,e,n){e=[].concat(e);for(var r=e.length;r--;){var s=t["on"+e[r]];if("function"==typeof s)try{s.call(t,n||t)}catch(i){u(i)}}},p=function(e,u){var f,p,m,w=this,g=e.type,y=!1,v=function(){h(w,"writestart progress write writeend".split(" "))},b=function(){if((y||!f)&&(f=n().createObjectURL(e)),p)p.location.href=f;else{var r=t.open(f,"_blank");void 0==r&&"undefined"!=typeof safari&&(t.location.href=f)}w.readyState=w.DONE,v(),d(f)},q=function(t){return function(){return w.readyState!==w.DONE?t.apply(this,arguments):void 0}},x={create:!0,exclusive:!1};return w.readyState=w.INIT,u||(u="download"),s?(f=n().createObjectURL(e),r.href=f,r.download=u,i(r),w.readyState=w.DONE,v(),void d(f)):(t.chrome&&g&&g!==c&&(m=e.slice||e.webkitSlice,e=m.call(e,0,e.size,c),y=!0),o&&"download"!==u&&(u+=".download"),(g===c||o)&&(p=t),a?(l+=e.size,void a(t.TEMPORARY,l,q(function(t){t.root.getDirectory("saved",x,q(function(t){var n=function(){t.getFile(u,x,q(function(t){t.createWriter(q(function(n){n.onwriteend=function(e){p.location.href=t.toURL(),w.readyState=w.DONE,h(w,"writeend",e),d(t)},n.onerror=function(){var t=n.error;t.code!==t.ABORT_ERR&&b()},"writestart progress write abort".split(" ").forEach(function(t){n["on"+t]=w["on"+t]}),n.write(e),w.abort=function(){n.abort(),w.readyState=w.DONE},w.readyState=w.WRITING}),b)}),b)};t.getFile(u,{create:!1},q(function(t){t.remove(),n()}),q(function(t){t.code===t.NOT_FOUND_ERR?n():b()}))}),b)}),b)):void b())},m=p.prototype,w=function(t,e){return new p(t,e)};return m.abort=function(){var t=this;t.readyState=t.DONE,h(t,"abort")},m.readyState=m.INIT=0,m.WRITING=1,m.DONE=2,m.error=m.onwritestart=m.onprogress=m.onwrite=m.onabort=m.onerror=m.onwriteend=null,w}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this.content);"undefined"!=typeof module&&null!==module&&(module.exports=r),void function(t,e){"object"==typeof module?module.exports=e():t.adler32cs=e()}(n,function(){var t="function"==typeof ArrayBuffer&&"function"==typeof Uint8Array,e=null,n=function(){if(!t)return function(){return!1};try{var n=require("buffer");"function"==typeof n.Buffer&&(e=n.Buffer)}catch(r){}return function(t){return t instanceof ArrayBuffer||null!==e&&t instanceof e}}(),r=function(){return null!==e?function(t){return new e(t,"utf8").toString("binary")}:function(t){return unescape(encodeURIComponent(t))}}(),s=65521,i=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;o>i;i++)n=(n+(255&e.charCodeAt(i)))%s,r=(r+n)%s;return(r<<16|n)>>>0},o=function(t,e){for(var n=65535&t,r=t>>>16,i=0,o=e.length;o>i;i++)n=(n+e[i])%s,r=(r+n)%s;return(r<<16|n)>>>0},a={},u=a.Adler32=function(){var e=function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(!isFinite(t=null==t?1:+t))throw new Error("First arguments needs to be a finite number.");this.checksum=t>>>0},s=e.prototype={};return s.constructor=e,e.from=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");this.checksum=i(1,t.toString())}),e.fromUtf8=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(null==t)throw new Error("First argument needs to be a string.");var n=r(t.toString());this.checksum=i(1,n)}),t&&(e.fromBuffer=function(t){return t.prototype=s,t}(function(t){if(!(this instanceof e))throw new TypeError("Constructor cannot called be as a function.");if(!n(t))throw new Error("First argument needs to be ArrayBuffer.");var r=new Uint8Array(t);return this.checksum=o(1,r)})),s.update=function(t){if(null==t)throw new Error("First argument needs to be a string.");return t=t.toString(),this.checksum=i(this.checksum,t)},s.updateUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=r(t.toString());return this.checksum=i(this.checksum,e)},t&&(s.updateBuffer=function(t){if(!n(t))throw new Error("First argument needs to be ArrayBuffer.");var e=new Uint8Array(t);return this.checksum=o(this.checksum,e)}),s.clone=function(){return new u(this.checksum)},e}();return a.from=function(t){if(null==t)throw new Error("First argument needs to be a string.");return i(1,t.toString())},a.fromUtf8=function(t){if(null==t)throw new Error("First argument needs to be a string.");var e=r(t.toString());return i(1,e)},t&&(a.fromBuffer=function(t){if(!n(t))throw new Error("First argument need to be ArrayBuffer.");var e=new Uint8Array(t);return o(1,e)}),a});var s=function(){function t(){function t(t){var e,n,s,i,a,u,c=r.dyn_tree,l=r.stat_desc.static_tree,f=r.stat_desc.extra_bits,h=r.stat_desc.extra_base,p=r.stat_desc.max_length,m=0;for(i=0;o>=i;i++)t.bl_count[i]=0;for(c[2*t.heap[t.heap_max]+1]=0,e=t.heap_max+1;d>e;e++)n=t.heap[e],i=c[2*c[2*n+1]+1]+1,i>p&&(i=p,m++),c[2*n+1]=i,n>r.max_code||(t.bl_count[i]++,a=0,n>=h&&(a=f[n-h]),u=c[2*n],t.opt_len+=u*(i+a),l&&(t.static_len+=u*(l[2*n+1]+a)));if(0!==m){do{for(i=p-1;0===t.bl_count[i];)i--;t.bl_count[i]--,t.bl_count[i+1]+=2,t.bl_count[p]--,m-=2}while(m>0);for(i=p;0!==i;i--)for(n=t.bl_count[i];0!==n;)s=t.heap[--e],s>r.max_code||(c[2*s+1]!=i&&(t.opt_len+=(i-c[2*s+1])*c[2*s],c[2*s+1]=i),n--)}}function e(t,e){var n=0;do n|=1&t,t>>>=1,n<<=1;while(--e>0);return n>>>1}function n(t,n,r){var s,i,a,u=[],c=0;for(s=1;o>=s;s++)u[s]=c=c+r[s-1]<<1;for(i=0;n>=i;i++)a=t[2*i+1],0!==a&&(t[2*i]=e(u[a]++,a))}var r=this;r.build_tree=function(e){var s,i,o,a=r.dyn_tree,u=r.stat_desc.static_tree,c=r.stat_desc.elems,l=-1;for(e.heap_len=0,e.heap_max=d,s=0;c>s;s++)0!==a[2*s]?(e.heap[++e.heap_len]=l=s,e.depth[s]=0):a[2*s+1]=0;for(;e.heap_len<2;)o=e.heap[++e.heap_len]=2>l?++l:0,a[2*o]=1,e.depth[o]=0,e.opt_len--,u&&(e.static_len-=u[2*o+1]);for(r.max_code=l,s=Math.floor(e.heap_len/2);s>=1;s--)e.pqdownheap(a,s);o=c;do s=e.heap[1],e.heap[1]=e.heap[e.heap_len--],e.pqdownheap(a,1),i=e.heap[1],e.heap[--e.heap_max]=s,e.heap[--e.heap_max]=i,a[2*o]=a[2*s]+a[2*i],e.depth[o]=Math.max(e.depth[s],e.depth[i])+1,a[2*s+1]=a[2*i+1]=o,e.heap[1]=o++,e.pqdownheap(a,1);while(e.heap_len>=2);e.heap[--e.heap_max]=e.heap[1],t(e),n(a,r.max_code,e.bl_count)}}function e(t,e,n,r,s){var i=this;i.static_tree=t,i.extra_bits=e,i.extra_base=n,i.elems=r,i.max_length=s}function n(t,e,n,r,s){var i=this;i.good_length=t,i.max_lazy=e,i.nice_length=n,i.max_chain=r,i.func=s}function r(t,e,n,r){var s=t[2*e],i=t[2*n];return i>s||s==i&&r[e]<=r[n]}function s(){function n(){var t;for(Te=2*Ce,Be[Pe-1]=0,t=0;Pe-1>t;t++)Be[t]=0;Je=N[Xe].max_lazy,Ke=N[Xe].good_length,Qe=N[Xe].nice_length,Ve=N[Xe].max_chain,Me=0,Ue=0,Ge=0,Ne=We=Z-1,je=0,Oe=0}function s(){var t;for(t=0;f>t;t++)$e[2*t]=0;for(t=0;a>t;t++)Ze[2*t]=0;for(t=0;u>t;t++)tn[2*t]=0;$e[2*h]=1,en.opt_len=en.static_len=0,un=ln=0}function i(){nn.dyn_tree=$e,nn.stat_desc=e.static_l_desc,rn.dyn_tree=Ze,rn.stat_desc=e.static_d_desc,sn.dyn_tree=tn,sn.stat_desc=e.static_bl_desc,dn=0,hn=0,fn=8,s()}function o(t,e){var n,r,s=-1,i=t[1],o=0,a=7,u=4;for(0===i&&(a=138,u=3),t[2*(e+1)+1]=65535,n=0;e>=n;n++)r=i,i=t[2*(n+1)+1],++oo?tn[2*r]+=o:0!==r?(r!=s&&tn[2*r]++,tn[2*m]++):10>=o?tn[2*w]++:tn[2*g]++,o=0,s=r,0===i?(a=138,u=3):r==i?(a=6,u=3):(a=7,u=4))}function c(){var e;for(o($e,nn.max_code),o(Ze,rn.max_code),sn.build_tree(en),e=u-1;e>=3&&0===tn[2*t.bl_order[e]+1];e--);return en.opt_len+=3*(e+1)+5+5+4,e}function d(t){en.pending_buf[en.pending++]=t}function p(t){d(255&t),d(t>>>8&255)}function O(t){d(t>>8&255),d(255&t&255)}function ne(t,e){var n,r=e;hn>y-r?(n=t,dn|=n<>>y-hn,hn+=r-y):(dn|=t<=n;n++)if(r=i,i=t[2*(n+1)+1],!(++oo){do re(r,tn);while(0!==--o)}else 0!==r?(r!=s&&(re(r,tn),o--),re(m,tn),ne(o-3,2)):10>=o?(re(w,tn),ne(o-3,3)):(re(g,tn),ne(o-11,7));o=0,s=r,0===i?(a=138,u=3):r==i?(a=6,u=3):(a=7,u=4)}}function ie(e,n,r){var s;for(ne(e-257,5),ne(n-1,5),ne(r-4,4),s=0;r>s;s++)ne(tn[2*t.bl_order[s]+1],3);se($e,e-1),se(Ze,n-1)}function oe(){16==hn?(p(dn),dn=0,hn=0):hn>=8&&(d(255&dn),dn>>>=8,hn-=8)}function ae(){ne(Q<<1,3),re(h,e.static_ltree),oe(),9>1+fn+10-hn&&(ne(Q<<1,3),re(h,e.static_ltree),oe()),fn=7}function ue(e,n){var r,s,i;if(en.pending_buf[cn+2*un]=e>>>8&255,en.pending_buf[cn+2*un+1]=255&e,en.pending_buf[on+un]=255&n,un++,0===e?$e[2*n]++:(ln++,e--,$e[2*(t._length_code[n]+l+1)]++,Ze[2*t.d_code(e)]++),0===(8191&un)&&Xe>2){for(r=8*un,s=Me-Ue,i=0;a>i;i++)r+=Ze[2*i]*(5+t.extra_dbits[i]);if(r>>>=3,lna);re(h,e),fn=e[2*h+1]}function le(){hn>8?p(dn):hn>0&&d(255&dn),dn=0,hn=0}function fe(t,e,n){le(),fn=8,n&&(p(e),p(~e)),en.pending_buf.set(ze.subarray(t,t+e),en.pending),en.pending+=e}function de(t,e,n){ne((K<<1)+(n?1:0),3),fe(t,e,!0)}function he(t,n,r){var i,o,a=0;Xe>0?(nn.build_tree(en),rn.build_tree(en),a=c(),i=en.opt_len+3+7>>>3,o=en.static_len+3+7>>>3,i>=o&&(i=o)):i=o=n+5,i>=n+4&&-1!=t?de(t,n,r):o==i?(ne((Q<<1)+(r?1:0),3),ce(e.static_ltree,e.static_dtree)):(ne(($<<1)+(r?1:0),3),ie(nn.max_code+1,rn.max_code+1,a+1),ce($e,Ze)),s(),r&&le()}function pe(t){he(Ue>=0?Ue:-1,Me-Ue,t),Ue=Me,qe.flush_pending()}function me(){var t,e,n,r;do{if(r=Te-Ge-Me,0===r&&0===Me&&0===Ge)r=Ce;else if(-1==r)r--;else if(Me>=Ce+Ce-ee){ze.set(ze.subarray(Ce,Ce+Ce),0),He-=Ce,Me-=Ce,Ue-=Ce,t=Pe,n=t;do e=65535&Be[--n],Be[n]=e>=Ce?e-Ce:0;while(0!==--t);t=Ce,n=t;do e=65535&Ie[--n],Ie[n]=e>=Ce?e-Ce:0;while(0!==--t);r+=Ce}if(0===qe.avail_in)return;t=qe.read_buf(ze,Me+Ge,r),Ge+=t,Ge>=Z&&(Oe=255&ze[Me],Oe=(Oe<Ge&&0!==qe.avail_in)}function we(t){var e,n=65535;for(n>ke-5&&(n=ke-5);;){if(1>=Ge){if(me(),0===Ge&&t==k)return j;if(0===Ge)break}if(Me+=Ge,Ge=0,e=Ue+n,(0===Me||Me>=e)&&(Ge=Me-e,Me=e,pe(!1),0===qe.avail_out))return j;if(Me-Ue>=Ce-ee&&(pe(!1),0===qe.avail_out))return j}return pe(t==C),0===qe.avail_out?t==C?H:j:t==C?G:M}function ge(t){var e,n,r=Ve,s=Me,i=We,o=Me>Ce-ee?Me-(Ce-ee):0,a=Qe,u=Ee,c=Me+te,l=ze[s+i-1],f=ze[s+i];We>=Ke&&(r>>=2),a>Ge&&(a=Ge);do if(e=t,ze[e+i]==f&&ze[e+i-1]==l&&ze[e]==ze[s]&&ze[++e]==ze[s+1]){s+=2,e++;do;while(ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&ze[++s]==ze[++e]&&c>s);if(n=te-(c-s),s=c-te,n>i){if(He=t,i=n,n>=a)break;l=ze[s+i-1],f=ze[s+i]}}while((t=65535&Ie[t&u])>o&&0!==--r);return Ge>=i?i:Ge}function ye(t){for(var e,n=0;;){if(ee>Ge){if(me(),ee>Ge&&t==k)return j;if(0===Ge)break}if(Ge>=Z&&(Oe=(Oe<=(Me-n&65535)&&Ye!=q&&(Ne=ge(n)),Ne>=Z)if(e=ue(Me-He,Ne-Z),Ge-=Ne,Je>=Ne&&Ge>=Z){Ne--;do Me++,Oe=(Oe<Ge){if(me(),ee>Ge&&t==k)return j;if(0===Ge)break}if(Ge>=Z&&(Oe=(Oe<We&&Ce-ee>=(Me-r&65535)&&(Ye!=q&&(Ne=ge(r)),5>=Ne&&(Ye==b||Ne==Z&&Me-He>4096)&&(Ne=Z-1)),We>=Z&&We>=Ne){n=Me+Ge-Z,e=ue(Me-1-Le,We-Z),Ge-=We-1,We-=2;do++Me<=n&&(Oe=(Oe<s||s>P||r!=Y||9>n||n>15||0>e||e>9||0>i||i>q?T:(t.dstate=en,Se=n,Ce=1<e||e>9||0>n||n>q?T:(N[Xe].func!=N[e].func&&0!==t.total_in&&(r=t.deflate(_)),Xe!=e&&(Xe=e,Je=N[Xe].max_lazy,Ke=N[Xe].good_length,Qe=N[Xe].nice_length,Ve=N[Xe].max_chain),Ye=n,r)},en.deflateSetDictionary=function(t,e,n){var r,s=n,i=0;if(!e||xe!=V)return T;if(Z>s)return S;for(s>Ce-ee&&(s=Ce-ee,i=n-s),ze.set(e.subarray(i,i+s),0),Me=s,Ue=s,Oe=255&ze[0],Oe=(Oe<=r;r++)Oe=(Oe<C||0>e)return T;if(!t.next_out||!t.next_in&&0!==t.avail_in||xe==X&&e!=C)return t.msg=L[z-T],T;if(0===t.avail_out)return t.msg=L[z-B],B;if(qe=t,i=Ae,Ae=e,xe==V&&(r=Y+(Se-8<<4)<<8,s=(Xe-1&255)>>1,s>3&&(s=3),r|=s<<6,0!==Me&&(r|=W),r+=31-r%31,xe=J,O(r)),0!==en.pending){if(qe.flush_pending(),0===qe.avail_out)return Ae=-1,S}else if(0===qe.avail_in&&i>=e&&e!=C)return qe.msg=L[z-B],B;if(xe==X&&0!==qe.avail_in)return t.msg=L[z-B],B;if(0!==qe.avail_in||0!==Ge||e!=k&&xe!=X){switch(o=-1,N[Xe].func){case F:o=we(e);break;case D:o=ye(e);break;case U:o=ve(e)}if((o==H||o==G)&&(xe=X),o==j||o==H)return 0===qe.avail_out&&(Ae=-1),S;if(o==M){if(e==_)ae();else if(de(0,0,!1),e==A)for(n=0;Pe>n;n++)Be[n]=0;if(qe.flush_pending(),0===qe.avail_out)return Ae=-1,S}}return e!=C?S:E}}function i(){var t=this;t.next_in_index=0,t.next_out_index=0,t.avail_in=0,t.total_in=0,t.avail_out=0,t.total_out=0}var o=15,a=30,u=19,c=29,l=256,f=l+1+c,d=2*f+1,h=256,p=7,m=16,w=17,g=18,y=16,v=-1,b=1,q=2,x=0,k=0,_=1,A=3,C=4,S=0,E=1,z=2,T=-2,I=-3,B=-5,O=[0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,0,0,16,17,18,18,19,19,20,20,20,20,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29];t._length_code=[0,1,2,3,4,5,6,7,8,8,9,9,10,10,11,11,12,12,12,12,13,13,13,13,14,14,14,14,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28],t.base_length=[0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224,0],t.base_dist=[0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576],t.d_code=function(t){return 256>t?O[t]:O[256+(t>>>7)]},t.extra_lbits=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],t.extra_dbits=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],t.extra_blbits=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],t.bl_order=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],e.static_ltree=[12,8,140,8,76,8,204,8,44,8,172,8,108,8,236,8,28,8,156,8,92,8,220,8,60,8,188,8,124,8,252,8,2,8,130,8,66,8,194,8,34,8,162,8,98,8,226,8,18,8,146,8,82,8,210,8,50,8,178,8,114,8,242,8,10,8,138,8,74,8,202,8,42,8,170,8,106,8,234,8,26,8,154,8,90,8,218,8,58,8,186,8,122,8,250,8,6,8,134,8,70,8,198,8,38,8,166,8,102,8,230,8,22,8,150,8,86,8,214,8,54,8,182,8,118,8,246,8,14,8,142,8,78,8,206,8,46,8,174,8,110,8,238,8,30,8,158,8,94,8,222,8,62,8,190,8,126,8,254,8,1,8,129,8,65,8,193,8,33,8,161,8,97,8,225,8,17,8,145,8,81,8,209,8,49,8,177,8,113,8,241,8,9,8,137,8,73,8,201,8,41,8,169,8,105,8,233,8,25,8,153,8,89,8,217,8,57,8,185,8,121,8,249,8,5,8,133,8,69,8,197,8,37,8,165,8,101,8,229,8,21,8,149,8,85,8,213,8,53,8,181,8,117,8,245,8,13,8,141,8,77,8,205,8,45,8,173,8,109,8,237,8,29,8,157,8,93,8,221,8,61,8,189,8,125,8,253,8,19,9,275,9,147,9,403,9,83,9,339,9,211,9,467,9,51,9,307,9,179,9,435,9,115,9,371,9,243,9,499,9,11,9,267,9,139,9,395,9,75,9,331,9,203,9,459,9,43,9,299,9,171,9,427,9,107,9,363,9,235,9,491,9,27,9,283,9,155,9,411,9,91,9,347,9,219,9,475,9,59,9,315,9,187,9,443,9,123,9,379,9,251,9,507,9,7,9,263,9,135,9,391,9,71,9,327,9,199,9,455,9,39,9,295,9,167,9,423,9,103,9,359,9,231,9,487,9,23,9,279,9,151,9,407,9,87,9,343,9,215,9,471,9,55,9,311,9,183,9,439,9,119,9,375,9,247,9,503,9,15,9,271,9,143,9,399,9,79,9,335,9,207,9,463,9,47,9,303,9,175,9,431,9,111,9,367,9,239,9,495,9,31,9,287,9,159,9,415,9,95,9,351,9,223,9,479,9,63,9,319,9,191,9,447,9,127,9,383,9,255,9,511,9,0,7,64,7,32,7,96,7,16,7,80,7,48,7,112,7,8,7,72,7,40,7,104,7,24,7,88,7,56,7,120,7,4,7,68,7,36,7,100,7,20,7,84,7,52,7,116,7,3,8,131,8,67,8,195,8,35,8,163,8,99,8,227,8],e.static_dtree=[0,5,16,5,8,5,24,5,4,5,20,5,12,5,28,5,2,5,18,5,10,5,26,5,6,5,22,5,14,5,30,5,1,5,17,5,9,5,25,5,5,5,21,5,13,5,29,5,3,5,19,5,11,5,27,5,7,5,23,5],e.static_l_desc=new e(e.static_ltree,t.extra_lbits,l+1,f,o),e.static_d_desc=new e(e.static_dtree,t.extra_dbits,0,a,o),e.static_bl_desc=new e(null,t.extra_blbits,0,u,p);var P=9,R=8,F=0,D=1,U=2,N=[new n(0,0,0,0,F),new n(4,4,8,4,D),new n(4,5,16,8,D),new n(4,6,32,32,D),new n(4,4,16,16,U),new n(8,16,32,32,U),new n(8,16,128,128,U),new n(8,32,128,256,U),new n(32,128,258,1024,U),new n(32,258,258,4096,U)],L=["need dictionary","stream end","","","stream error","data error","","buffer error","",""],j=0,M=1,H=2,G=3,W=32,V=42,J=113,X=666,Y=8,K=0,Q=1,$=2,Z=3,te=258,ee=te+Z+1;return i.prototype={deflateInit:function(t,e){var n=this;return n.dstate=new s,e||(e=o),n.dstate.deflateInit(n,t,e)},deflate:function(t){var e=this;return e.dstate?e.dstate.deflate(e,t):T},deflateEnd:function(){var t=this;if(!t.dstate)return T;var e=t.dstate.deflateEnd();return t.dstate=null,e},deflateParams:function(t,e){var n=this;return n.dstate?n.dstate.deflateParams(n,t,e):T},deflateSetDictionary:function(t,e){var n=this;return n.dstate?n.dstate.deflateSetDictionary(n,t,e):T},read_buf:function(t,e,n){var r=this,s=r.avail_in;return s>n&&(s=n),0===s?0:(r.avail_in-=s,t.set(r.next_in.subarray(r.next_in_index,r.next_in_index+s),e),r.next_in_index+=s,r.total_in+=s,s)},flush_pending:function(){var t=this,e=t.dstate.pending;e>t.avail_out&&(e=t.avail_out),0!==e&&(t.next_out.set(t.dstate.pending_buf.subarray(t.dstate.pending_out,t.dstate.pending_out+e),t.next_out_index),t.next_out_index+=e,t.dstate.pending_out+=e,t.total_out+=e,t.avail_out-=e,t.dstate.pending-=e,0===t.dstate.pending&&(t.dstate.pending_out=0))}},function(t){var e=this,n=new i,r=512,s=k,o=new Uint8Array(r);"undefined"==typeof t&&(t=v),n.deflateInit(t),n.next_out=o,e.append=function(t,e){var i,a,u=[],c=0,l=0,f=0;if(t.length){n.next_in_index=0,n.next_in=t,n.avail_in=t.length;do{if(n.next_out_index=0,n.avail_out=r,i=n.deflate(s),i!=S)throw"deflating: "+n.msg;n.next_out_index&&u.push(n.next_out_index==r?new Uint8Array(o):new Uint8Array(o.subarray(0,n.next_out_index))),f+=n.next_out_index,e&&n.next_in_index>0&&n.next_in_index!=c&&(e(n.next_in_index),c=n.next_in_index)}while(n.avail_in>0||0===n.avail_out);return a=new Uint8Array(f),u.forEach(function(t){a.set(t,l),l+=t.length}),a}},e.flush=function(){var t,e,s=[],i=0,a=0;do{if(n.next_out_index=0,n.avail_out=r,t=n.deflate(C),t!=E&&t!=S)throw"deflating: "+n.msg;r-n.avail_out>0&&s.push(new Uint8Array(o.subarray(0,n.next_out_index))),a+=n.next_out_index}while(n.avail_in>0||0===n.avail_out);return n.deflateEnd(),e=new Uint8Array(a),s.forEach(function(t){e.set(t,i),i+=t.length}),e}}}(this);!function(t){var e;e=function(){function e(t){var e,n,r,s,i,o,a,u,c,l,f,d,h,p,m;for(this.data=t,this.pos=8,this.palette=[],this.imgData=[],this.transparency={},this.animation=null,this.text={},o=null;;){switch(e=this.readUInt32(),l=function(){var t,e;for(e=[],a=t=0;4>t;a=++t)e.push(String.fromCharCode(this.data[this.pos++]));return e}.call(this).join("")){case"IHDR":this.width=this.readUInt32(),this.height=this.readUInt32(),this.bits=this.data[this.pos++],this.colorType=this.data[this.pos++],this.compressionMethod=this.data[this.pos++],this.filterMethod=this.data[this.pos++],this.interlaceMethod=this.data[this.pos++];break;case"acTL":this.animation={numFrames:this.readUInt32(),numPlays:this.readUInt32()||1/0,frames:[]};break;case"PLTE":this.palette=this.read(e);break;case"fcTL":o&&this.animation.frames.push(o),this.pos+=4,o={width:this.readUInt32(),height:this.readUInt32(),xOffset:this.readUInt32(),yOffset:this.readUInt32()},i=this.readUInt16(),s=this.readUInt16()||100,o.delay=1e3*i/s,o.disposeOp=this.data[this.pos++],o.blendOp=this.data[this.pos++],o.data=[];break;case"IDAT":case"fdAT":for("fdAT"===l&&(this.pos+=4,e-=4),t=(null!=o?o.data:void 0)||this.imgData,a=h=0;e>=0?e>h:h>e;a=e>=0?++h:--h)t.push(this.data[this.pos++]);break;case"tRNS":switch(this.transparency={},this.colorType){case 3:if(r=this.palette.length/3,this.transparency.indexed=this.read(e),this.transparency.indexed.length>r)throw new Error("More transparent colors than palette size");if(f=r-this.transparency.indexed.length,f>0)for(a=p=0;f>=0?f>p:p>f;a=f>=0?++p:--p)this.transparency.indexed.push(255);break;case 0:this.transparency.grayscale=this.read(e)[0];break;case 2:this.transparency.rgb=this.read(e)}break;case"tEXt":d=this.read(e),u=d.indexOf(0),c=String.fromCharCode.apply(String,d.slice(0,u)),this.text[c]=String.fromCharCode.apply(String,d.slice(u+1));break;case"IEND":return o&&this.animation.frames.push(o),this.colors=function(){switch(this.colorType){case 0:case 3:case 4:return 1;case 2:case 6:return 3}}.call(this),this.hasAlphaChannel=4===(m=this.colorType)||6===m,n=this.colors+(this.hasAlphaChannel?1:0),this.pixelBitlength=this.bits*n,this.colorSpace=function(){switch(this.colors){case 1:return"DeviceGray";case 3:return"DeviceRGB"}}.call(this),void(this.imgData=new Uint8Array(this.imgData));default:this.pos+=e}if(this.pos+=4,this.pos>this.data.length)throw new Error("Incomplete or corrupt PNG file")}}var n,r,s,i,a,u,c,l;e.load=function(t,n,r){var s;return"function"==typeof n&&(r=n),s=new XMLHttpRequest,s.open("GET",t,!0),s.responseType="arraybuffer",s.onload=function(){var t,i;return t=new Uint8Array(s.response||s.mozResponseArrayBuffer),i=new e(t),"function"==typeof(null!=n?n.getContext:void 0)&&i.render(n),"function"==typeof r?r(i):void 0},s.send(null)},i=0,s=1,a=2,r=0,n=1,e.prototype.read=function(t){var e,n,r;for(r=[],e=n=0;t>=0?t>n:n>t;e=t>=0?++n:--n)r.push(this.data[this.pos++]);return r},e.prototype.readUInt32=function(){var t,e,n,r;return t=this.data[this.pos++]<<24,e=this.data[this.pos++]<<16,n=this.data[this.pos++]<<8,r=this.data[this.pos++],t|e|n|r},e.prototype.readUInt16=function(){var t,e;return t=this.data[this.pos++]<<8,e=this.data[this.pos++],t|e},e.prototype.decodePixels=function(t){var e,n,r,s,i,a,u,c,l,f,d,h,p,m,w,g,y,v,b,q,x,k,_;if(null==t&&(t=this.imgData),0===t.length)return new Uint8Array(0);for(t=new o(t),t=t.getBytes(),h=this.pixelBitlength/8,g=h*this.width,p=new Uint8Array(g*this.height),a=t.length,w=0,m=0,n=0;a>m;){switch(t[m++]){case 0:for(s=b=0;g>b;s=b+=1)p[n++]=t[m++];break;case 1:for(s=q=0;g>q;s=q+=1)e=t[m++],i=h>s?0:p[n-h],p[n++]=(e+i)%256;break;case 2:for(s=x=0;g>x;s=x+=1)e=t[m++],r=(s-s%h)/h,y=w&&p[(w-1)*g+r*h+s%h],p[n++]=(y+e)%256;break;case 3:for(s=k=0;g>k;s=k+=1)e=t[m++],r=(s-s%h)/h,i=h>s?0:p[n-h],y=w&&p[(w-1)*g+r*h+s%h],p[n++]=(e+Math.floor((i+y)/2))%256;break;case 4:for(s=_=0;g>_;s=_+=1)e=t[m++],r=(s-s%h)/h,i=h>s?0:p[n-h],0===w?y=v=0:(y=p[(w-1)*g+r*h+s%h],v=r&&p[(w-1)*g+(r-1)*h+s%h]),u=i+y-v,c=Math.abs(u-i),f=Math.abs(u-y),d=Math.abs(u-v),l=f>=c&&d>=c?i:d>=f?y:v,p[n++]=(e+l)%256;break;default:throw new Error("Invalid filter algorithm: "+t[m-1])}w++}return p},e.prototype.decodePalette=function(){var t,e,n,r,s,i,o,a,u,c;for(r=this.palette,o=this.transparency.indexed||[],i=new Uint8Array((o.length||0)+r.length),s=0,n=r.length,t=0,e=a=0,u=r.length;u>a;e=a+=3)i[s++]=r[e],i[s++]=r[e+1],i[s++]=r[e+2],i[s++]=null!=(c=o[t++])?c:255;return i},e.prototype.copyToImageData=function(t,e){var n,r,s,i,o,a,u,c,l,f,d;if(r=this.colors,l=null,n=this.hasAlphaChannel,this.palette.length&&(l=null!=(d=this._decodedPalette)?d:this._decodedPalette=this.decodePalette(),r=4,n=!0),s=t.data||t,c=s.length,o=l||e,i=a=0,1===r)for(;c>i;)u=l?4*e[i/4]:a,f=o[u++],s[i++]=f,s[i++]=f,s[i++]=f,s[i++]=n?o[u++]:255,a=u;else for(;c>i;)u=l?4*e[i/4]:a,s[i++]=o[u++],s[i++]=o[u++],s[i++]=o[u++],s[i++]=n?o[u++]:255,a=u},e.prototype.decode=function(){var t;return t=new Uint8Array(this.width*this.height*4),this.copyToImageData(t,this.decodePixels()),t};try{c=t.document.createElement("canvas"),l=c.getContext("2d")}catch(f){return-1}return u=function(t){var e;return l.width=t.width,l.height=t.height,l.clearRect(0,0,t.width,t.height),l.putImageData(t,0,0),e=new Image,e.src=c.toDataURL(),e},e.prototype.decodeFrames=function(t){var e,n,r,s,i,o,a,c;if(this.animation){for(a=this.animation.frames,c=[],n=i=0,o=a.length;o>i;n=++i)e=a[n],r=t.createImageData(e.width,e.height),s=this.decodePixels(new Uint8Array(e.data)),this.copyToImageData(r,s),e.imageData=r,c.push(e.image=u(r));return c}},e.prototype.renderFrame=function(t,e){var n,i,o;return i=this.animation.frames,n=i[e],o=i[e-1],0===e&&t.clearRect(0,0,this.width,this.height),(null!=o?o.disposeOp:void 0)===s?t.clearRect(o.xOffset,o.yOffset,o.width,o.height):(null!=o?o.disposeOp:void 0)===a&&t.putImageData(o.imageData,o.xOffset,o.yOffset),n.blendOp===r&&t.clearRect(n.xOffset,n.yOffset,n.width,n.height),t.drawImage(n.image,n.xOffset,n.yOffset)},e.prototype.animate=function(t){var e,n,r,s,i,o,a=this;return n=0,o=this.animation,s=o.numFrames,r=o.frames,i=o.numPlays,(e=function(){var o,u;return o=n++%s,u=r[o],a.renderFrame(t,o),s>1&&i>n/s?a.animation._timeout=setTimeout(e,u.delay):void 0 })()},e.prototype.stopAnimation=function(){var t;return clearTimeout(null!=(t=this.animation)?t._timeout:void 0)},e.prototype.render=function(t){var e,n;return t._png&&t._png.stopAnimation(),t._png=this,t.width=this.width,t.height=this.height,e=t.getContext("2d"),this.animation?(this.decodeFrames(e),this.animate(e)):(n=e.createImageData(this.width,this.height),this.copyToImageData(n,this.decodePixels()),e.putImageData(n,0,0))},e}(),t.PNG=e}("undefined"!=typeof window&&window||this);var i=function(){function t(){this.pos=0,this.bufferLength=0,this.eof=!1,this.buffer=null}return t.prototype={ensureBuffer:function(t){var e=this.buffer,n=e?e.byteLength:0;if(n>t)return e;for(var r=512;t>r;)r<<=1;for(var s=new Uint8Array(r),i=0;n>i;++i)s[i]=e[i];return this.buffer=s},getByte:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return this.buffer[this.pos++]},getBytes:function(t){var e=this.pos;if(t){this.ensureBuffer(e+t);for(var n=e+t;!this.eof&&this.bufferLengthr&&(n=r)}else{for(;!this.eof;)this.readBlock();var n=this.bufferLength}return this.pos=n,this.buffer.subarray(e,n)},lookChar:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return String.fromCharCode(this.buffer[this.pos])},getChar:function(){for(var t=this.pos;this.bufferLength<=t;){if(this.eof)return null;this.readBlock()}return String.fromCharCode(this.buffer[this.pos++])},makeSubStream:function(t,e,n){for(var r=t+e;this.bufferLength<=r&&!this.eof;)this.readBlock();return new Stream(this.buffer,t,e,n)},skip:function(t){t||(t=1),this.pos+=t},reset:function(){this.pos=0}},t}(),o=function(){function t(t){throw new Error(t)}function e(e){var n=0,r=e[n++],s=e[n++];(-1==r||-1==s)&&t("Invalid header in flate stream"),8!=(15&r)&&t("Unknown compression method in flate stream"),((r<<8)+s)%31!=0&&t("Bad FCHECK in flate stream"),32&s&&t("FDICT bit set in flate stream"),this.bytes=e,this.bytesPos=n,this.codeSize=0,this.codeBuf=0,i.call(this)}if("undefined"==typeof Uint32Array)return void 0;var n=new Uint32Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),r=new Uint32Array([3,4,5,6,7,8,9,10,65547,65549,65551,65553,131091,131095,131099,131103,196643,196651,196659,196667,262211,262227,262243,262259,327811,327843,327875,327907,258,258,258]),s=new Uint32Array([1,2,3,4,65541,65543,131081,131085,196625,196633,262177,262193,327745,327777,393345,393409,459009,459137,524801,525057,590849,591361,657409,658433,724993,727041,794625,798721,868353,876545]),o=[new Uint32Array([459008,524368,524304,524568,459024,524400,524336,590016,459016,524384,524320,589984,524288,524416,524352,590048,459012,524376,524312,589968,459028,524408,524344,590032,459020,524392,524328,59e4,524296,524424,524360,590064,459010,524372,524308,524572,459026,524404,524340,590024,459018,524388,524324,589992,524292,524420,524356,590056,459014,524380,524316,589976,459030,524412,524348,590040,459022,524396,524332,590008,524300,524428,524364,590072,459009,524370,524306,524570,459025,524402,524338,590020,459017,524386,524322,589988,524290,524418,524354,590052,459013,524378,524314,589972,459029,524410,524346,590036,459021,524394,524330,590004,524298,524426,524362,590068,459011,524374,524310,524574,459027,524406,524342,590028,459019,524390,524326,589996,524294,524422,524358,590060,459015,524382,524318,589980,459031,524414,524350,590044,459023,524398,524334,590012,524302,524430,524366,590076,459008,524369,524305,524569,459024,524401,524337,590018,459016,524385,524321,589986,524289,524417,524353,590050,459012,524377,524313,589970,459028,524409,524345,590034,459020,524393,524329,590002,524297,524425,524361,590066,459010,524373,524309,524573,459026,524405,524341,590026,459018,524389,524325,589994,524293,524421,524357,590058,459014,524381,524317,589978,459030,524413,524349,590042,459022,524397,524333,590010,524301,524429,524365,590074,459009,524371,524307,524571,459025,524403,524339,590022,459017,524387,524323,589990,524291,524419,524355,590054,459013,524379,524315,589974,459029,524411,524347,590038,459021,524395,524331,590006,524299,524427,524363,590070,459011,524375,524311,524575,459027,524407,524343,590030,459019,524391,524327,589998,524295,524423,524359,590062,459015,524383,524319,589982,459031,524415,524351,590046,459023,524399,524335,590014,524303,524431,524367,590078,459008,524368,524304,524568,459024,524400,524336,590017,459016,524384,524320,589985,524288,524416,524352,590049,459012,524376,524312,589969,459028,524408,524344,590033,459020,524392,524328,590001,524296,524424,524360,590065,459010,524372,524308,524572,459026,524404,524340,590025,459018,524388,524324,589993,524292,524420,524356,590057,459014,524380,524316,589977,459030,524412,524348,590041,459022,524396,524332,590009,524300,524428,524364,590073,459009,524370,524306,524570,459025,524402,524338,590021,459017,524386,524322,589989,524290,524418,524354,590053,459013,524378,524314,589973,459029,524410,524346,590037,459021,524394,524330,590005,524298,524426,524362,590069,459011,524374,524310,524574,459027,524406,524342,590029,459019,524390,524326,589997,524294,524422,524358,590061,459015,524382,524318,589981,459031,524414,524350,590045,459023,524398,524334,590013,524302,524430,524366,590077,459008,524369,524305,524569,459024,524401,524337,590019,459016,524385,524321,589987,524289,524417,524353,590051,459012,524377,524313,589971,459028,524409,524345,590035,459020,524393,524329,590003,524297,524425,524361,590067,459010,524373,524309,524573,459026,524405,524341,590027,459018,524389,524325,589995,524293,524421,524357,590059,459014,524381,524317,589979,459030,524413,524349,590043,459022,524397,524333,590011,524301,524429,524365,590075,459009,524371,524307,524571,459025,524403,524339,590023,459017,524387,524323,589991,524291,524419,524355,590055,459013,524379,524315,589975,459029,524411,524347,590039,459021,524395,524331,590007,524299,524427,524363,590071,459011,524375,524311,524575,459027,524407,524343,590031,459019,524391,524327,589999,524295,524423,524359,590063,459015,524383,524319,589983,459031,524415,524351,590047,459023,524399,524335,590015,524303,524431,524367,590079]),9],a=[new Uint32Array([327680,327696,327688,327704,327684,327700,327692,327708,327682,327698,327690,327706,327686,327702,327694,0,327681,327697,327689,327705,327685,327701,327693,327709,327683,327699,327691,327707,327687,327703,327695,0]),5];return e.prototype=Object.create(i.prototype),e.prototype.getBits=function(e){for(var n,r=this.codeSize,s=this.codeBuf,i=this.bytes,o=this.bytesPos;e>r;)"undefined"==typeof(n=i[o++])&&t("Bad encoding in flate stream"),s|=n<>e,this.codeSize=r-=e,this.bytesPos=o,n},e.prototype.getCode=function(e){for(var n=e[0],r=e[1],s=this.codeSize,i=this.codeBuf,o=this.bytes,a=this.bytesPos;r>s;){var u;"undefined"==typeof(u=o[a++])&&t("Bad encoding in flate stream"),i|=u<>16,f=65535&c;return(0==s||l>s||0==l)&&t("Bad encoding in flate stream"),this.codeBuf=i>>l,this.codeSize=s-l,this.bytesPos=a,f},e.prototype.generateHuffmanTable=function(t){for(var e=t.length,n=0,r=0;e>r;++r)t[r]>n&&(n=t[r]);for(var s=1<=o;++o,a<<=1,u<<=1)for(var c=0;e>c;++c)if(t[c]==o){for(var l=0,f=a,r=0;o>r;++r)l=l<<1|1&f,f>>=1;for(var r=l;s>r;r+=u)i[r]=o<<16|c;++a}return[i,n]},e.prototype.readBlock=function(){function e(t,e,n,r,s){for(var i=t.getBits(n)+r;i-->0;)e[k++]=s}var i=this.getBits(3);if(1&i&&(this.eof=!0),i>>=1,0==i){var u,c=this.bytes,l=this.bytesPos;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream");var f=u;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream"),f|=u<<8,"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream");var d=u;"undefined"==typeof(u=c[l++])&&t("Bad block header in flate stream"),d|=u<<8,d!=(65535&~f)&&t("Bad uncompressed block length in flate stream"),this.codeBuf=0,this.codeSize=0;var h=this.bufferLength,p=this.ensureBuffer(h+f),m=h+f;this.bufferLength=m;for(var w=h;m>w;++w){if("undefined"==typeof(u=c[l++])){this.eof=!0;break}p[w]=u}return void(this.bytesPos=l)}var g,y;if(1==i)g=o,y=a;else if(2==i){for(var v=this.getBits(5)+257,b=this.getBits(5)+1,q=this.getBits(4)+4,x=Array(n.length),k=0;q>k;)x[n[k++]]=this.getBits(3);for(var _=this.generateHuffmanTable(x),A=0,k=0,C=v+b,S=new Array(C);C>k;){var E=this.getCode(_);16==E?e(this,S,2,3,A):17==E?e(this,S,3,3,A=0):18==E?e(this,S,7,11,A=0):S[k++]=A=E}g=this.generateHuffmanTable(S.slice(0,v)),y=this.generateHuffmanTable(S.slice(v,C))}else t("Unknown block type in flate stream");for(var p=this.buffer,z=p?p.length:0,T=this.bufferLength;;){var I=this.getCode(g);if(256>I)T+1>=z&&(p=this.ensureBuffer(T+1),z=p.length),p[T++]=I;else{if(256==I)return void(this.bufferLength=T);I-=257,I=r[I];var B=I>>16;B>0&&(B=this.getBits(B));var A=(65535&I)+B;I=this.getCode(y),I=s[I],B=I>>16,B>0&&(B=this.getBits(B));var O=(65535&I)+B;T+A>=z&&(p=this.ensureBuffer(T+A),z=p.length);for(var P=0;A>P;++P,++T)p[T]=p[T-O]}}},e}();!function(t){var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";"undefined"==typeof t.btoa&&(t.btoa=function(t){var n,r,s,i,o,a,u,c,l=0,f=0,d="",h=[];if(!t)return t;do n=t.charCodeAt(l++),r=t.charCodeAt(l++),s=t.charCodeAt(l++),c=n<<16|r<<8|s,i=c>>18&63,o=c>>12&63,a=c>>6&63,u=63&c,h[f++]=e.charAt(i)+e.charAt(o)+e.charAt(a)+e.charAt(u);while(l>16&255,r=c>>8&255,s=255&c,h[f++]=64==a?String.fromCharCode(n):64==u?String.fromCharCode(n,r):String.fromCharCode(n,r,s);while(l>>0,r=new Array(n),s=arguments.length>1?arguments[1]:void 0,i=0;n>i;i++)i in e&&(r[i]=t.call(s,e[i],i,e));return r}),Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),Array.prototype.forEach||(Array.prototype.forEach=function(t,e){"use strict";if(void 0===this||null===this||"function"!=typeof t)throw new TypeError;for(var n=Object(this),r=n.length>>>0,s=0;r>s;s++)s in n&&t.call(e,n[s],s,n)}),Object.keys||(Object.keys=function(){"use strict";var t=Object.prototype.hasOwnProperty,e=!{toString:null}.propertyIsEnumerable("toString"),n=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],r=n.length;return function(s){if("object"!=typeof s&&("function"!=typeof s||null===s))throw new TypeError;var i,o,a=[];for(i in s)t.call(s,i)&&a.push(i);if(e)for(o=0;r>o;o++)t.call(s,n[o])&&a.push(n[o]);return a}}()),String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),String.prototype.trimLeft||(String.prototype.trimLeft=function(){return this.replace(/^\s+/g,"")}),String.prototype.trimRight||(String.prototype.trimRight=function(){return this.replace(/\s+$/g,"")})}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this)}({},function(){return this}()); //! moment.js -//! version : 2.10.3 +//! version : 2.10.6 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors //! license : MIT //! momentjs.com -!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Dc.apply(null,arguments)}function b(a){Dc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c0)for(c in Fc)d=Fc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(+b._d),Gc===!1&&(Gc=!0,a.updateOffset(this),Gc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function q(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&p(a[d])!==p(b[d]))&&g++;return g+f}function r(){}function s(a){return a?a.toLowerCase().replace("_","-"):a}function t(a){for(var b,c,d,e,f=0;f0;){if(d=u(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&q(e,c,!0)>=b-1)break;b--}f++}return null}function u(a){var b=null;if(!Hc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ec._abbr,require("./locale/"+a),v(b)}catch(c){}return Hc[a]}function v(a,b){var c;return a&&(c="undefined"==typeof b?x(a):w(a,b),c&&(Ec=c)),Ec._abbr}function w(a,b){return null!==b?(b.abbr=a,Hc[a]||(Hc[a]=new r),Hc[a].set(b),v(a),Hc[a]):(delete Hc[a],null)}function x(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ec;if(!c(a)){if(b=u(a))return b;a=[a]}return t(a)}function y(a,b){var c=a.toLowerCase();Ic[c]=Ic[c+"s"]=Ic[b]=a}function z(a){return"string"==typeof a?Ic[a]||Ic[a.toLowerCase()]:void 0}function A(a){var b,c,d={};for(c in a)f(a,c)&&(b=z(c),b&&(d[b]=a[c]));return d}function B(b,c){return function(d){return null!=d?(D(this,b,d),a.updateOffset(this,c),this):C(this,b)}}function C(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function D(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function E(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=z(a),"function"==typeof this[a])return this[a](b);return this}function F(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.lengthb;b++)Mc[d[b]]?d[b]=Mc[d[b]]:d[b]=H(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function J(a,b){return a.isValid()?(b=K(b,a.localeData()),Lc[b]||(Lc[b]=I(b)),Lc[b](a)):a.localeData().invalidDate()}function K(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Kc.lastIndex=0;d>=0&&Kc.test(a);)a=a.replace(Kc,c),Kc.lastIndex=0,d-=1;return a}function L(a,b,c){_c[a]="function"==typeof b?b:function(a){return a&&c?c:b}}function M(a,b){return f(_c,a)?_c[a](b._strict,b._locale):new RegExp(N(a))}function N(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function O(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=p(a)}),c=0;cd;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function V(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),R(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function W(b){return null!=b?(V(this,b),a.updateOffset(this,!0),this):C(this,"Month")}function X(){return R(this.year(),this.month())}function Y(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[cd]<0||c[cd]>11?cd:c[dd]<1||c[dd]>R(c[bd],c[cd])?dd:c[ed]<0||c[ed]>24||24===c[ed]&&(0!==c[fd]||0!==c[gd]||0!==c[hd])?ed:c[fd]<0||c[fd]>59?fd:c[gd]<0||c[gd]>59?gd:c[hd]<0||c[hd]>999?hd:-1,j(a)._overflowDayOfYear&&(bd>b||b>dd)&&(b=dd),j(a).overflow=b),a}function Z(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function $(a,b){var c=!0,d=a+"\n"+(new Error).stack;return g(function(){return c&&(Z(d),c=!1),b.apply(this,arguments)},b)}function _(a,b){kd[a]||(Z(b),kd[a]=!0)}function aa(a){var b,c,d=a._i,e=ld.exec(d);if(e){for(j(a).iso=!0,b=0,c=md.length;c>b;b++)if(md[b][1].exec(d)){a._f=md[b][0]+(e[6]||" ");break}for(b=0,c=nd.length;c>b;b++)if(nd[b][1].exec(d)){a._f+=nd[b][0];break}d.match(Yc)&&(a._f+="Z"),ta(a)}else a._isValid=!1}function ba(b){var c=od.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(aa(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ca(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function da(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ea(a){return fa(a)?366:365}function fa(a){return a%4===0&&a%100!==0||a%400===0}function ga(){return fa(this.year())}function ha(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Aa(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ia(a){return ha(a,this._week.dow,this._week.doy).week}function ja(){return this._week.dow}function ka(){return this._week.doy}function la(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function ma(a){var b=ha(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function na(a,b,c,d,e){var f,g,h=da(a,0,1).getUTCDay();return h=0===h?7:h,c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:ea(a-1)+g}}function oa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function pa(a,b,c){return null!=a?a:null!=b?b:c}function qa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ra(a){var b,c,d,e,f=[];if(!a._d){for(d=qa(a),a._w&&null==a._a[dd]&&null==a._a[cd]&&sa(a),a._dayOfYear&&(e=pa(a._a[bd],d[bd]),a._dayOfYear>ea(e)&&(j(a)._overflowDayOfYear=!0),c=da(e,0,a._dayOfYear),a._a[cd]=c.getUTCMonth(),a._a[dd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[ed]&&0===a._a[fd]&&0===a._a[gd]&&0===a._a[hd]&&(a._nextDay=!0,a._a[ed]=0),a._d=(a._useUTC?da:ca).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[ed]=24)}}function sa(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=pa(b.GG,a._a[bd],ha(Aa(),1,4).year),d=pa(b.W,1),e=pa(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=pa(b.gg,a._a[bd],ha(Aa(),f,g).year),d=pa(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=na(c,d,e,g,f),a._a[bd]=h.year,a._dayOfYear=h.dayOfYear}function ta(b){if(b._f===a.ISO_8601)return void aa(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=K(b._f,b._locale).match(Jc)||[],c=0;c0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Mc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),Q(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[ed]<=12&&b._a[ed]>0&&(j(b).bigHour=void 0),b._a[ed]=ua(b._locale,b._a[ed],b._meridiem),ra(b),Y(b)}function ua(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function va(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(0/0));for(e=0;ef)&&(d=f,c=b));g(a,c||b)}function wa(a){if(!a._d){var b=A(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ra(a)}}function xa(a){var b,e=a._i,f=a._f;return a._locale=a._locale||x(a._l),null===e||void 0===f&&""===e?l({nullInput:!0}):("string"==typeof e&&(a._i=e=a._locale.preparse(e)),o(e)?new n(Y(e)):(c(f)?va(a):f?ta(a):d(e)?a._d=e:ya(a),b=new n(Y(a)),b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b))}function ya(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?ba(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ra(b)):"object"==typeof f?wa(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function za(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,xa(f)}function Aa(a,b,c,d){return za(a,b,c,d,!1)}function Ba(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Aa();for(d=b[0],e=1;ea&&(a=-a,c="-"),c+F(~~(a/60),2)+b+F(~~a%60,2)})}function Ha(a){var b=(a||"").match(Yc)||[],c=b[b.length-1]||[],d=(c+"").match(td)||["-",0,0],e=+(60*d[1])+p(d[2]);return"+"===d[0]?e:-e}function Ia(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Aa(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Aa(b).local();return c._isUTC?Aa(b).zone(c._offset||0):Aa(b).local()}function Ja(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Ka(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ha(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ja(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?$a(this,Va(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ja(this)}function La(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Ma(a){return this.utcOffset(0,a)}function Na(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ja(this),"m")),this}function Oa(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ha(this._i)),this}function Pa(a){return a=a?Aa(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Qa(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ra(){if(this._a){var a=this._isUTC?h(this._a):Aa(this._a);return this.isValid()&&q(this._a,a.toArray())>0}return!1}function Sa(){return!this._isUTC}function Ta(){return this._isUTC}function Ua(){return this._isUTC&&0===this._offset}function Va(a,b){var c,d,e,g=a,h=null;return Fa(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=ud.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:p(h[dd])*c,h:p(h[ed])*c,m:p(h[fd])*c,s:p(h[gd])*c,ms:p(h[hd])*c}):(h=vd.exec(a))?(c="-"===h[1]?-1:1,g={y:Wa(h[2],c),M:Wa(h[3],c),d:Wa(h[4],c),h:Wa(h[5],c),m:Wa(h[6],c),s:Wa(h[7],c),w:Wa(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=Ya(Aa(g.from),Aa(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ea(g),Fa(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Wa(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function Xa(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Ya(a,b){var c;return b=Ia(b,a),a.isBefore(b)?c=Xa(a,b):(c=Xa(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function Za(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(_(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Va(c,d),$a(this,e,a),this}}function $a(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&D(b,"Date",C(b,"Date")+g*d),h&&V(b,C(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function _a(a){var b=a||Aa(),c=Ia(b,this).startOf("day"),d=this.diff(c,"days",!0),e=-6>d?"sameElse":-1>d?"lastWeek":0>d?"lastDay":1>d?"sameDay":2>d?"nextDay":7>d?"nextWeek":"sameElse";return this.format(this.localeData().calendar(e,this,Aa(b)))}function ab(){return new n(this)}function bb(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Aa(a),+this>+a):(c=o(a)?+a:+Aa(a),c<+this.clone().startOf(b))}function cb(a,b){var c;return b=z("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Aa(a),+a>+this):(c=o(a)?+a:+Aa(a),+this.clone().endOf(b)a?Math.ceil(a):Math.floor(a)}function gb(a,b,c){var d,e,f=Ia(a,this),g=6e4*(f.utcOffset()-this.utcOffset());return b=z(b),"year"===b||"month"===b||"quarter"===b?(e=hb(this,f),"quarter"===b?e/=3:"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:fb(e)}function hb(a,b){var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),f=a.clone().add(e,"months");return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function ib(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function jb(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=Aa([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Mb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Hb(a,this.localeData()),this.add(a-b,"d")):b}function Nb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Ob(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Pb(a,b){G(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Qb(a,b){return b._meridiemParse}function Rb(a){return"p"===(a+"").toLowerCase().charAt(0)}function Sb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Tb(a){G(0,[a,3],0,"millisecond")}function Ub(){return this._isUTC?"UTC":""}function Vb(){return this._isUTC?"Coordinated Universal Time":""}function Wb(a){return Aa(1e3*a)}function Xb(){return Aa.apply(null,arguments).parseZone()}function Yb(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function Zb(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b}function $b(){return this._invalidDate}function _b(a){return this._ordinal.replace("%d",a)}function ac(a){return a}function bc(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function cc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function dc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function ec(a,b,c,d){var e=x(),f=h().set(d,b);return e[c](f,a)}function fc(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return ec(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=ec(a,f,c,e);return g}function gc(a,b){return fc(a,b,"months",12,"month")}function hc(a,b){return fc(a,b,"monthsShort",12,"month")}function ic(a,b){return fc(a,b,"weekdays",7,"day")}function jc(a,b){return fc(a,b,"weekdaysShort",7,"day")}function kc(a,b){return fc(a,b,"weekdaysMin",7,"day")}function lc(){var a=this._data;return this._milliseconds=Rd(this._milliseconds),this._days=Rd(this._days),this._months=Rd(this._months),a.milliseconds=Rd(a.milliseconds),a.seconds=Rd(a.seconds),a.minutes=Rd(a.minutes),a.hours=Rd(a.hours),a.months=Rd(a.months),a.years=Rd(a.years),this}function mc(a,b,c,d){var e=Va(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function nc(a,b){return mc(this,a,b,1)}function oc(a,b){return mc(this,a,b,-1)}function pc(){var a,b,c,d=this._milliseconds,e=this._days,f=this._months,g=this._data,h=0;return g.milliseconds=d%1e3,a=fb(d/1e3),g.seconds=a%60,b=fb(a/60),g.minutes=b%60,c=fb(b/60),g.hours=c%24,e+=fb(c/24),h=fb(qc(e)),e-=fb(rc(h)),f+=fb(e/30),e%=30,h+=fb(f/12),f%=12,g.days=e,g.months=f,g.years=h,this}function qc(a){return 400*a/146097}function rc(a){return 146097*a/400}function sc(a){var b,c,d=this._milliseconds;if(a=z(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+12*qc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(rc(this._months/12)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function tc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*p(this._months/12)}function uc(a){return function(){return this.as(a)}}function vc(a){return a=z(a),this[a+"s"]()}function wc(a){return function(){return this._data[a]}}function xc(){return fb(this.days()/7)}function yc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function zc(a,b,c){var d=Va(a).abs(),e=fe(d.as("s")),f=fe(d.as("m")),g=fe(d.as("h")),h=fe(d.as("d")),i=fe(d.as("M")),j=fe(d.as("y")),k=e0,k[4]=c,yc.apply(null,k)}function Ac(a,b){return void 0===ge[a]?!1:void 0===b?ge[a]:(ge[a]=b,!0)}function Bc(a){var b=this.localeData(),c=zc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Cc(){var a=he(this.years()),b=he(this.months()),c=he(this.days()),d=he(this.hours()),e=he(this.minutes()),f=he(this.seconds()+this.milliseconds()/1e3),g=this.asSeconds();return g?(0>g?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}var Dc,Ec,Fc=a.momentProperties=[],Gc=!1,Hc={},Ic={},Jc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,Kc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Lc={},Mc={},Nc=/\d/,Oc=/\d\d/,Pc=/\d{3}/,Qc=/\d{4}/,Rc=/[+-]?\d{6}/,Sc=/\d\d?/,Tc=/\d{1,3}/,Uc=/\d{1,4}/,Vc=/[+-]?\d{1,6}/,Wc=/\d+/,Xc=/[+-]?\d+/,Yc=/Z|[+-]\d\d:?\d\d/gi,Zc=/[+-]?\d+(\.\d{1,3})?/,$c=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,_c={},ad={},bd=0,cd=1,dd=2,ed=3,fd=4,gd=5,hd=6;G("M",["MM",2],"Mo",function(){return this.month()+1}),G("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),G("MMMM",0,0,function(a){return this.localeData().months(this,a)}),y("month","M"),L("M",Sc),L("MM",Sc,Oc),L("MMM",$c),L("MMMM",$c),O(["M","MM"],function(a,b){b[cd]=p(a)-1}),O(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[cd]=e:j(c).invalidMonth=a});var id="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),jd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),kd={};a.suppressDeprecationWarnings=!1;var ld=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,md=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],nd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],od=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=$("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),G(0,["YY",2],0,function(){return this.year()%100}),G(0,["YYYY",4],0,"year"),G(0,["YYYYY",5],0,"year"),G(0,["YYYYYY",6,!0],0,"year"),y("year","y"),L("Y",Xc),L("YY",Sc,Oc),L("YYYY",Uc,Qc),L("YYYYY",Vc,Rc),L("YYYYYY",Vc,Rc),O(["YYYY","YYYYY","YYYYYY"],bd),O("YY",function(b,c){c[bd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return p(a)+(p(a)>68?1900:2e3)};var pd=B("FullYear",!1);G("w",["ww",2],"wo","week"),G("W",["WW",2],"Wo","isoWeek"),y("week","w"),y("isoWeek","W"),L("w",Sc),L("ww",Sc,Oc),L("W",Sc),L("WW",Sc,Oc),P(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=p(a)});var qd={dow:0,doy:6};G("DDD",["DDDD",3],"DDDo","dayOfYear"),y("dayOfYear","DDD"),L("DDD",Tc),L("DDDD",Pc),O(["DDD","DDDD"],function(a,b,c){c._dayOfYear=p(a)}),a.ISO_8601=function(){};var rd=$("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Aa.apply(null,arguments);return this>a?this:a}),sd=$("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Aa.apply(null,arguments);return a>this?this:a});Ga("Z",":"),Ga("ZZ",""),L("Z",Yc),L("ZZ",Yc),O(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ha(a)});var td=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var ud=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,vd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Va.fn=Ea.prototype;var wd=Za(1,"add"),xd=Za(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var yd=$("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});G(0,["gg",2],0,function(){return this.weekYear()%100}),G(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Ab("gggg","weekYear"),Ab("ggggg","weekYear"),Ab("GGGG","isoWeekYear"),Ab("GGGGG","isoWeekYear"),y("weekYear","gg"),y("isoWeekYear","GG"),L("G",Xc),L("g",Xc),L("GG",Sc,Oc),L("gg",Sc,Oc),L("GGGG",Uc,Qc),L("gggg",Uc,Qc),L("GGGGG",Vc,Rc),L("ggggg",Vc,Rc),P(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=p(a)}),P(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),G("Q",0,0,"quarter"),y("quarter","Q"),L("Q",Nc),O("Q",function(a,b){b[cd]=3*(p(a)-1)}),G("D",["DD",2],"Do","date"),y("date","D"),L("D",Sc),L("DD",Sc,Oc),L("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),O(["D","DD"],dd),O("Do",function(a,b){b[dd]=p(a.match(Sc)[0],10)});var zd=B("Date",!0);G("d",0,"do","day"),G("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),G("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),G("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),G("e",0,0,"weekday"),G("E",0,0,"isoWeekday"),y("day","d"),y("weekday","e"),y("isoWeekday","E"),L("d",Sc),L("e",Sc),L("E",Sc),L("dd",$c),L("ddd",$c),L("dddd",$c),P(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),P(["d","e","E"],function(a,b,c,d){b[d]=p(a)});var Ad="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Bd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Cd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");G("H",["HH",2],0,"hour"),G("h",["hh",2],0,function(){return this.hours()%12||12}),Pb("a",!0),Pb("A",!1),y("hour","h"),L("a",Qb),L("A",Qb),L("H",Sc),L("h",Sc),L("HH",Sc,Oc),L("hh",Sc,Oc),O(["H","HH"],ed),O(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),O(["h","hh"],function(a,b,c){b[ed]=p(a),j(c).bigHour=!0});var Dd=/[ap]\.?m?\.?/i,Ed=B("Hours",!0);G("m",["mm",2],0,"minute"),y("minute","m"),L("m",Sc),L("mm",Sc,Oc),O(["m","mm"],fd);var Fd=B("Minutes",!1);G("s",["ss",2],0,"second"),y("second","s"),L("s",Sc),L("ss",Sc,Oc),O(["s","ss"],gd);var Gd=B("Seconds",!1);G("S",0,0,function(){return~~(this.millisecond()/100)}),G(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),Tb("SSS"),Tb("SSSS"),y("millisecond","ms"),L("S",Tc,Nc),L("SS",Tc,Oc),L("SSS",Tc,Pc),L("SSSS",Wc),O(["S","SS","SSS","SSSS"],function(a,b){b[hd]=p(1e3*("0."+a))});var Hd=B("Milliseconds",!1);G("z",0,0,"zoneAbbr"),G("zz",0,0,"zoneName");var Id=n.prototype;Id.add=wd,Id.calendar=_a,Id.clone=ab,Id.diff=gb,Id.endOf=sb,Id.format=kb,Id.from=lb,Id.fromNow=mb,Id.to=nb,Id.toNow=ob,Id.get=E,Id.invalidAt=zb,Id.isAfter=bb,Id.isBefore=cb,Id.isBetween=db,Id.isSame=eb,Id.isValid=xb,Id.lang=yd,Id.locale=pb,Id.localeData=qb,Id.max=sd,Id.min=rd,Id.parsingFlags=yb,Id.set=E,Id.startOf=rb,Id.subtract=xd,Id.toArray=wb,Id.toDate=vb,Id.toISOString=jb,Id.toJSON=jb,Id.toString=ib,Id.unix=ub,Id.valueOf=tb,Id.year=pd,Id.isLeapYear=ga,Id.weekYear=Cb,Id.isoWeekYear=Db,Id.quarter=Id.quarters=Gb,Id.month=W,Id.daysInMonth=X,Id.week=Id.weeks=la,Id.isoWeek=Id.isoWeeks=ma,Id.weeksInYear=Fb,Id.isoWeeksInYear=Eb,Id.date=zd,Id.day=Id.days=Mb,Id.weekday=Nb,Id.isoWeekday=Ob,Id.dayOfYear=oa,Id.hour=Id.hours=Ed,Id.minute=Id.minutes=Fd,Id.second=Id.seconds=Gd,Id.millisecond=Id.milliseconds=Hd,Id.utcOffset=Ka,Id.utc=Ma,Id.local=Na,Id.parseZone=Oa,Id.hasAlignedHourOffset=Pa,Id.isDST=Qa,Id.isDSTShifted=Ra,Id.isLocal=Sa,Id.isUtcOffset=Ta,Id.isUtc=Ua,Id.isUTC=Ua,Id.zoneAbbr=Ub,Id.zoneName=Vb,Id.dates=$("dates accessor is deprecated. Use date instead.",zd),Id.months=$("months accessor is deprecated. Use month instead",W),Id.years=$("years accessor is deprecated. Use year instead",pd),Id.zone=$("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",La);var Jd=Id,Kd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Ld={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM D, YYYY LT"},Md="Invalid date",Nd="%d",Od=/\d{1,2}/,Pd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour", -hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Qd=r.prototype;Qd._calendar=Kd,Qd.calendar=Yb,Qd._longDateFormat=Ld,Qd.longDateFormat=Zb,Qd._invalidDate=Md,Qd.invalidDate=$b,Qd._ordinal=Nd,Qd.ordinal=_b,Qd._ordinalParse=Od,Qd.preparse=ac,Qd.postformat=ac,Qd._relativeTime=Pd,Qd.relativeTime=bc,Qd.pastFuture=cc,Qd.set=dc,Qd.months=S,Qd._months=id,Qd.monthsShort=T,Qd._monthsShort=jd,Qd.monthsParse=U,Qd.week=ia,Qd._week=qd,Qd.firstDayOfYear=ka,Qd.firstDayOfWeek=ja,Qd.weekdays=Ib,Qd._weekdays=Ad,Qd.weekdaysMin=Kb,Qd._weekdaysMin=Cd,Qd.weekdaysShort=Jb,Qd._weekdaysShort=Bd,Qd.weekdaysParse=Lb,Qd.isPM=Rb,Qd._meridiemParse=Dd,Qd.meridiem=Sb,v("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===p(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=$("moment.lang is deprecated. Use moment.locale instead.",v),a.langData=$("moment.langData is deprecated. Use moment.localeData instead.",x);var Rd=Math.abs,Sd=uc("ms"),Td=uc("s"),Ud=uc("m"),Vd=uc("h"),Wd=uc("d"),Xd=uc("w"),Yd=uc("M"),Zd=uc("y"),$d=wc("milliseconds"),_d=wc("seconds"),ae=wc("minutes"),be=wc("hours"),ce=wc("days"),de=wc("months"),ee=wc("years"),fe=Math.round,ge={s:45,m:45,h:22,d:26,M:11},he=Math.abs,ie=Ea.prototype;ie.abs=lc,ie.add=nc,ie.subtract=oc,ie.as=sc,ie.asMilliseconds=Sd,ie.asSeconds=Td,ie.asMinutes=Ud,ie.asHours=Vd,ie.asDays=Wd,ie.asWeeks=Xd,ie.asMonths=Yd,ie.asYears=Zd,ie.valueOf=tc,ie._bubble=pc,ie.get=vc,ie.milliseconds=$d,ie.seconds=_d,ie.minutes=ae,ie.hours=be,ie.days=ce,ie.weeks=xc,ie.months=de,ie.years=ee,ie.humanize=Bc,ie.toISOString=Cc,ie.toString=Cc,ie.toJSON=Cc,ie.locale=pb,ie.localeData=qb,ie.toIsoString=$("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Cc),ie.lang=yd,G("X",0,0,"unix"),G("x",0,0,"valueOf"),L("x",Xc),L("X",Zc),O("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),O("x",function(a,b,c){c._d=new Date(p(a))}),a.version="2.10.3",b(Aa),a.fn=Jd,a.min=Ca,a.max=Da,a.utc=h,a.unix=Wb,a.months=gc,a.isDate=d,a.locale=v,a.invalid=l,a.duration=Va,a.isMoment=o,a.weekdays=ic,a.parseZone=Xb,a.localeData=x,a.isDuration=Fa,a.monthsShort=hc,a.weekdaysMin=kc,a.defineLocale=w,a.weekdaysShort=jc,a.normalizeUnits=z,a.relativeTimeThreshold=Ac;var je=a;return je}); +!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return Hc.apply(null,arguments)}function b(a){Hc=a}function c(a){return"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c0)for(c in Jc)d=Jc[c],e=b[d],"undefined"!=typeof e&&(a[d]=e);return a}function n(b){m(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),Kc===!1&&(Kc=!0,a.updateOffset(this),Kc=!1)}function o(a){return a instanceof n||null!=a&&null!=a._isAMomentObject}function p(a){return 0>a?Math.ceil(a):Math.floor(a)}function q(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=p(b)),c}function r(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&q(a[d])!==q(b[d]))&&g++;return g+f}function s(){}function t(a){return a?a.toLowerCase().replace("_","-"):a}function u(a){for(var b,c,d,e,f=0;f0;){if(d=v(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&r(e,c,!0)>=b-1)break;b--}f++}return null}function v(a){var b=null;if(!Lc[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=Ic._abbr,require("./locale/"+a),w(b)}catch(c){}return Lc[a]}function w(a,b){var c;return a&&(c="undefined"==typeof b?y(a):x(a,b),c&&(Ic=c)),Ic._abbr}function x(a,b){return null!==b?(b.abbr=a,Lc[a]=Lc[a]||new s,Lc[a].set(b),w(a),Lc[a]):(delete Lc[a],null)}function y(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return Ic;if(!c(a)){if(b=v(a))return b;a=[a]}return u(a)}function z(a,b){var c=a.toLowerCase();Mc[c]=Mc[c+"s"]=Mc[b]=a}function A(a){return"string"==typeof a?Mc[a]||Mc[a.toLowerCase()]:void 0}function B(a){var b,c,d={};for(c in a)f(a,c)&&(b=A(c),b&&(d[b]=a[c]));return d}function C(b,c){return function(d){return null!=d?(E(this,b,d),a.updateOffset(this,c),this):D(this,b)}}function D(a,b){return a._d["get"+(a._isUTC?"UTC":"")+b]()}function E(a,b,c){return a._d["set"+(a._isUTC?"UTC":"")+b](c)}function F(a,b){var c;if("object"==typeof a)for(c in a)this.set(c,a[c]);else if(a=A(a),"function"==typeof this[a])return this[a](b);return this}function G(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}function H(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Qc[a]=e),b&&(Qc[b[0]]=function(){return G(e.apply(this,arguments),b[1],b[2])}),c&&(Qc[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function I(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function J(a){var b,c,d=a.match(Nc);for(b=0,c=d.length;c>b;b++)Qc[d[b]]?d[b]=Qc[d[b]]:d[b]=I(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function K(a,b){return a.isValid()?(b=L(b,a.localeData()),Pc[b]=Pc[b]||J(b),Pc[b](a)):a.localeData().invalidDate()}function L(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Oc.lastIndex=0;d>=0&&Oc.test(a);)a=a.replace(Oc,c),Oc.lastIndex=0,d-=1;return a}function M(a){return"function"==typeof a&&"[object Function]"===Object.prototype.toString.call(a)}function N(a,b,c){dd[a]=M(b)?b:function(a){return a&&c?c:b}}function O(a,b){return f(dd,a)?dd[a](b._strict,b._locale):new RegExp(P(a))}function P(a){return a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function Q(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=q(a)}),c=0;cd;d++){if(e=h([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}function X(a,b){var c;return"string"==typeof b&&(b=a.localeData().monthsParse(b),"number"!=typeof b)?a:(c=Math.min(a.date(),T(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a)}function Y(b){return null!=b?(X(this,b),a.updateOffset(this,!0),this):D(this,"Month")}function Z(){return T(this.year(),this.month())}function $(a){var b,c=a._a;return c&&-2===j(a).overflow&&(b=c[gd]<0||c[gd]>11?gd:c[hd]<1||c[hd]>T(c[fd],c[gd])?hd:c[id]<0||c[id]>24||24===c[id]&&(0!==c[jd]||0!==c[kd]||0!==c[ld])?id:c[jd]<0||c[jd]>59?jd:c[kd]<0||c[kd]>59?kd:c[ld]<0||c[ld]>999?ld:-1,j(a)._overflowDayOfYear&&(fd>b||b>hd)&&(b=hd),j(a).overflow=b),a}function _(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function aa(a,b){var c=!0;return g(function(){return c&&(_(a+"\n"+(new Error).stack),c=!1),b.apply(this,arguments)},b)}function ba(a,b){od[a]||(_(b),od[a]=!0)}function ca(a){var b,c,d=a._i,e=pd.exec(d);if(e){for(j(a).iso=!0,b=0,c=qd.length;c>b;b++)if(qd[b][1].exec(d)){a._f=qd[b][0];break}for(b=0,c=rd.length;c>b;b++)if(rd[b][1].exec(d)){a._f+=(e[6]||" ")+rd[b][0];break}d.match(ad)&&(a._f+="Z"),va(a)}else a._isValid=!1}function da(b){var c=sd.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(ca(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}function ea(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function fa(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function ga(a){return ha(a)?366:365}function ha(a){return a%4===0&&a%100!==0||a%400===0}function ia(){return ha(this.year())}function ja(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=Da(a).add(f,"d"),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function ka(a){return ja(a,this._week.dow,this._week.doy).week}function la(){return this._week.dow}function ma(){return this._week.doy}function na(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function oa(a){var b=ja(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}function pa(a,b,c,d,e){var f,g=6+e-d,h=fa(a,0,1+g),i=h.getUTCDay();return e>i&&(i+=7),c=null!=c?1*c:e,f=1+g+7*(b-1)-i+c,{year:f>0?a:a-1,dayOfYear:f>0?f:ga(a-1)+f}}function qa(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function ra(a,b,c){return null!=a?a:null!=b?b:c}function sa(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function ta(a){var b,c,d,e,f=[];if(!a._d){for(d=sa(a),a._w&&null==a._a[hd]&&null==a._a[gd]&&ua(a),a._dayOfYear&&(e=ra(a._a[fd],d[fd]),a._dayOfYear>ga(e)&&(j(a)._overflowDayOfYear=!0),c=fa(e,0,a._dayOfYear),a._a[gd]=c.getUTCMonth(),a._a[hd]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];24===a._a[id]&&0===a._a[jd]&&0===a._a[kd]&&0===a._a[ld]&&(a._nextDay=!0,a._a[id]=0),a._d=(a._useUTC?fa:ea).apply(null,f),null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[id]=24)}}function ua(a){var b,c,d,e,f,g,h;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=ra(b.GG,a._a[fd],ja(Da(),1,4).year),d=ra(b.W,1),e=ra(b.E,1)):(f=a._locale._week.dow,g=a._locale._week.doy,c=ra(b.gg,a._a[fd],ja(Da(),f,g).year),d=ra(b.w,1),null!=b.d?(e=b.d,f>e&&++d):e=null!=b.e?b.e+f:f),h=pa(c,d,e,g,f),a._a[fd]=h.year,a._dayOfYear=h.dayOfYear}function va(b){if(b._f===a.ISO_8601)return void ca(b);b._a=[],j(b).empty=!0;var c,d,e,f,g,h=""+b._i,i=h.length,k=0;for(e=L(b._f,b._locale).match(Nc)||[],c=0;c0&&j(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),k+=d.length),Qc[f]?(d?j(b).empty=!1:j(b).unusedTokens.push(f),S(f,d,b)):b._strict&&!d&&j(b).unusedTokens.push(f);j(b).charsLeftOver=i-k,h.length>0&&j(b).unusedInput.push(h),j(b).bigHour===!0&&b._a[id]<=12&&b._a[id]>0&&(j(b).bigHour=void 0),b._a[id]=wa(b._locale,b._a[id],b._meridiem),ta(b),$(b)}function wa(a,b,c){var d;return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}function xa(a){var b,c,d,e,f;if(0===a._f.length)return j(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;ef)&&(d=f,c=b));g(a,c||b)}function ya(a){if(!a._d){var b=B(a._i);a._a=[b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],ta(a)}}function za(a){var b=new n($(Aa(a)));return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function Aa(a){var b=a._i,e=a._f;return a._locale=a._locale||y(a._l),null===b||void 0===e&&""===b?l({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),o(b)?new n($(b)):(c(e)?xa(a):e?va(a):d(b)?a._d=b:Ba(a),a))}function Ba(b){var f=b._i;void 0===f?b._d=new Date:d(f)?b._d=new Date(+f):"string"==typeof f?da(b):c(f)?(b._a=e(f.slice(0),function(a){return parseInt(a,10)}),ta(b)):"object"==typeof f?ya(b):"number"==typeof f?b._d=new Date(f):a.createFromInputFallback(b)}function Ca(a,b,c,d,e){var f={};return"boolean"==typeof c&&(d=c,c=void 0),f._isAMomentObject=!0,f._useUTC=f._isUTC=e,f._l=c,f._i=a,f._f=b,f._strict=d,za(f)}function Da(a,b,c,d){return Ca(a,b,c,d,!1)}function Ea(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return Da();for(d=b[0],e=1;ea&&(a=-a,c="-"),c+G(~~(a/60),2)+b+G(~~a%60,2)})}function Ka(a){var b=(a||"").match(ad)||[],c=b[b.length-1]||[],d=(c+"").match(xd)||["-",0,0],e=+(60*d[1])+q(d[2]);return"+"===d[0]?e:-e}function La(b,c){var e,f;return c._isUTC?(e=c.clone(),f=(o(b)||d(b)?+b:+Da(b))-+e,e._d.setTime(+e._d+f),a.updateOffset(e,!1),e):Da(b).local()}function Ma(a){return 15*-Math.round(a._d.getTimezoneOffset()/15)}function Na(b,c){var d,e=this._offset||0;return null!=b?("string"==typeof b&&(b=Ka(b)),Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ma(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?bb(this,Ya(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ma(this)}function Oa(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Pa(a){return this.utcOffset(0,a)}function Qa(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ma(this),"m")),this}function Ra(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(Ka(this._i)),this}function Sa(a){return a=a?Da(a).utcOffset():0,(this.utcOffset()-a)%60===0}function Ta(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ua(){if("undefined"!=typeof this._isDSTShifted)return this._isDSTShifted;var a={};if(m(a,this),a=Aa(a),a._a){var b=a._isUTC?h(a._a):Da(a._a);this._isDSTShifted=this.isValid()&&r(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Va(){return!this._isUTC}function Wa(){return this._isUTC}function Xa(){return this._isUTC&&0===this._offset}function Ya(a,b){var c,d,e,g=a,h=null;return Ia(a)?g={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(g={},b?g[b]=a:g.milliseconds=a):(h=yd.exec(a))?(c="-"===h[1]?-1:1,g={y:0,d:q(h[hd])*c,h:q(h[id])*c,m:q(h[jd])*c,s:q(h[kd])*c,ms:q(h[ld])*c}):(h=zd.exec(a))?(c="-"===h[1]?-1:1,g={y:Za(h[2],c),M:Za(h[3],c),d:Za(h[4],c),h:Za(h[5],c),m:Za(h[6],c),s:Za(h[7],c),w:Za(h[8],c)}):null==g?g={}:"object"==typeof g&&("from"in g||"to"in g)&&(e=_a(Da(g.from),Da(g.to)),g={},g.ms=e.milliseconds,g.M=e.months),d=new Ha(g),Ia(a)&&f(a,"_locale")&&(d._locale=a._locale),d}function Za(a,b){var c=a&&parseFloat(a.replace(",","."));return(isNaN(c)?0:c)*b}function $a(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function _a(a,b){var c;return b=La(b,a),a.isBefore(b)?c=$a(a,b):(c=$a(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c}function ab(a,b){return function(c,d){var e,f;return null===d||isNaN(+d)||(ba(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period)."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Ya(c,d),bb(this,e,a),this}}function bb(b,c,d,e){var f=c._milliseconds,g=c._days,h=c._months;e=null==e?!0:e,f&&b._d.setTime(+b._d+f*d),g&&E(b,"Date",D(b,"Date")+g*d),h&&X(b,D(b,"Month")+h*d),e&&a.updateOffset(b,g||h)}function cb(a,b){var c=a||Da(),d=La(c,this).startOf("day"),e=this.diff(d,"days",!0),f=-6>e?"sameElse":-1>e?"lastWeek":0>e?"lastDay":1>e?"sameDay":2>e?"nextDay":7>e?"nextWeek":"sameElse";return this.format(b&&b[f]||this.localeData().calendar(f,this,Da(c)))}function db(){return new n(this)}function eb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+this>+a):(c=o(a)?+a:+Da(a),c<+this.clone().startOf(b))}function fb(a,b){var c;return b=A("undefined"!=typeof b?b:"millisecond"),"millisecond"===b?(a=o(a)?a:Da(a),+a>+this):(c=o(a)?+a:+Da(a),+this.clone().endOf(b)b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)}function kb(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function lb(){var a=this.clone().utc();return 0b;b++)if(this._weekdaysParse[b]||(c=Da([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b}function Pb(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Kb(a,this.localeData()),this.add(a-b,"d")):b}function Qb(a){var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function Rb(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)}function Sb(a,b){H(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}function Tb(a,b){return b._meridiemParse}function Ub(a){return"p"===(a+"").toLowerCase().charAt(0)}function Vb(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wb(a,b){b[ld]=q(1e3*("0."+a))}function Xb(){return this._isUTC?"UTC":""}function Yb(){return this._isUTC?"Coordinated Universal Time":""}function Zb(a){return Da(1e3*a)}function $b(){return Da.apply(null,arguments).parseZone()}function _b(a,b,c){var d=this._calendar[a];return"function"==typeof d?d.call(b,c):d}function ac(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function bc(){return this._invalidDate}function cc(a){return this._ordinal.replace("%d",a)}function dc(a){return a}function ec(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)}function fc(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)}function gc(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b;this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function hc(a,b,c,d){var e=y(),f=h().set(d,b);return e[c](f,a)}function ic(a,b,c,d,e){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return hc(a,b,c,e);var f,g=[];for(f=0;d>f;f++)g[f]=hc(a,f,c,e);return g}function jc(a,b){return ic(a,b,"months",12,"month")}function kc(a,b){return ic(a,b,"monthsShort",12,"month")}function lc(a,b){return ic(a,b,"weekdays",7,"day")}function mc(a,b){return ic(a,b,"weekdaysShort",7,"day")}function nc(a,b){return ic(a,b,"weekdaysMin",7,"day")}function oc(){var a=this._data;return this._milliseconds=Wd(this._milliseconds),this._days=Wd(this._days),this._months=Wd(this._months),a.milliseconds=Wd(a.milliseconds),a.seconds=Wd(a.seconds),a.minutes=Wd(a.minutes),a.hours=Wd(a.hours),a.months=Wd(a.months),a.years=Wd(a.years),this}function pc(a,b,c,d){var e=Ya(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}function qc(a,b){return pc(this,a,b,1)}function rc(a,b){return pc(this,a,b,-1)}function sc(a){return 0>a?Math.floor(a):Math.ceil(a)}function tc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*sc(vc(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=p(f/1e3),i.seconds=a%60,b=p(a/60),i.minutes=b%60,c=p(b/60),i.hours=c%24,g+=p(c/24),e=p(uc(g)),h+=e,g-=sc(vc(e)),d=p(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function uc(a){return 4800*a/146097}function vc(a){return 146097*a/4800}function wc(a){var b,c,d=this._milliseconds;if(a=A(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+uc(b),"month"===a?c:c/12;switch(b=this._days+Math.round(vc(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}function xc(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*q(this._months/12)}function yc(a){return function(){return this.as(a)}}function zc(a){return a=A(a),this[a+"s"]()}function Ac(a){return function(){return this._data[a]}}function Bc(){return p(this.days()/7)}function Cc(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function Dc(a,b,c){var d=Ya(a).abs(),e=ke(d.as("s")),f=ke(d.as("m")),g=ke(d.as("h")),h=ke(d.as("d")),i=ke(d.as("M")),j=ke(d.as("y")),k=e0,k[4]=c,Cc.apply(null,k)}function Ec(a,b){return void 0===le[a]?!1:void 0===b?le[a]:(le[a]=b,!0)}function Fc(a){var b=this.localeData(),c=Dc(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function Gc(){var a,b,c,d=me(this._milliseconds)/1e3,e=me(this._days),f=me(this._months);a=p(d/60),b=p(a/60),d%=60,a%=60,c=p(f/12),f%=12;var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var Hc,Ic,Jc=a.momentProperties=[],Kc=!1,Lc={},Mc={},Nc=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Oc=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Pc={},Qc={},Rc=/\d/,Sc=/\d\d/,Tc=/\d{3}/,Uc=/\d{4}/,Vc=/[+-]?\d{6}/,Wc=/\d\d?/,Xc=/\d{1,3}/,Yc=/\d{1,4}/,Zc=/[+-]?\d{1,6}/,$c=/\d+/,_c=/[+-]?\d+/,ad=/Z|[+-]\d\d:?\d\d/gi,bd=/[+-]?\d+(\.\d{1,3})?/,cd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,dd={},ed={},fd=0,gd=1,hd=2,id=3,jd=4,kd=5,ld=6;H("M",["MM",2],"Mo",function(){return this.month()+1}),H("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),H("MMMM",0,0,function(a){return this.localeData().months(this,a)}),z("month","M"),N("M",Wc),N("MM",Wc,Sc),N("MMM",cd),N("MMMM",cd),Q(["M","MM"],function(a,b){b[gd]=q(a)-1}),Q(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[gd]=e:j(c).invalidMonth=a});var md="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),nd="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),od={};a.suppressDeprecationWarnings=!1;var pd=/^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,qd=[["YYYYYY-MM-DD",/[+-]\d{6}-\d{2}-\d{2}/],["YYYY-MM-DD",/\d{4}-\d{2}-\d{2}/],["GGGG-[W]WW-E",/\d{4}-W\d{2}-\d/],["GGGG-[W]WW",/\d{4}-W\d{2}/],["YYYY-DDD",/\d{4}-\d{3}/]],rd=[["HH:mm:ss.SSSS",/(T| )\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss",/(T| )\d\d:\d\d:\d\d/],["HH:mm",/(T| )\d\d:\d\d/],["HH",/(T| )\d\d/]],sd=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=aa("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to https://github.com/moment/moment/issues/1407 for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),H(0,["YY",2],0,function(){return this.year()%100}),H(0,["YYYY",4],0,"year"),H(0,["YYYYY",5],0,"year"),H(0,["YYYYYY",6,!0],0,"year"),z("year","y"),N("Y",_c),N("YY",Wc,Sc),N("YYYY",Yc,Uc),N("YYYYY",Zc,Vc),N("YYYYYY",Zc,Vc),Q(["YYYYY","YYYYYY"],fd),Q("YYYY",function(b,c){c[fd]=2===b.length?a.parseTwoDigitYear(b):q(b)}),Q("YY",function(b,c){c[fd]=a.parseTwoDigitYear(b)}),a.parseTwoDigitYear=function(a){return q(a)+(q(a)>68?1900:2e3)};var td=C("FullYear",!1);H("w",["ww",2],"wo","week"),H("W",["WW",2],"Wo","isoWeek"),z("week","w"),z("isoWeek","W"),N("w",Wc),N("ww",Wc,Sc),N("W",Wc),N("WW",Wc,Sc),R(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=q(a)});var ud={dow:0,doy:6};H("DDD",["DDDD",3],"DDDo","dayOfYear"),z("dayOfYear","DDD"),N("DDD",Xc),N("DDDD",Tc),Q(["DDD","DDDD"],function(a,b,c){c._dayOfYear=q(a)}),a.ISO_8601=function(){};var vd=aa("moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return this>a?this:a}),wd=aa("moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548",function(){var a=Da.apply(null,arguments);return a>this?this:a});Ja("Z",":"),Ja("ZZ",""),N("Z",ad),N("ZZ",ad),Q(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=Ka(a)});var xd=/([\+\-]|\d\d)/gi;a.updateOffset=function(){};var yd=/(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,zd=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/;Ya.fn=Ha.prototype;var Ad=ab(1,"add"),Bd=ab(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ";var Cd=aa("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});H(0,["gg",2],0,function(){return this.weekYear()%100}),H(0,["GG",2],0,function(){return this.isoWeekYear()%100}),Db("gggg","weekYear"),Db("ggggg","weekYear"),Db("GGGG","isoWeekYear"),Db("GGGGG","isoWeekYear"),z("weekYear","gg"),z("isoWeekYear","GG"),N("G",_c),N("g",_c),N("GG",Wc,Sc),N("gg",Wc,Sc),N("GGGG",Yc,Uc),N("gggg",Yc,Uc),N("GGGGG",Zc,Vc),N("ggggg",Zc,Vc),R(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=q(a)}),R(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),H("Q",0,0,"quarter"),z("quarter","Q"),N("Q",Rc),Q("Q",function(a,b){b[gd]=3*(q(a)-1)}),H("D",["DD",2],"Do","date"),z("date","D"),N("D",Wc),N("DD",Wc,Sc),N("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),Q(["D","DD"],hd),Q("Do",function(a,b){b[hd]=q(a.match(Wc)[0],10)});var Dd=C("Date",!0);H("d",0,"do","day"),H("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),H("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),H("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),H("e",0,0,"weekday"),H("E",0,0,"isoWeekday"),z("day","d"),z("weekday","e"),z("isoWeekday","E"),N("d",Wc),N("e",Wc),N("E",Wc),N("dd",cd),N("ddd",cd),N("dddd",cd),R(["dd","ddd","dddd"],function(a,b,c){var d=c._locale.weekdaysParse(a);null!=d?b.d=d:j(c).invalidWeekday=a}),R(["d","e","E"],function(a,b,c,d){b[d]=q(a)});var Ed="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Fd="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Gd="Su_Mo_Tu_We_Th_Fr_Sa".split("_");H("H",["HH",2],0,"hour"),H("h",["hh",2],0,function(){return this.hours()%12||12}),Sb("a",!0),Sb("A",!1),z("hour","h"),N("a",Tb),N("A",Tb),N("H",Wc),N("h",Wc),N("HH",Wc,Sc),N("hh",Wc,Sc),Q(["H","HH"],id),Q(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),Q(["h","hh"],function(a,b,c){b[id]=q(a),j(c).bigHour=!0});var Hd=/[ap]\.?m?\.?/i,Id=C("Hours",!0);H("m",["mm",2],0,"minute"),z("minute","m"),N("m",Wc),N("mm",Wc,Sc),Q(["m","mm"],jd);var Jd=C("Minutes",!1);H("s",["ss",2],0,"second"),z("second","s"),N("s",Wc),N("ss",Wc,Sc),Q(["s","ss"],kd);var Kd=C("Seconds",!1);H("S",0,0,function(){return~~(this.millisecond()/100)}),H(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),H(0,["SSS",3],0,"millisecond"),H(0,["SSSS",4],0,function(){return 10*this.millisecond()}),H(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),H(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),H(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),H(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),H(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),z("millisecond","ms"),N("S",Xc,Rc),N("SS",Xc,Sc),N("SSS",Xc,Tc);var Ld;for(Ld="SSSS";Ld.length<=9;Ld+="S")N(Ld,$c);for(Ld="S";Ld.length<=9;Ld+="S")Q(Ld,Wb);var Md=C("Milliseconds",!1);H("z",0,0,"zoneAbbr"),H("zz",0,0,"zoneName");var Nd=n.prototype;Nd.add=Ad,Nd.calendar=cb,Nd.clone=db,Nd.diff=ib,Nd.endOf=ub,Nd.format=mb,Nd.from=nb,Nd.fromNow=ob,Nd.to=pb,Nd.toNow=qb,Nd.get=F,Nd.invalidAt=Cb,Nd.isAfter=eb,Nd.isBefore=fb,Nd.isBetween=gb,Nd.isSame=hb,Nd.isValid=Ab,Nd.lang=Cd,Nd.locale=rb,Nd.localeData=sb,Nd.max=wd,Nd.min=vd,Nd.parsingFlags=Bb,Nd.set=F,Nd.startOf=tb,Nd.subtract=Bd,Nd.toArray=yb,Nd.toObject=zb,Nd.toDate=xb,Nd.toISOString=lb,Nd.toJSON=lb,Nd.toString=kb,Nd.unix=wb,Nd.valueOf=vb,Nd.year=td,Nd.isLeapYear=ia,Nd.weekYear=Fb,Nd.isoWeekYear=Gb,Nd.quarter=Nd.quarters=Jb,Nd.month=Y,Nd.daysInMonth=Z,Nd.week=Nd.weeks=na,Nd.isoWeek=Nd.isoWeeks=oa,Nd.weeksInYear=Ib,Nd.isoWeeksInYear=Hb,Nd.date=Dd,Nd.day=Nd.days=Pb,Nd.weekday=Qb,Nd.isoWeekday=Rb,Nd.dayOfYear=qa,Nd.hour=Nd.hours=Id,Nd.minute=Nd.minutes=Jd,Nd.second=Nd.seconds=Kd, +Nd.millisecond=Nd.milliseconds=Md,Nd.utcOffset=Na,Nd.utc=Pa,Nd.local=Qa,Nd.parseZone=Ra,Nd.hasAlignedHourOffset=Sa,Nd.isDST=Ta,Nd.isDSTShifted=Ua,Nd.isLocal=Va,Nd.isUtcOffset=Wa,Nd.isUtc=Xa,Nd.isUTC=Xa,Nd.zoneAbbr=Xb,Nd.zoneName=Yb,Nd.dates=aa("dates accessor is deprecated. Use date instead.",Dd),Nd.months=aa("months accessor is deprecated. Use month instead",Y),Nd.years=aa("years accessor is deprecated. Use year instead",td),Nd.zone=aa("moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779",Oa);var Od=Nd,Pd={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},Qd={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},Rd="Invalid date",Sd="%d",Td=/\d{1,2}/,Ud={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},Vd=s.prototype;Vd._calendar=Pd,Vd.calendar=_b,Vd._longDateFormat=Qd,Vd.longDateFormat=ac,Vd._invalidDate=Rd,Vd.invalidDate=bc,Vd._ordinal=Sd,Vd.ordinal=cc,Vd._ordinalParse=Td,Vd.preparse=dc,Vd.postformat=dc,Vd._relativeTime=Ud,Vd.relativeTime=ec,Vd.pastFuture=fc,Vd.set=gc,Vd.months=U,Vd._months=md,Vd.monthsShort=V,Vd._monthsShort=nd,Vd.monthsParse=W,Vd.week=ka,Vd._week=ud,Vd.firstDayOfYear=ma,Vd.firstDayOfWeek=la,Vd.weekdays=Lb,Vd._weekdays=Ed,Vd.weekdaysMin=Nb,Vd._weekdaysMin=Gd,Vd.weekdaysShort=Mb,Vd._weekdaysShort=Fd,Vd.weekdaysParse=Ob,Vd.isPM=Ub,Vd._meridiemParse=Hd,Vd.meridiem=Vb,w("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===q(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),a.lang=aa("moment.lang is deprecated. Use moment.locale instead.",w),a.langData=aa("moment.langData is deprecated. Use moment.localeData instead.",y);var Wd=Math.abs,Xd=yc("ms"),Yd=yc("s"),Zd=yc("m"),$d=yc("h"),_d=yc("d"),ae=yc("w"),be=yc("M"),ce=yc("y"),de=Ac("milliseconds"),ee=Ac("seconds"),fe=Ac("minutes"),ge=Ac("hours"),he=Ac("days"),ie=Ac("months"),je=Ac("years"),ke=Math.round,le={s:45,m:45,h:22,d:26,M:11},me=Math.abs,ne=Ha.prototype;ne.abs=oc,ne.add=qc,ne.subtract=rc,ne.as=wc,ne.asMilliseconds=Xd,ne.asSeconds=Yd,ne.asMinutes=Zd,ne.asHours=$d,ne.asDays=_d,ne.asWeeks=ae,ne.asMonths=be,ne.asYears=ce,ne.valueOf=xc,ne._bubble=tc,ne.get=zc,ne.milliseconds=de,ne.seconds=ee,ne.minutes=fe,ne.hours=ge,ne.days=he,ne.weeks=Bc,ne.months=ie,ne.years=je,ne.humanize=Fc,ne.toISOString=Gc,ne.toString=Gc,ne.toJSON=Gc,ne.locale=rb,ne.localeData=sb,ne.toIsoString=aa("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Gc),ne.lang=Cd,H("X",0,0,"unix"),H("x",0,0,"valueOf"),N("x",_c),N("X",bd),Q("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),Q("x",function(a,b,c){c._d=new Date(q(a))}),a.version="2.10.6",b(Da),a.fn=Od,a.min=Fa,a.max=Ga,a.utc=h,a.unix=Zb,a.months=jc,a.isDate=d,a.locale=w,a.invalid=l,a.duration=Ya,a.isMoment=o,a.weekdays=lc,a.parseZone=$b,a.localeData=y,a.isDuration=Ia,a.monthsShort=kc,a.weekdaysMin=nc,a.defineLocale=x,a.weekdaysShort=mc,a.normalizeUnits=A,a.relativeTimeThreshold=Ec;var oe=a;return oe}); /** * Lightbox v2.7.1 * by Lokesh Dhakar - http://lokeshdhakar.com/projects/lightbox2/ diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 8b590d85ae12..916aa7e40d5a 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -119,7 +119,7 @@ return array( 'active_client' => 'active client', 'active_clients' => 'active clients', 'invoices_past_due' => 'Invoices Past Due', - 'upcoming_invoices' => 'Upcoming invoices', + 'upcoming_invoices' => 'Upcoming Invoices', 'average_invoice' => 'Average invoice', // list pages @@ -738,6 +738,9 @@ return array( 'custom' => 'Custom', 'invoice_to' => 'Invoice to', 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + ); diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 661edbe5e014..864e7aeb1f89 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -6,7 +6,7 @@

- +
@if (count($paidToDate)) @foreach ($paidToDate as $item) @@ -44,12 +44,18 @@
- -
- {{ $invoicesSent }} -
+
- {{ Utils::pluralize('invoice', $invoicesSent) }} {{ trans('texts.sent') }} + {{ trans('texts.outstanding') }} +
+
+ @if (count($balances)) + @foreach ($balances as $item) + {{ Utils::formatMoney($item->value, $item->currency_id) }}
+ @endforeach + @else + {{ Utils::formatMoney(0) }} + @endif
@@ -61,13 +67,16 @@
-
+

{{ trans('texts.notifications') }} +
+ {{ $invoicesSent }} {{ Utils::pluralize('invoice', $invoicesSent) }} {{ trans('texts.sent') }} +

-
    +
      @foreach ($activities as $activity)
    • {{ Utils::timestampToDateString(strtotime($activity->created_at)) }}: @@ -76,15 +85,43 @@ @endforeach
+
+
+

+ {{ trans('texts.recent_payments') }} +

+
+
+ + + + + + + + + @foreach ($payments as $payment) + + + + + + + @endforeach + +
{{ trans('texts.invoice_number_short') }}{{ trans('texts.client') }}{{ trans('texts.payment_date') }}{{ trans('texts.amount') }}
{!! \App\Models\Invoice::calcLink($payment) !!}{!! link_to('/clients/'.$payment->client_public_id, trim($payment->client_name) ?: (trim($payment->first_name . ' ' . $payment->last_name) ?: $payment->email)) !!}{{ Utils::fromSqlDate($payment->payment_date) }}{{ Utils::formatMoney($payment->amount, $payment->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}
+
+
+
-
+

{{ trans('texts.invoices_past_due') }}

-
+
@@ -95,23 +132,23 @@ @foreach ($pastDue as $invoice) - - + + - + @endforeach
{{ trans('texts.invoice_number_short') }}
{!! $invoice->getLink() !!}{{ $invoice->client->getDisplayName() }}{!! \App\Models\Invoice::calcLink($invoice) !!}{!! link_to('/clients/'.$invoice->client_public_id, trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email)) !!} {{ Utils::fromSqlDate($invoice->due_date) }}{{ Utils::formatMoney($invoice->balance, $invoice->client->getCurrencyId()) }}{{ Utils::formatMoney($invoice->balance, $invoice->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}
-
+

{{ trans('texts.upcoming_invoices') }}

-
+
@@ -122,10 +159,10 @@ @foreach ($upcoming as $invoice) - - + + - + @endforeach diff --git a/resources/views/payments/payment.blade.php b/resources/views/payments/payment.blade.php index 57aa05572814..359f01a3ccd7 100644 --- a/resources/views/payments/payment.blade.php +++ b/resources/views/payments/payment.blade.php @@ -169,7 +169,7 @@ header h3 em {
@if ($client)

{{ $client->getDisplayName() }}

-

{{ trans('texts.invoice') . ' ' . $invoiceNumber }}|  {{ trans('texts.amount_due') }}: {{ Utils::formatMoney($amount, $currencyId) }}

+

{{ trans('texts.invoice') . ' ' . $invoiceNumber }}|  {{ trans('texts.amount_due') }}: {{ Utils::formatMoney($amount, $currencyId) }} {{ $currencyCode }}

@elseif ($paymentTitle)

{{ $paymentTitle }}
{{ $paymentSubtitle }}

@endif diff --git a/resources/views/tasks/edit.blade.php b/resources/views/tasks/edit.blade.php index aacfee35cb6b..294b85af80a5 100644 --- a/resources/views/tasks/edit.blade.php +++ b/resources/views/tasks/edit.blade.php @@ -223,7 +223,7 @@ }); self.startTime.pretty = ko.computed({ - read: function() { + read: function() { return self.startTime() ? moment.unix(self.startTime()).utcOffset({{ $minuteOffset }}).format('MMM D YYYY h:mm:ss a') : ''; }, write: function(data) { @@ -341,13 +341,6 @@ $clientSelect.combobox(); - @if ($task) - $('#date').datepicker('update', new Date('{{ Utils::fromSqlDateTime($task->start_time) }}')); - @else - var date = new Date(); - $('#date').datepicker('update', date); - @endif - @if (!$task && !$clientPublicId) $('.client-select input.form-control').focus(); @else diff --git a/resources/views/user_account.blade.php b/resources/views/user_account.blade.php index 47d03b3ce137..c3c2520aee0e 100644 --- a/resources/views/user_account.blade.php +++ b/resources/views/user_account.blade.php @@ -2,7 +2,7 @@ @if (isset($user_id) && $show_remove) @else - + @endif @if (isset($show_remove) && $show_remove) @@ -10,7 +10,9 @@ @endif @if (file_exists('logo/'.$account_key.'.jpg')) - +
+ +
@else
 
@endif diff --git a/storage/templates/bold.js b/storage/templates/bold.js index 79a4388ad038..d56955ade4c6 100644 --- a/storage/templates/bold.js +++ b/storage/templates/bold.js @@ -65,13 +65,13 @@ "$notesAndTerms", { "table": { - "widths": ["*", "*"], + "widths": ["*", "auto"], "body": "$subtotals" }, "layout": { "hLineWidth": "$none", "vLineWidth": "$none", - "paddingLeft": "$amount:8", + "paddingLeft": "$amount:34", "paddingRight": "$amount:8", "paddingTop": "$amount:4", "paddingBottom": "$amount:4" diff --git a/storage/templates/clean.js b/storage/templates/clean.js index 86cdfdf3ff45..6caa07959d60 100644 --- a/storage/templates/clean.js +++ b/storage/templates/clean.js @@ -3,7 +3,7 @@ "columns": [ { "image": "$accountLogo", - "width": 140 + "fit": [120, 80] }, { "stack": "$accountDetails", @@ -16,7 +16,7 @@ }, { "text": "$entityTypeUC", - "margin": [8, 50, 8, 5], + "margin": [8, 30, 8, 5], "style": "entityTypeLabel" }, @@ -70,17 +70,17 @@ } }, { - "columns": [ + "columns": [ "$notesAndTerms", { "table": { - "widths": ["*", "*"], + "widths": ["*", "auto"], "body": "$subtotals" }, "layout": { "hLineWidth": "$none", "vLineWidth": "$none", - "paddingLeft": "$amount:8", + "paddingLeft": "$amount:34", "paddingRight": "$amount:8", "paddingTop": "$amount:4", "paddingBottom": "$amount:4" @@ -97,12 +97,10 @@ "columns": [ { "text": "$invoiceFooter", - "alignment": "left", - "margin": [0, 0, 0, 12] - + "alignment": "left" } ], - "margin": [40, -20, 40, 40] + "margin": [40, -20, 40, 0] }, "styles": { "entityTypeLabel": { @@ -171,8 +169,7 @@ "alignment": "right" }, "termsLabel": { - "bold": true, - "margin": [0, 0, 0, 4] + "bold": true } }, "pageMargins": [40, 40, 40, 60] diff --git a/storage/templates/modern.js b/storage/templates/modern.js index 86c229db4536..8c1702138cba 100644 --- a/storage/templates/modern.js +++ b/storage/templates/modern.js @@ -4,7 +4,7 @@ "columns": [ { "image": "$accountLogo", - "width": 80, + "fit": [120, 80], "margin": [0, 60, 0, 30] }, { @@ -37,13 +37,13 @@ "$notesAndTerms", { "table": { - "widths": ["*", "*"], + "widths": ["*", "auto"], "body": "$subtotalsWithoutBalance" }, "layout": { "hLineWidth": "$none", "vLineWidth": "$none", - "paddingLeft": "$amount:8", + "paddingLeft": "$amount:34", "paddingRight": "$amount:8", "paddingTop": "$amount:4", "paddingBottom": "$amount:4" diff --git a/storage/templates/plain.js b/storage/templates/plain.js index bbcc7b6a1229..d412c9654f43 100644 --- a/storage/templates/plain.js +++ b/storage/templates/plain.js @@ -11,7 +11,7 @@ [ { "image": "$accountLogo", - "width": 100 + "fit": [120, 80] } ] ]}, @@ -66,13 +66,13 @@ { "style": "subtotals", "table": { - "widths": ["*", "*"], + "widths": ["*", "auto"], "body": "$subtotals" }, "layout": { "hLineWidth": "$none", "vLineWidth": "$none", - "paddingLeft": "$amount:8", + "paddingLeft": "$amount:34", "paddingRight": "$amount:8", "paddingTop": "$amount:4", "paddingBottom": "$amount:4" From 4fa4f650053f0b08da5d2b0d63f2673dd73fad1f Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Thu, 30 Jul 2015 17:44:47 +0300 Subject: [PATCH 04/16] Support updating invoices through the API --- .env.example | 4 +- app/Http/Controllers/AccountController.php | 22 ++-- app/Http/Controllers/AppController.php | 6 +- app/Http/Controllers/DashboardController.php | 2 +- app/Http/Controllers/HomeController.php | 2 +- app/Http/Controllers/InvoiceApiController.php | 20 ++-- app/Http/Controllers/InvoiceController.php | 6 +- app/Http/Controllers/PaymentController.php | 7 +- app/Http/Controllers/QuoteController.php | 5 +- app/Libraries/Utils.php | 18 ++- app/Models/Account.php | 45 ++++--- app/Models/Invoice.php | 2 +- app/Ninja/Mailers/UserMailer.php | 2 +- app/Ninja/Repositories/InvoiceRepository.php | 10 +- public/js/built.js | 111 +++++++++--------- public/js/pdf.pdfmake.js | 111 +++++++++--------- resources/lang/da/texts.php | 4 +- resources/lang/de/texts.php | 4 +- resources/lang/en/texts.php | 4 +- resources/lang/es/texts.php | 4 +- resources/lang/es_ES/texts.php | 4 +- resources/lang/fr/texts.php | 4 +- resources/lang/fr_CA/texts.php | 4 +- resources/lang/it/texts.php | 4 +- resources/lang/lt/texts.php | 4 +- resources/lang/nb_NO/texts.php | 4 +- resources/lang/nl/texts.php | 4 +- resources/lang/pt_BR/texts.php | 4 +- resources/lang/sv/texts.php | 4 +- resources/views/accounts/details.blade.php | 10 +- resources/views/auth/login.blade.php | 6 +- resources/views/header.blade.php | 6 +- resources/views/user_account.blade.php | 2 +- 33 files changed, 240 insertions(+), 209 deletions(-) diff --git a/.env.example b/.env.example index abc9da3a5254..643dda91d834 100644 --- a/.env.example +++ b/.env.example @@ -18,6 +18,4 @@ MAIL_HOST MAIL_USERNAME MAIL_FROM_ADDRESS MAIL_FROM_NAME -MAIL_PASSWORD - -ALLOW_NEW_ACCOUNTS \ No newline at end of file +MAIL_PASSWORD \ No newline at end of file diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index b781e41887d2..fea09ebf9f21 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -75,18 +75,18 @@ class AccountController extends BaseController public function getStarted() { - if (Auth::check()) { - return Redirect::to('invoices/create'); - } - - if (!Utils::isNinja() && !Utils::allowNewAccounts() && Account::count() > 0) { - return Redirect::to('/login'); - } - $user = false; $guestKey = Input::get('guest_key'); // local storage key to login until registered $prevUserId = Session::pull(PREV_USER_ID); // last user id used to link to new account + if (Auth::check()) { + return Redirect::to('invoices/create'); + } + + if (!Utils::isNinja() && (Account::count() > 0 && !$prevUserId)) { + return Redirect::to('/login'); + } + if ($guestKey && !$prevUserId) { $user = User::where('password', '=', $guestKey)->first(); @@ -149,6 +149,7 @@ class AccountController extends BaseController public function showSection($section = ACCOUNT_DETAILS, $subSection = false) { if ($section == ACCOUNT_DETAILS) { + $primaryUser = Auth::user()->account->users()->orderBy('id')->first(); $data = [ 'account' => Account::with('users')->findOrFail(Auth::user()->account_id), 'countries' => Cache::get('countries'), @@ -159,8 +160,9 @@ class AccountController extends BaseController 'datetimeFormats' => Cache::get('datetimeFormats'), 'currencies' => Cache::get('currencies'), 'languages' => Cache::get('languages'), - 'showUser' => Auth::user()->id === Auth::user()->account->users()->first()->id, + 'showUser' => Auth::user()->id === $primaryUser->id, 'title' => trans('texts.company_details'), + 'primaryUser' => $primaryUser, ]; return View::make('accounts.details', $data); @@ -639,7 +641,7 @@ class AccountController extends BaseController 'name' => 'required', ); - $user = Auth::user()->account->users()->first(); + $user = Auth::user()->account->users()->orderBy('id')->first(); if (Auth::user()->id === $user->id) { $rules['email'] = 'email|required|unique:users,email,'.$user->id.',id'; diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php index 91d716cf253d..b135c045053e 100644 --- a/app/Http/Controllers/AppController.php +++ b/app/Http/Controllers/AppController.php @@ -88,9 +88,7 @@ class AppController extends BaseController "MAIL_HOST={$mail['host']}\n". "MAIL_USERNAME={$mail['username']}\n". "MAIL_FROM_NAME={$mail['from']['name']}\n". - "MAIL_PASSWORD={$mail['password']}\n\n". - "ADMIN_USER_ID=1\n". - "ALLOW_NEW_ACCOUNTS\n"; + "MAIL_PASSWORD={$mail['password']}"; // Write Config Settings $fp = fopen(base_path()."/.env", 'w'); @@ -178,7 +176,7 @@ class AppController extends BaseController public function update() { - if (!Utils::isNinja()) { + if (!Utils::isNinja() && Auth::check()) { try { Artisan::call('migrate', array('--force' => true)); Artisan::call('db:seed', array('--force' => true, '--class' => 'PaymentLibrariesSeeder')); diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 292f09336be2..6ac4de2a4039 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -110,7 +110,7 @@ class DashboardController extends BaseController ->where('contacts.deleted_at', '=', null) ->where('contacts.is_primary', '=', true) ->select(['payments.payment_date', 'payments.amount', 'invoices.public_id', 'invoices.invoice_number', 'clients.name as client_name', 'contacts.email', 'contacts.first_name', 'contacts.last_name', 'clients.currency_id', 'clients.public_id as client_public_id']) - ->orderBy('payments.payment_date', 'asc') + ->orderBy('payments.id', 'desc') ->take(50) ->get(); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index a58245e0e25b..2645b0cbd98a 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -43,7 +43,7 @@ class HomeController extends BaseController public function invoiceNow() { - if (Auth::check() && Input::get('new_account')) { + if (Auth::check() && Input::get('new_company')) { Session::put(PREV_USER_ID, Auth::user()->id); Auth::user()->clearSession(); Auth::logout(); diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php index 43911db7d8c3..02fb8e19bf9a 100644 --- a/app/Http/Controllers/InvoiceApiController.php +++ b/app/Http/Controllers/InvoiceApiController.php @@ -50,12 +50,14 @@ class InvoiceApiController extends Controller $error = null; // check if the invoice number is set and unique - if (!isset($data['invoice_number'])) { + if (!isset($data['invoice_number']) && !isset($data['id'])) { $data['invoice_number'] = Auth::user()->account->getNextInvoiceNumber(); - } else { + } else if (isset($data['invoice_number'])) { $invoice = Invoice::scope()->where('invoice_number', '=', $data['invoice_number'])->first(); if ($invoice) { $error = trans('validation.unique', ['attribute' => 'texts.invoice_number']); + } else { + $data['id'] = $invoice->public_id; } } @@ -98,13 +100,15 @@ class InvoiceApiController extends Controller } else { $data = self::prepareData($data); $data['client_id'] = $client->id; - $invoice = $this->invoiceRepo->save(false, $data, false); + $invoice = $this->invoiceRepo->save(isset($data['id']) ? $data['id'] : false, $data, false); - $invitation = Invitation::createNew(); - $invitation->invoice_id = $invoice->id; - $invitation->contact_id = $client->contacts[0]->id; - $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH); - $invitation->save(); + if (!isset($data['id'])) { + $invitation = Invitation::createNew(); + $invitation->invoice_id = $invoice->id; + $invitation->contact_id = $client->contacts[0]->id; + $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH); + $invitation->save(); + } if (isset($data['email_invoice']) && $data['email_invoice']) { $this->mailer->sendInvoice($invoice); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 1939ce9c65da..d93e67300bc9 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -86,11 +86,12 @@ class InvoiceController extends BaseController } $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first(); - $color = $invitation->account->primary_color ? $invitation->account->primary_color : '#0b4d78'; + $account = $invitation->account; + $color = $account->primary_color ? $account->primary_color : '#0b4d78'; $data = [ 'color' => $color, - 'hideLogo' => Session::get('white_label'), + 'hideLogo' => $account->isWhiteLabel(), 'title' => trans('texts.invoices'), 'entityType' => ENTITY_INVOICE, 'columns' => Utils::trans(['invoice_number', 'invoice_date', 'invoice_total', 'balance_due', 'due_date']), @@ -205,7 +206,6 @@ class InvoiceController extends BaseController Session::set($invitationKey, true); Session::set('invitation_key', $invitationKey); - Session::set('white_label', $account->isWhiteLabel()); $account->loadLocalizationSettings(); diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 8b70a780bdfe..4b63aabc695c 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -61,11 +61,12 @@ class PaymentController extends BaseController } $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first(); - $color = $invitation->account->primary_color ? $invitation->account->primary_color : '#0b4d78'; + $account = $invitation->account; + $color = $account->primary_color ? $account->primary_color : '#0b4d78'; $data = [ 'color' => $color, - 'hideLogo' => Session::get('white_label'), + 'hideLogo' => $account->isWhiteLabel(), 'entityType' => ENTITY_PAYMENT, 'title' => trans('texts.payments'), 'columns' => Utils::trans(['invoice', 'transaction_reference', 'method', 'payment_amount', 'payment_date']) @@ -336,7 +337,7 @@ class PaymentController extends BaseController 'acceptedCreditCardTypes' => $acceptedCreditCardTypes, 'countries' => Cache::get('countries'), 'currencyId' => $client->getCurrencyId(), - 'currencyCode' => $client->currency->code, + 'currencyCode' => $client->currency ? $client->currency->code : ($account->currency ? $account->currency->code : 'USD'), 'account' => $client->account, 'hideLogo' => $account->isWhiteLabel(), 'showAddress' => $accountGateway->show_address, diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index b8dfd095e44b..bb8526c424e9 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -75,11 +75,12 @@ class QuoteController extends BaseController } $invitation = Invitation::with('account')->where('invitation_key', '=', $invitationKey)->first(); - $color = $invitation->account->primary_color ? $invitation->account->primary_color : '#0b4d78'; + $account = $invitation->account; + $color = $account->primary_color ? $account->primary_color : '#0b4d78'; $data = [ 'color' => $color, - 'hideLogo' => Session::get('white_label'), + 'hideLogo' => $account->isWhiteLabel(), 'title' => trans('texts.quotes'), 'entityType' => ENTITY_QUOTE, 'columns' => Utils::trans(['quote_number', 'quote_date', 'quote_total', 'due_date']), diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index 184dd453e498..b38911371476 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -61,7 +61,7 @@ class Utils public static function allowNewAccounts() { - return Utils::isNinja() || (isset($_ENV['ALLOW_NEW_ACCOUNTS']) && $_ENV['ALLOW_NEW_ACCOUNTS'] == 'true'); + return Utils::isNinja() || Auth::check(); } public static function isPro() @@ -400,10 +400,12 @@ class Utils } $object = new stdClass(); + $object->accountId = Auth::user()->account_id; $object->url = $url; $object->name = ucwords($type).': '.$name; $data = []; + $counts = []; for ($i = 0; $iaccountId])) { + $counts[$item->accountId]++; + } else { + $counts[$item->accountId] = 1; + } } array_unshift($data, $object); - - if (count($data) > RECENTLY_VIEWED_LIMIT) { + + if (isset($counts[Auth::user()->account_id]) && $counts[Auth::user()->account_id] > RECENTLY_VIEWED_LIMIT) { array_pop($data); } diff --git a/app/Models/Account.php b/app/Models/Account.php index 10ba19d99ecd..5def5c6a999c 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -176,37 +176,36 @@ class Account extends Eloquent { $counter = $isQuote && !$this->share_counter ? $this->quote_number_counter : $this->invoice_number_counter; $prefix .= $isQuote ? $this->quote_number_prefix : $this->invoice_number_prefix; - + $counterOffset = 0; + // confirm the invoice number isn't already taken do { $number = $prefix.str_pad($counter, 4, "0", STR_PAD_LEFT); $check = Invoice::scope(false, $this->id)->whereInvoiceNumber($number)->withTrashed()->first(); $counter++; + $counterOffset++; } while ($check); + // update the invoice counter to be caught up + if ($counterOffset > 1) { + if ($isQuote && !$this->share_counter) { + $this->quote_number_counter += $counterOffset - 1; + } else { + $this->invoice_number_counter += $counterOffset - 1; + } + + $this->save(); + } + return $number; } - public function incrementCounter($invoiceNumber, $isQuote = false, $isRecurring) + public function incrementCounter($isQuote = false) { - // check if the user modified the invoice number - if (!$isRecurring && $invoiceNumber != $this->getNextInvoiceNumber($isQuote)) { - // remove the prefix - $prefix = $isQuote ? $this->quote_number_prefix : $this->invoice_number_prefix; - $invoiceNumber = preg_replace('/^'.$prefix.'/', '', $invoiceNumber); - $invoiceNumber = intval(preg_replace('/[^0-9]/', '', $invoiceNumber)); - if ($isQuote && !$this->share_counter) { - $this->quote_number_counter = $invoiceNumber + 1; - } else { - $this->invoice_number_counter = $invoiceNumber + 1; - } - // otherwise, just increment the counter + if ($isQuote && !$this->share_counter) { + $this->quote_number_counter += 1; } else { - if ($isQuote && !$this->share_counter) { - $this->quote_number_counter += 1; - } else { - $this->invoice_number_counter += 1; - } + $this->invoice_number_counter += 1; } $this->save(); @@ -315,11 +314,11 @@ class Account extends Eloquent public function isWhiteLabel() { - if (Utils::isNinjaProd()) { - return false; + if (Utils::isNinja()) { + return self::isPro(); + } else { + return $this->pro_plan_paid == NINJA_DATE; } - - return $this->pro_plan_paid == NINJA_DATE; } public function getSubscription($eventId) diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index a1f01a5b5040..63700410fa18 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -258,7 +258,7 @@ class Invoice extends EntityModel } Invoice::creating(function ($invoice) { - $invoice->account->incrementCounter($invoice->invoice_number, $invoice->is_quote, $invoice->recurring_invoice_id); + $invoice->account->incrementCounter($invoice->is_quote); }); Invoice::created(function ($invoice) { diff --git a/app/Ninja/Mailers/UserMailer.php b/app/Ninja/Mailers/UserMailer.php index 710e436c11e8..3f2b4290a7eb 100644 --- a/app/Ninja/Mailers/UserMailer.php +++ b/app/Ninja/Mailers/UserMailer.php @@ -47,7 +47,7 @@ class UserMailer extends Mailer 'clientName' => $invoice->client->getDisplayName(), 'accountName' => $invoice->account->getDisplayName(), 'userName' => $user->getDisplayName(), - 'invoiceAmount' => Utils::formatMoney($invoice->amount, $invoice->client->getCurrencyId()), + 'invoiceAmount' => Utils::formatMoney($invoice->getRequestedAmount(), $invoice->client->getCurrencyId()), 'invoiceNumber' => $invoice->invoice_number, 'invoiceLink' => SITE_URL."/{$entityType}s/{$invoice->public_id}", ]; diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index ce0397d64b4d..0d3b2e8ce565 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -266,15 +266,18 @@ class InvoiceRepository $account->save(); } - $invoice->client_id = $data['client_id']; + if (isset($data['invoice_number'])) { + $invoice->invoice_number = trim($data['invoice_number']); + } + $invoice->discount = round(Utils::parseFloat($data['discount']), 2); $invoice->is_amount_discount = $data['is_amount_discount'] ? true : false; - $invoice->invoice_number = trim($data['invoice_number']); $invoice->partial = round(Utils::parseFloat($data['partial']), 2); $invoice->invoice_date = isset($data['invoice_date_sql']) ? $data['invoice_date_sql'] : Utils::toSqlDate($data['invoice_date']); $invoice->has_tasks = isset($data['has_tasks']) ? $data['has_tasks'] : false; if (!$publicId) { + $invoice->client_id = $data['client_id']; $invoice->is_recurring = $data['is_recurring'] && !Utils::isDemo() ? true : false; } @@ -543,8 +546,9 @@ class InvoiceRepository ->whereClientId($clientId) ->whereIsQuote(false) ->whereIsRecurring(false) + ->whereDeletedAt(null) ->whereHasTasks(true) - ->where('balance', '>', 0) + ->where('invoice_status_id', '<', 5) ->select(['public_id', 'invoice_number']) ->get(); } diff --git a/public/js/built.js b/public/js/built.js index fc0fa403d399..0a22d2a5a35e 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -31599,7 +31599,10 @@ NINJA.decodeJavascript = function(invoice, javascript) field = match.substring(2, match.indexOf('Label')); field = toSnakeCase(field); var value = getDescendantProp(invoice, field); - if (match.indexOf('?') < 0) { + if (match.indexOf('?') < 0 || value) { + if (invoice.partial && field == 'balance_due') { + field = 'amount_due'; + } var label = invoiceLabels[field]; if (match.indexOf('UC') >= 0) { if (!label) console.log('match: ' + field); @@ -31663,14 +31666,14 @@ NINJA.invoiceColumns = function(invoice) NINJA.invoiceLines = function(invoice) { var grid = [ - [ - {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, - {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, - {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, - {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, - {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, - {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} - ] + [ + {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, + {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, + {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, + {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, + {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, + {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} + ] ]; var total = 0; @@ -31679,7 +31682,7 @@ NINJA.invoiceLines = function(invoice) { var hideQuantity = invoice.account.hide_quantity == '1'; for (var i = 0; i < invoice.invoice_items.length; i++) { - + var row = []; var item = invoice.invoice_items[i]; var cost = formatMoney(item.cost, currencyId, true); @@ -31767,16 +31770,17 @@ NINJA.subtotals = function(invoice, removeBalance) data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); } - var paid = invoice.amount - invoice.balance; + var paid = invoice.amount - invoice.balance; if (invoice.account.hide_paid_to_date != '1' || paid) { data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoney(paid, invoice.client.currency_id)}]); } if (!removeBalance) { + var isPartial = NINJA.parseFloat(invoice.partial); data.push([ - {text:invoice.is_quote ? invoiceLabels.balance_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, - {text:formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} - ]); + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, + {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} + ]); } return NINJA.prepareDataPairs(data, 'subtotals'); @@ -31785,11 +31789,11 @@ NINJA.subtotals = function(invoice, removeBalance) NINJA.accountDetails = function(invoice) { var account = invoice.account; var data = [ - {text:account.name, style: ['accountName']}, - {text:account.id_number}, - {text:account.vat_number}, - {text:account.work_email}, - {text:account.work_phone} + {text:account.name, style: ['accountName']}, + {text:account.id_number}, + {text:account.vat_number}, + {text:account.work_email}, + {text:account.work_phone} ]; return NINJA.prepareDataList(data, 'accountDetails'); } @@ -31801,11 +31805,11 @@ NINJA.accountAddress = function(invoice) { cityStatePostal = ((account.city ? account.city + ', ' : '') + account.state + ' ' + account.postal_code).trim(); } - var data = [ - {text: account.address1}, - {text: account.address2}, - {text: cityStatePostal}, - {text: account.country ? account.country.name : ''} + var data = [ + {text: account.address1}, + {text: account.address2}, + {text: cityStatePostal}, + {text: account.country ? account.country.name : ''} ]; return NINJA.prepareDataList(data, 'accountAddress'); @@ -31814,42 +31818,43 @@ NINJA.accountAddress = function(invoice) { NINJA.invoiceDetails = function(invoice) { var data = [ - [ - {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, - {text: invoice.invoice_number, style: ['invoiceNumber']} - ], - [ - {text: invoiceLabels.po_number}, - {text: invoice.po_number} - ], - [ - {text: invoiceLabels.invoice_date}, - {text: invoice.invoice_date} - ], - [ - {text: invoiceLabels.due_date}, - {text: invoice.due_date} - ] + [ + {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, + {text: invoice.invoice_number, style: ['invoiceNumber']} + ], + [ + {text: invoiceLabels.po_number}, + {text: invoice.po_number} + ], + [ + {text: (invoice.is_quote ? invoiceLabels.quote_date : invoiceLabels.invoice_date)}, + {text: invoice.invoice_date} + ], + [ + {text: invoiceLabels.due_date}, + {text: invoice.due_date} + ] ]; + + var isPartial = NINJA.parseFloat(invoice.partial); + if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) { data.push([ {text: invoiceLabels.total}, {text: formatMoney(invoice.amount, invoice.client.currency_id)} - ]); - } - - if (NINJA.parseFloat(invoice.partial)) { + ]); + } else if (isPartial) { data.push([ - {text: invoiceLabels.balance}, + {text: invoiceLabels.total}, {text: formatMoney(invoice.total_amount, invoice.client.currency_id)} - ]); + ]); } data.push([ - {text: invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style: ['invoiceDetailBalanceDue']} - ]) + ]) return NINJA.prepareDataPairs(data, 'invoiceDetails'); } @@ -31865,11 +31870,11 @@ NINJA.clientDetails = function(invoice) { var clientEmail = client.contacts[0].email == clientName ? '' : client.contacts[0].email; data = [ - {text:clientName || ' ', style: ['clientName']}, - {text:client.address1}, - {text:concatStrings(client.city, client.state, client.postal_code)}, - {text:client.country ? client.country.name : ''}, - {text:clientEmail} + {text:clientName || ' ', style: ['clientName']}, + {text:client.address1}, + {text:concatStrings(client.city, client.state, client.postal_code)}, + {text:client.country ? client.country.name : ''}, + {text:clientEmail} ]; return NINJA.prepareDataList(data, 'clientDetails'); diff --git a/public/js/pdf.pdfmake.js b/public/js/pdf.pdfmake.js index ad7ad654067b..168a8733567b 100644 --- a/public/js/pdf.pdfmake.js +++ b/public/js/pdf.pdfmake.js @@ -122,7 +122,10 @@ NINJA.decodeJavascript = function(invoice, javascript) field = match.substring(2, match.indexOf('Label')); field = toSnakeCase(field); var value = getDescendantProp(invoice, field); - if (match.indexOf('?') < 0) { + if (match.indexOf('?') < 0 || value) { + if (invoice.partial && field == 'balance_due') { + field = 'amount_due'; + } var label = invoiceLabels[field]; if (match.indexOf('UC') >= 0) { if (!label) console.log('match: ' + field); @@ -186,14 +189,14 @@ NINJA.invoiceColumns = function(invoice) NINJA.invoiceLines = function(invoice) { var grid = [ - [ - {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, - {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, - {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, - {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, - {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, - {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} - ] + [ + {text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']}, + {text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']}, + {text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}, + {text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']}, + {text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']}, + {text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']} + ] ]; var total = 0; @@ -202,7 +205,7 @@ NINJA.invoiceLines = function(invoice) { var hideQuantity = invoice.account.hide_quantity == '1'; for (var i = 0; i < invoice.invoice_items.length; i++) { - + var row = []; var item = invoice.invoice_items[i]; var cost = formatMoney(item.cost, currencyId, true); @@ -290,16 +293,17 @@ NINJA.subtotals = function(invoice, removeBalance) data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); } - var paid = invoice.amount - invoice.balance; + var paid = invoice.amount - invoice.balance; if (invoice.account.hide_paid_to_date != '1' || paid) { data.push([{text:invoiceLabels.paid_to_date}, {text:formatMoney(paid, invoice.client.currency_id)}]); } if (!removeBalance) { + var isPartial = NINJA.parseFloat(invoice.partial); data.push([ - {text:invoice.is_quote ? invoiceLabels.balance_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, - {text:formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} - ]); + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style:['balanceDueLabel']}, + {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style:['balanceDue']} + ]); } return NINJA.prepareDataPairs(data, 'subtotals'); @@ -308,11 +312,11 @@ NINJA.subtotals = function(invoice, removeBalance) NINJA.accountDetails = function(invoice) { var account = invoice.account; var data = [ - {text:account.name, style: ['accountName']}, - {text:account.id_number}, - {text:account.vat_number}, - {text:account.work_email}, - {text:account.work_phone} + {text:account.name, style: ['accountName']}, + {text:account.id_number}, + {text:account.vat_number}, + {text:account.work_email}, + {text:account.work_phone} ]; return NINJA.prepareDataList(data, 'accountDetails'); } @@ -324,11 +328,11 @@ NINJA.accountAddress = function(invoice) { cityStatePostal = ((account.city ? account.city + ', ' : '') + account.state + ' ' + account.postal_code).trim(); } - var data = [ - {text: account.address1}, - {text: account.address2}, - {text: cityStatePostal}, - {text: account.country ? account.country.name : ''} + var data = [ + {text: account.address1}, + {text: account.address2}, + {text: cityStatePostal}, + {text: account.country ? account.country.name : ''} ]; return NINJA.prepareDataList(data, 'accountAddress'); @@ -337,42 +341,43 @@ NINJA.accountAddress = function(invoice) { NINJA.invoiceDetails = function(invoice) { var data = [ - [ - {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, - {text: invoice.invoice_number, style: ['invoiceNumber']} - ], - [ - {text: invoiceLabels.po_number}, - {text: invoice.po_number} - ], - [ - {text: invoiceLabels.invoice_date}, - {text: invoice.invoice_date} - ], - [ - {text: invoiceLabels.due_date}, - {text: invoice.due_date} - ] + [ + {text: (invoice.is_quote ? invoiceLabels.quote_number : invoiceLabels.invoice_number), style: ['invoiceNumberLabel']}, + {text: invoice.invoice_number, style: ['invoiceNumber']} + ], + [ + {text: invoiceLabels.po_number}, + {text: invoice.po_number} + ], + [ + {text: (invoice.is_quote ? invoiceLabels.quote_date : invoiceLabels.invoice_date)}, + {text: invoice.invoice_date} + ], + [ + {text: invoiceLabels.due_date}, + {text: invoice.due_date} + ] ]; + + var isPartial = NINJA.parseFloat(invoice.partial); + if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) { data.push([ {text: invoiceLabels.total}, {text: formatMoney(invoice.amount, invoice.client.currency_id)} - ]); - } - - if (NINJA.parseFloat(invoice.partial)) { + ]); + } else if (isPartial) { data.push([ - {text: invoiceLabels.balance}, + {text: invoiceLabels.total}, {text: formatMoney(invoice.total_amount, invoice.client.currency_id)} - ]); + ]); } data.push([ - {text: invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, + {text: isPartial ? invoiceLabels.amount_due : invoiceLabels.balance_due, style: ['invoiceDetailBalanceDueLabel']}, {text: formatMoney(invoice.balance_amount, invoice.client.currency_id), style: ['invoiceDetailBalanceDue']} - ]) + ]) return NINJA.prepareDataPairs(data, 'invoiceDetails'); } @@ -388,11 +393,11 @@ NINJA.clientDetails = function(invoice) { var clientEmail = client.contacts[0].email == clientName ? '' : client.contacts[0].email; data = [ - {text:clientName || ' ', style: ['clientName']}, - {text:client.address1}, - {text:concatStrings(client.city, client.state, client.postal_code)}, - {text:client.country ? client.country.name : ''}, - {text:clientEmail} + {text:clientName || ' ', style: ['clientName']}, + {text:client.address1}, + {text:concatStrings(client.city, client.state, client.postal_code)}, + {text:client.country ? client.country.name : ''}, + {text:clientEmail} ]; return NINJA.prepareDataList(data, 'clientDetails'); diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 429d778ca2e1..5a5b73b03582 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -698,9 +698,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index e91162679c8b..03f8f773c770 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -688,9 +688,9 @@ return array( 'email_receipt' => 'Zahlungsbestätigung an Kunden per E-Mail senden', 'created_payment_emailed_client' => 'Zahlung erfolgreich erstellt und Kunde per E-Mail benachrichtigt', - 'add_account' => 'Konto hinzufügen', + 'add_company' => 'Konto hinzufügen', 'untitled' => 'Unbenannt', - 'new_account' => 'Neues Konto', + 'new_company' => 'Neues Konto', 'associated_accounts' => 'Konten erfolgreich verlinkt', 'unlinked_account' => 'Konten erfolgreich getrennt', 'login' => 'Login', diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 916aa7e40d5a..11092c957a16 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -696,9 +696,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index f5ecb6107543..aa0273a47042 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -668,9 +668,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php index d8677edff31e..df7ec3c92535 100644 --- a/resources/lang/es_ES/texts.php +++ b/resources/lang/es_ES/texts.php @@ -697,9 +697,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index bdbd4c505254..b401ea0d3076 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -689,9 +689,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Paiement crée avec succès et envoyé au client', - 'add_account' => 'Ajouter compte', + 'add_company' => 'Ajouter compte', 'untitled' => 'Sans titre', - 'new_account' => 'Nouveau compte', + 'new_company' => 'Nouveau compte', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Connexion', diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php index eaf88d318209..2300badc12b2 100644 --- a/resources/lang/fr_CA/texts.php +++ b/resources/lang/fr_CA/texts.php @@ -690,9 +690,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index b4cc4736638f..d12f6f2bcb94 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -692,9 +692,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index a507fa01a433..b57bdc7cfc25 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -699,9 +699,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index cda4b94fabff..18b88e16886e 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -697,9 +697,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index 5118ac4fdd9a..27778af2b948 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -692,9 +692,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index 0923299362e7..ea074e12d853 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -692,9 +692,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index 4ac8dfb42977..295f596832d4 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -695,9 +695,9 @@ return array( 'email_receipt' => 'Email payment receipt to the client', 'created_payment_emailed_client' => 'Successfully created payment and emailed client', - 'add_account' => 'Add Account', + 'add_company' => 'Add Company', 'untitled' => 'Untitled', - 'new_account' => 'New Account', + 'new_company' => 'New Company', 'associated_accounts' => 'Successfully linked accounts', 'unlinked_account' => 'Successfully unlinked accounts', 'login' => 'Login', diff --git a/resources/views/accounts/details.blade.php b/resources/views/accounts/details.blade.php index 90475d384b75..89a2a179f94b 100644 --- a/resources/views/accounts/details.blade.php +++ b/resources/views/accounts/details.blade.php @@ -18,12 +18,12 @@ {{ Former::populate($account) }} @if ($showUser) - {{ Former::populateField('first_name', $account->users()->first()->first_name) }} - {{ Former::populateField('last_name', $account->users()->first()->last_name) }} - {{ Former::populateField('email', $account->users()->first()->email) }} - {{ Former::populateField('phone', $account->users()->first()->phone) }} + {{ Former::populateField('first_name', $primaryUser->first_name) }} + {{ Former::populateField('last_name', $primaryUser->last_name) }} + {{ Former::populateField('email', $primaryUser->email) }} + {{ Former::populateField('phone', $primaryUser->phone) }} @if (Utils::isNinja()) - {{ Former::populateField('dark_mode', intval($account->users()->first()->dark_mode)) }} + {{ Former::populateField('dark_mode', intval($primaryUser->dark_mode)) }} @endif @endif diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 76b315c84283..b3ac449db155 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -79,11 +79,11 @@ {!! Former::hidden('remember')->raw() !!}

-

{!! Button::success(trans(Input::get('new_account') && Utils::allowNewAccounts() ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}

+

{!! Button::success(trans(Input::get('new_company') ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}

- @if (Input::get('new_account') && Utils::allowNewAccounts()) + @if (Input::get('new_company') && Utils::allowNewAccounts())

- {{ trans('texts.or') }} -

-

{!! Button::primary(trans('texts.new_account'))->asLinkTo(URL::to('/invoice_now?new_account=true'))->large()->submit()->block() !!}

+

{!! Button::primary(trans('texts.new_company'))->asLinkTo(URL::to('/invoice_now?new_company=true&sign_up=true'))->large()->submit()->block() !!}

@endif diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php index 64d1e6df225b..cc8a1f0eb6d5 100644 --- a/resources/views/header.blade.php +++ b/resources/views/header.blade.php @@ -427,7 +427,7 @@ @endif
  • @if (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5) -
  • {!! link_to('/login?new_account=true', trans('texts.add_account')) !!}
  • +
  • {!! link_to('/login?new_company=true', trans('texts.add_company')) !!}
  • @endif
  • {!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}
  • @@ -462,7 +462,9 @@
  • {{ trans('texts.no_items') }}
  • @else @foreach (Session::get(RECENTLY_VIEWED) as $link) -
  • {{ $link->name }}
  • + @if (property_exists($link, 'accountId') && $link->accountId == Auth::user()->account_id) +
  • {{ $link->name }}
  • + @endif @endforeach @endif diff --git a/resources/views/user_account.blade.php b/resources/views/user_account.blade.php index c3c2520aee0e..e9aad6d6abb0 100644 --- a/resources/views/user_account.blade.php +++ b/resources/views/user_account.blade.php @@ -6,7 +6,7 @@ @endif @if (isset($show_remove) && $show_remove) -
    +
    @endif @if (file_exists('logo/'.$account_key.'.jpg')) From 33364d3d9c69d788f9a7db4e604f53a1091204ec Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Thu, 30 Jul 2015 20:48:59 +0300 Subject: [PATCH 05/16] Bug fixes --- app/Http/Controllers/InvoiceApiController.php | 8 ++++++-- app/Http/Controllers/QuoteApiController.php | 6 +++++- app/Models/Activity.php | 2 ++ app/Ninja/Repositories/InvoiceRepository.php | 2 +- database/seeds/PaymentLibrariesSeeder.php | 10 ++++++++-- 5 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php index 02fb8e19bf9a..4c13259aecb2 100644 --- a/app/Http/Controllers/InvoiceApiController.php +++ b/app/Http/Controllers/InvoiceApiController.php @@ -26,7 +26,11 @@ class InvoiceApiController extends Controller public function index() { - $invoices = Invoice::scope()->with('client', 'invitations.account')->where('invoices.is_quote', '=', false)->orderBy('created_at', 'desc')->get(); + $invoices = Invoice::scope() + ->with('client', 'invitations.account') + ->where('invoices.is_quote', '=', false) + ->orderBy('created_at', 'desc') + ->get(); // Add the first invitation link to the data foreach ($invoices as $key => $invoice) { @@ -100,7 +104,7 @@ class InvoiceApiController extends Controller } else { $data = self::prepareData($data); $data['client_id'] = $client->id; - $invoice = $this->invoiceRepo->save(isset($data['id']) ? $data['id'] : false, $data, false); + $invoice = $this->invoiceRepo->save(false, $data, false); if (!isset($data['id'])) { $invitation = Invitation::createNew(); diff --git a/app/Http/Controllers/QuoteApiController.php b/app/Http/Controllers/QuoteApiController.php index 70257644c544..83e5e8781179 100644 --- a/app/Http/Controllers/QuoteApiController.php +++ b/app/Http/Controllers/QuoteApiController.php @@ -16,7 +16,11 @@ class QuoteApiController extends Controller public function index() { - $invoices = Invoice::scope()->with('client', 'user')->where('invoices.is_quote', '=', true)->orderBy('created_at', 'desc')->get(); + $invoices = Invoice::scope() + ->with('client', 'user') + ->where('invoices.is_quote', '=', true) + ->orderBy('created_at', 'desc') + ->get(); $invoices = Utils::remapPublicIds($invoices); $response = json_encode($invoices, JSON_PRETTY_PRINT); diff --git a/app/Models/Activity.php b/app/Models/Activity.php index 5997412ebf2b..0dd5ec54bf37 100644 --- a/app/Models/Activity.php +++ b/app/Models/Activity.php @@ -214,6 +214,8 @@ class Activity extends Eloquent if ($invoice->isPaid() && $invoice->balance > 0) { $invoice->invoice_status_id = INVOICE_STATUS_PARTIAL; + } elseif ($invoice->invoice_status_id && $invoice->balance == 0) { + $invoice->invoice_status_id = INVOICE_STATUS_PAID; } } } diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index 0d3b2e8ce565..e93ea47826bb 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -390,7 +390,7 @@ class InvoiceRepository $task->invoice_id = $invoice->id; $task->client_id = $invoice->client_id; $task->save(); - } else if ($item['product_key']) { + } else if ($item['product_key'] && !$invoice->has_tasks) { $product = Product::findProductByKey(trim($item['product_key'])); if (!$product) { diff --git a/database/seeds/PaymentLibrariesSeeder.php b/database/seeds/PaymentLibrariesSeeder.php index 73eb34c0e438..9e9af179cb2b 100644 --- a/database/seeds/PaymentLibrariesSeeder.php +++ b/database/seeds/PaymentLibrariesSeeder.php @@ -64,7 +64,7 @@ class PaymentLibrariesSeeder extends Seeder ['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], @@ -82,10 +82,16 @@ class PaymentLibrariesSeeder extends Seeder ['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ['name' => 'Thai baht', 'code' => 'THB', 'symbol' => 'THB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => 'NGN ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], ]; foreach ($currencies as $currency) { - if (!DB::table('currencies')->whereName($currency['name'])->get()) { + $record = Currency::whereCode($currency['code'])->first(); + if ($record) { + $record->name = $currency['name']; + $record->save(); + } else { Currency::create($currency); } } From 859b878965a3dfbb18cf9a47d445edcda4937174 Mon Sep 17 00:00:00 2001 From: Linus Metzler Date: Sun, 2 Aug 2015 17:28:32 +0200 Subject: [PATCH 06/16] updated German translations --- resources/lang/de/texts.php | 69 +++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index 03f8f773c770..280580e8e50c 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -696,40 +696,43 @@ return array( 'login' => 'Login', 'or' => 'oder', - 'email_error' => 'There was a problem sending the email', - 'created_by_recurring' => 'Created by recurring invoice :invoice', - 'confirm_recurring_timing' => 'Note: emails are sent at the start of the hour.', - 'old_browser' => 'Please use a newer browser', - 'payment_terms_help' => 'Sets the default invoice due date', - 'unlink_account' => 'Unlink Account', - 'unlink' => 'Unlink', - 'show_address' => 'Show Address', - 'show_address_help' => 'Require client to provide their billing address', - 'update_address' => 'Update Address', - 'update_address_help' => 'Update client\'s address with provided details', - 'times' => 'Times', - 'set_now' => 'Set now', - 'dark_mode' => 'Dark Mode', - 'dark_mode_help' => 'Show white text on black background', - 'add_to_invoice' => 'Add to invoice :invoice', - 'create_new_invoice' => 'Create new invoice', - 'task_errors' => 'Please correct any overlapping times', - 'utf8_invoices' => 'New PDF Engine Beta', - 'from' => 'From', - 'to' => 'To', - 'font_size' => 'Font Size', - 'primary_color' => 'Primary Color', - 'secondary_color' => 'Secondary Color', - 'customize_design' => 'Customize Design', + 'email_error' => 'Es gab ein Problem beim Senden dieses E-Mails.', + 'created_by_recurring' => 'Erzeugt durch die wiederkehrende Rechnung :invoice', + 'confirm_recurring_timing' => 'Beachten Sie: E-Mails werden zu Beginn der Stunde gesendet.', + 'old_browser' => 'Bitte verwenden Sie einen neueren Browser', + 'payment_terms_help' => 'Setzt das Standardfälligkeitssdatum', + 'unlink_account' => 'Konten Trennen', + 'unlink' => 'Trennen', + 'show_address' => 'Adresse Anzeigen', + 'show_address_help' => 'Verlange von Kunden ihre Rechnungsadresse anzugeben', + 'update_address' => 'Adresse Aktualisieren', + 'update_address_help' => 'Kundenadresse mit den gemachten Angaben aktualisieren', + 'times' => 'Zeiten', + 'set_now' => 'Jetzt setzen', + 'dark_mode' => 'Dunkler Modus', + 'dark_mode_help' => 'Weisser Text auf schwarzem Hintergrund anzeigen', + 'add_to_invoice' => 'Zur Rechnung :invoice hinzufügen', + 'create_new_invoice' => 'Neue Rechnung erstellen', + 'task_errors' => 'Bitte korrigieren Sie alle überlappenden Zeiten', + 'utf8_invoices' => 'Neue PDF Engine Beta', + 'from' => 'Von', + 'to' => 'An', + 'font_size' => 'Schriftgrösse', + 'primary_color' => 'Primäre Farbe', + 'secondary_color' => 'Sekundäre Farbe', + 'customize_design' => 'Design Anpassen', - 'content' => 'Content', - 'styles' => 'Styles', - 'defaults' => 'Defaults', - 'margins' => 'Margins', - 'header' => 'Header', - 'footer' => 'Footer', - 'custom' => 'Custom', - + 'content' => 'Inhalt', + 'styles' => 'Stile', + 'defaults' => 'Standards', + 'margins' => 'Aussenabstände', + 'header' => 'Kopfzeile', + 'footer' => 'Fusszeile', + 'custom' => 'Benutzerdefiniert', + 'invoice_to' => 'Rechnunge an', + 'invoice_no' => 'Rechnung Nr.', + 'recent_payments' => 'Kürzliche Zahlungen', + 'outstanding' => 'Ausstehend', ); \ No newline at end of file From 559a7d8a460c7b6b8f5e9bcef2f30fd8a570bf78 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 3 Aug 2015 10:15:58 +0300 Subject: [PATCH 07/16] Moved unlink to separate page --- app/Http/Controllers/AccountController.php | 1 + app/Http/Controllers/InvoiceController.php | 3 +- app/Http/Controllers/PaymentController.php | 23 +++---- app/Http/Controllers/UserController.php | 11 +++- app/Http/routes.php | 5 +- app/Models/Account.php | 2 +- resources/lang/da/texts.php | 6 ++ resources/lang/de/texts.php | 3 +- resources/lang/en/texts.php | 3 +- resources/lang/es/texts.php | 6 ++ resources/lang/es_ES/texts.php | 6 ++ resources/lang/fr/texts.php | 6 ++ resources/lang/fr_CA/texts.php | 6 ++ resources/lang/it/texts.php | 6 ++ resources/lang/lt/texts.php | 6 ++ resources/lang/nb_NO/texts.php | 6 ++ resources/lang/nl/texts.php | 6 ++ resources/lang/pt_BR/texts.php | 6 ++ resources/lang/sv/texts.php | 6 ++ resources/views/header.blade.php | 42 ++----------- resources/views/user_account.blade.php | 10 +-- .../views/users/account_management.blade.php | 62 +++++++++++++++++++ 22 files changed, 168 insertions(+), 63 deletions(-) create mode 100644 resources/views/users/account_management.blade.php diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index fea09ebf9f21..42737940bbe8 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -639,6 +639,7 @@ class AccountController extends BaseController { $rules = array( 'name' => 'required', + 'logo' => 'sometimes|max:1024|mimes:jpeg,gif,png', ); $user = Auth::user()->account->users()->orderBy('id')->first(); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index d93e67300bc9..248b1be6bef3 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -60,8 +60,7 @@ class InvoiceController extends BaseController 'columns' => Utils::trans(['checkbox', 'invoice_number', 'client', 'invoice_date', 'invoice_total', 'balance_due', 'due_date', 'status', 'action']), ]; - $recurringInvoices = Invoice::scope() - ->where('is_recurring', '=', true); + $recurringInvoices = Invoice::scope()->where('is_recurring', '=', true); if (Session::get('show_trash:invoice')) { $recurringInvoices->withTrashed(); diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 4b63aabc695c..6632ce843b3b 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -543,18 +543,19 @@ class PaymentController extends BaseController ->withErrors($validator) ->withInput(); } + + + if ($accountGateway->update_address) { + $client->address1 = trim(Input::get('address1')); + $client->address2 = trim(Input::get('address2')); + $client->city = trim(Input::get('city')); + $client->state = trim(Input::get('state')); + $client->postal_code = trim(Input::get('postal_code')); + $client->country_id = Input::get('country_id'); + $client->save(); + } } - - if ($onSite && $accountGateway->update_address) { - $client->address1 = trim(Input::get('address1')); - $client->address2 = trim(Input::get('address2')); - $client->city = trim(Input::get('city')); - $client->state = trim(Input::get('state')); - $client->postal_code = trim(Input::get('postal_code')); - $client->country_id = Input::get('country_id'); - $client->save(); - } - + try { $gateway = self::createGateway($accountGateway); $details = self::getPaymentDetails($invitation, ($useToken || !$onSite) ? false : Input::all()); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index d90c821414e1..50b66b69f720 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -377,6 +377,15 @@ class UserController extends BaseController Session::put(SESSION_USER_ACCOUNTS, $users); Session::flash('message', trans('texts.unlinked_account')); - return Redirect::to($referer); + return Redirect::to('/dashboard'); + } + + public function manageCompanies() + { + $data = [ + + ]; + + return View::make('users.account_management', $data); } } diff --git a/app/Http/routes.php b/app/Http/routes.php index 156e66ea6573..e016e3841c09 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,5 +1,7 @@ 'auth'], function() { Route::post('users/change_password', 'UserController@changePassword'); Route::get('/switch_account/{user_id}', 'UserController@switchAccount'); Route::get('/unlink_account/{user_account_id}/{user_id}', 'UserController@unlinkAccount'); + Route::get('/manage_companies', 'UserController@manageCompanies'); Route::get('api/tokens', array('as'=>'api.tokens', 'uses'=>'TokenController@getDatatable')); Route::resource('tokens', 'TokenController'); @@ -363,7 +366,7 @@ define('NINJA_GATEWAY_ID', GATEWAY_STRIPE); define('NINJA_GATEWAY_CONFIG', ''); define('NINJA_WEB_URL', 'https://www.invoiceninja.com'); define('NINJA_APP_URL', 'https://app.invoiceninja.com'); -define('NINJA_VERSION', '2.2.2'); +define('NINJA_VERSION', '2.3.0'); define('NINJA_DATE', '2000-01-01'); define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com'); diff --git a/app/Models/Account.php b/app/Models/Account.php index 5def5c6a999c..be307f6ca775 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -315,7 +315,7 @@ class Account extends Eloquent public function isWhiteLabel() { if (Utils::isNinja()) { - return self::isPro(); + return self::isPro() && $this->pro_plan_paid != NINJA_DATE; } else { return $this->pro_plan_paid == NINJA_DATE; } diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 5a5b73b03582..580e366e7298 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -738,6 +738,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index 280580e8e50c..7519119b40d6 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -732,7 +732,8 @@ return array( 'invoice_to' => 'Rechnunge an', 'invoice_no' => 'Rechnung Nr.', 'recent_payments' => 'Kürzliche Zahlungen', - 'outstanding' => 'Ausstehend', + 'manage_companies' => 'Manage Companies', + ); \ No newline at end of file diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 11092c957a16..b9807c4c93b4 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -740,7 +740,8 @@ return array( 'invoice_no' => 'Invoice No.', 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', - + 'manage_companies' => 'Manage Companies', + ); diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index aa0273a47042..92ca314723b6 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -708,6 +708,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + ); \ No newline at end of file diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php index df7ec3c92535..97b333fbb2c2 100644 --- a/resources/lang/es_ES/texts.php +++ b/resources/lang/es_ES/texts.php @@ -737,6 +737,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index b401ea0d3076..6fd60e17c4ba 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -729,6 +729,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php index 2300badc12b2..0c0bf2e3a4a2 100644 --- a/resources/lang/fr_CA/texts.php +++ b/resources/lang/fr_CA/texts.php @@ -730,6 +730,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + ); diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index d12f6f2bcb94..9672b9ea533d 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -732,6 +732,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index b57bdc7cfc25..15ca60fcba36 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -739,6 +739,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index 18b88e16886e..c014c917637c 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -737,6 +737,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index 27778af2b948..f82175f36ad9 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -732,6 +732,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index ea074e12d853..875691412797 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -732,6 +732,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + ); diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index 295f596832d4..13e443f81bdc 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -735,6 +735,12 @@ return array( 'header' => 'Header', 'footer' => 'Footer', 'custom' => 'Custom', + 'invoice_to' => 'Invoice to', + 'invoice_no' => 'Invoice No.', + 'recent_payments' => 'Recent Payments', + 'outstanding' => 'Outstanding', + 'manage_companies' => 'Manage Companies', + diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php index cc8a1f0eb6d5..e42e71f27574 100644 --- a/resources/views/header.blade.php +++ b/resources/views/header.blade.php @@ -203,19 +203,6 @@ }); } - function showUnlink(userAccountId, userId) { - NINJA.unlink = { - 'userAccountId': userAccountId, - 'userId': userId - }; - $('#unlinkModal').modal('show'); - return false; - } - - function unlinkAccount() { - window.location = '{{ URL::to('/unlink_account') }}' + '/' + NINJA.unlink.userAccountId + '/' + NINJA.unlink.userId; - } - function wordWrapText(value, width) { @if (Auth::user()->account->auto_wrap) @@ -389,7 +376,7 @@ -
    {{ trans('texts.invoice_number_short') }}
    {!! $invoice->getLink() !!}{{ $invoice->client->getDisplayName() }}{!! \App\Models\Invoice::calcLink($invoice) !!}{!! link_to('/clients/'.$invoice->client_public_id, trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email)) !!} {{ Utils::fromSqlDate($invoice->due_date) }}{{ Utils::formatMoney($invoice->balance, $invoice->client->getCurrencyId()) }}{{ Utils::formatMoney($invoice->balance, $invoice->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}
    + @foreach (Session::get(SESSION_USER_ACCOUNTS) as $account) + + + + + + @endforeach +
    {{ $account->account_name }}{{ $account->user_name }}{!! Button::primary(trans('texts.unlink'))->small()->withAttributes(['onclick'=>"return showUnlink({$account->id}, {$account->user_id})"]) !!}
    +
    +
    +
    +
    + + + + + + +@stop \ No newline at end of file From 5249e24fa26c9f1c1ca583dd6c2a1f167b52bbc6 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 3 Aug 2015 10:26:31 +0300 Subject: [PATCH 08/16] Git push --- app/Http/routes.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/routes.php b/app/Http/routes.php index e016e3841c09..dc58f5d14eb1 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -2,6 +2,7 @@ //dd("We're currently undergoing a brief maintenance, we'll be right back."); + /* |-------------------------------------------------------------------------- | Application Routes From 29e90cae0b29616663cbd9d5492759cd5b4c3d83 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 3 Aug 2015 11:02:35 +0300 Subject: [PATCH 09/16] Minor fix --- app/Http/Middleware/StartupCheck.php | 2 +- app/Http/routes.php | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/app/Http/Middleware/StartupCheck.php b/app/Http/Middleware/StartupCheck.php index a6c2741977c8..a0b7fd2b1d09 100644 --- a/app/Http/Middleware/StartupCheck.php +++ b/app/Http/Middleware/StartupCheck.php @@ -158,7 +158,7 @@ class StartupCheck } } - if (preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) { + if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) { Session::flash('error', trans('texts.old_browser')); } diff --git a/app/Http/routes.php b/app/Http/routes.php index dc58f5d14eb1..a9c322632db0 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,8 +1,5 @@ Date: Mon, 3 Aug 2015 11:52:47 +0300 Subject: [PATCH 10/16] Disabled datepicker localization --- app/Http/Controllers/PaymentController.php | 1 + resources/views/master.blade.php | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 6632ce843b3b..712f19dce6c5 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -389,6 +389,7 @@ class PaymentController extends BaseController 'currencyId' => 1, 'paymentTitle' => $affiliate->payment_title, 'paymentSubtitle' => $affiliate->payment_subtitle, + 'showAddress' => true, ]; return View::make('payments.payment', $data); diff --git a/resources/views/master.blade.php b/resources/views/master.blade.php index 59a486405da7..b9dec31654c2 100644 --- a/resources/views/master.blade.php +++ b/resources/views/master.blade.php @@ -53,10 +53,13 @@ 'sSearch': '' } } ); - + + /* $.extend( true, $.fn.datepicker.defaults, { language:'{{App::getLocale()}}' }); + */ + From 4b7d14363038ea62b7144b24909753e38b570515 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 3 Aug 2015 22:08:07 +0300 Subject: [PATCH 11/16] Minor fixes --- app/Http/Controllers/Auth/AuthController.php | 2 +- app/Http/Controllers/UserController.php | 6 +----- app/Libraries/Utils.php | 6 ++++++ app/Models/Account.php | 2 +- app/Ninja/Repositories/AccountRepository.php | 6 +++++- public/js/built.js | 2 +- public/js/script.js | 2 +- resources/views/accounts/details.blade.php | 2 +- resources/views/header.blade.php | 6 +++--- resources/views/invoices/edit.blade.php | 2 +- resources/views/user_account.blade.php | 2 +- 11 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php index e17135fe7146..a5897ac6879d 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/AuthController.php @@ -62,7 +62,7 @@ class AuthController extends Controller { $userId = Auth::check() ? Auth::user()->id : null; $user = User::where('email', '=', $request->input('email'))->first(); - if ($user->failed_logins >= 3) { + if ($user && $user->failed_logins >= 3) { Session::flash('error', 'These credentials do not match our records.'); return redirect()->to('login'); } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 50b66b69f720..85b4cede7d9a 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -382,10 +382,6 @@ class UserController extends BaseController public function manageCompanies() { - $data = [ - - ]; - - return View::make('users.account_management', $data); + return View::make('users.account_management'); } } diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index b38911371476..1efcf4b229a8 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -3,6 +3,7 @@ use Auth; use Cache; use DB; +use App; use Schema; use Session; use Request; @@ -69,6 +70,11 @@ class Utils return Auth::check() && Auth::user()->isPro(); } + public static function isEnglish() + { + return App::getLocale() == 'en'; + } + public static function getUserType() { if (Utils::isNinja()) { diff --git a/app/Models/Account.php b/app/Models/Account.php index be307f6ca775..e8cde5293c09 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -147,7 +147,7 @@ class Account extends Eloquent public function getLogoPath() { $fileName = 'logo/' . $this->account_key; - return file_exists($fileName.'.png') ? $fileName.'.png' : $fileName.'.jpg'; + return file_exists($fileName.'.png') && $this->utf8_invoices ? $fileName.'.png' : $fileName.'.jpg'; } public function getLogoWidth() diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php index 98ef973f674f..222463c4b532 100644 --- a/app/Ninja/Repositories/AccountRepository.php +++ b/app/Ninja/Repositories/AccountRepository.php @@ -6,7 +6,7 @@ use Session; use Utils; use DB; use stdClass; - +use Schema; use App\Models\AccountGateway; use App\Models\Invitation; use App\Models\Invoice; @@ -250,6 +250,10 @@ class AccountRepository public function findUserAccounts($userId1, $userId2 = false) { + if (!Schema::hasTable('user_accounts')) { + return false; + } + $query = UserAccount::where('user_id1', '=', $userId1) ->orWhere('user_id2', '=', $userId1) ->orWhere('user_id3', '=', $userId1) diff --git a/public/js/built.js b/public/js/built.js index 0a22d2a5a35e..a47d137523b7 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -29884,7 +29884,7 @@ function generatePDF(invoice, javascript, force, cb) { if (!invoice || !javascript) { return; } - console.log('== generatePDF - force: %s', force); + //console.log('== generatePDF - force: %s', force); if (force || !invoiceOld) { refreshTimer = null; } else { diff --git a/public/js/script.js b/public/js/script.js index dded462d101a..eabb1be9f671 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -13,7 +13,7 @@ function generatePDF(invoice, javascript, force, cb) { if (!invoice || !javascript) { return; } - console.log('== generatePDF - force: %s', force); + //console.log('== generatePDF - force: %s', force); if (force || !invoiceOld) { refreshTimer = null; } else { diff --git a/resources/views/accounts/details.blade.php b/resources/views/accounts/details.blade.php index 89a2a179f94b..b433f55b7353 100644 --- a/resources/views/accounts/details.blade.php +++ b/resources/views/accounts/details.blade.php @@ -51,7 +51,7 @@ @if (file_exists($account->getLogoPath()))
    - {!! HTML::image($account->getLogoPath().'?no_cache='.time(), "Logo") !!}   + {!! HTML::image($account->getLogoPath().'?no_cache='.time(), 'Logo', ['width' => 200]) !!}   {{ trans('texts.remove_logo') }}

    @endif diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php index e42e71f27574..9abb87690796 100644 --- a/resources/views/header.blade.php +++ b/resources/views/header.blade.php @@ -253,12 +253,12 @@ }, 2000); $('#search').blur(function(){ - $('#search').css('width', '150px'); + $('#search').css('width', '{{ Utils::isEnglish() ? 150 : 100 }}px'); $('ul.navbar-right').show(); }); $('#search').focus(function(){ - $('#search').css('width', '256px'); + $('#search').css('width', '{{ Utils::isEnglish() ? 256 : 206 }}px'); $('ul.navbar-right').hide(); if (!window.hasOwnProperty('searchData')) { $.get('{{ URL::route('getSearchData') }}', function(data) { @@ -461,7 +461,7 @@ diff --git a/resources/views/invoices/edit.blade.php b/resources/views/invoices/edit.blade.php index 317b72965392..db574f26b340 100644 --- a/resources/views/invoices/edit.blade.php +++ b/resources/views/invoices/edit.blade.php @@ -94,7 +94,7 @@ {!! Former::text('end_date')->data_bind("datePicker: end_date, valueUpdate: 'afterkeydown'") ->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT, DEFAULT_DATE_PICKER_FORMAT))->append('') !!}
    - @if ($invoice && $invoice->recurring_invoice_id) + @if ($invoice && $invoice->recurring_invoice)
    {!! trans('texts.created_by_recurring', ['invoice' => link_to('/invoices/'.$invoice->recurring_invoice->public_id, $invoice->recurring_invoice->invoice_number)]) !!}
    diff --git a/resources/views/user_account.blade.php b/resources/views/user_account.blade.php index 7364f33f6afc..9384f621b498 100644 --- a/resources/views/user_account.blade.php +++ b/resources/views/user_account.blade.php @@ -1,5 +1,5 @@
  • - @if (isset($user_id)) + @if (isset($user_id) && $user_id != Auth::user()->id) @else From 8f80ccf4d792db071f76274ce306f3d401ae5533 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 4 Aug 2015 14:38:48 +0300 Subject: [PATCH 12/16] Minor fixes --- app/Http/Controllers/AppController.php | 2 +- app/Ninja/Repositories/AccountRepository.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php index b135c045053e..bc6c699e728b 100644 --- a/app/Http/Controllers/AppController.php +++ b/app/Http/Controllers/AppController.php @@ -176,7 +176,7 @@ class AppController extends BaseController public function update() { - if (!Utils::isNinja() && Auth::check()) { + if (!Utils::isNinja()) { try { Artisan::call('migrate', array('--force' => true)); Artisan::call('db:seed', array('--force' => true, '--class' => 'PaymentLibrariesSeeder')); diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php index 222463c4b532..5aaa6e8d4d90 100644 --- a/app/Ninja/Repositories/AccountRepository.php +++ b/app/Ninja/Repositories/AccountRepository.php @@ -316,6 +316,9 @@ class AccountRepository } public function syncUserAccounts($users, $proPlanPaid = false) { + if (!$users) { + return; + } if (!$proPlanPaid) { foreach ($users as $user) { From 2cfcdd1e777ebb8472759f5ef10b8a512e2e5653 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 4 Aug 2015 17:33:30 +0300 Subject: [PATCH 13/16] Minor improvements --- app/Http/Controllers/HomeController.php | 4 ++-- resources/lang/da/texts.php | 2 +- resources/lang/de/texts.php | 2 +- resources/lang/en/texts.php | 3 ++- resources/lang/es/texts.php | 2 +- resources/lang/es_ES/texts.php | 2 +- resources/lang/fr/texts.php | 2 +- resources/lang/fr_CA/texts.php | 2 +- resources/lang/it/texts.php | 2 +- resources/lang/lt/texts.php | 2 +- resources/lang/nb_NO/texts.php | 2 +- resources/lang/nl/texts.php | 2 +- resources/lang/pt_BR/texts.php | 2 +- resources/lang/sv/texts.php | 2 +- resources/views/dashboard.blade.php | 6 +++--- resources/views/list.blade.php | 7 +++++-- 16 files changed, 24 insertions(+), 20 deletions(-) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 2645b0cbd98a..0f8226f077b1 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -72,9 +72,9 @@ class HomeController extends BaseController $user->news_feed_id = $newsFeedId; $user->save(); } - - Session::forget('news_feed_message'); } + + Session::forget('news_feed_message'); return 'success'; } diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 580e366e7298..ced550498886 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -743,7 +743,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index 7519119b40d6..9cd8866c9276 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -733,7 +733,7 @@ return array( 'invoice_no' => 'Rechnung Nr.', 'recent_payments' => 'Kürzliche Zahlungen', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', ); \ No newline at end of file diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index b9807c4c93b4..23b684fb2577 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -120,7 +120,7 @@ return array( 'active_clients' => 'active clients', 'invoices_past_due' => 'Invoices Past Due', 'upcoming_invoices' => 'Upcoming Invoices', - 'average_invoice' => 'Average invoice', + 'average_invoice' => 'Average Invoice', // list pages 'archive' => 'Archive', @@ -741,6 +741,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', + 'total_revenue' => 'Total Revenue', ); diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index 92ca314723b6..cf290277618c 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -713,7 +713,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', ); \ No newline at end of file diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php index 97b333fbb2c2..8d6fd83a7f9a 100644 --- a/resources/lang/es_ES/texts.php +++ b/resources/lang/es_ES/texts.php @@ -742,7 +742,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index 6fd60e17c4ba..6a87a6e78896 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -734,7 +734,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php index 0c0bf2e3a4a2..05d56c57821c 100644 --- a/resources/lang/fr_CA/texts.php +++ b/resources/lang/fr_CA/texts.php @@ -735,7 +735,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', ); diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index 9672b9ea533d..061bd060be8e 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -737,7 +737,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index 15ca60fcba36..ba4f8715e5a1 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -744,7 +744,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index c014c917637c..eeb80190ad5a 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -742,7 +742,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index f82175f36ad9..aa8458c590ee 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -737,7 +737,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index 875691412797..8bb24e732859 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -737,7 +737,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', ); diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index 13e443f81bdc..09aaa7998718 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -740,7 +740,7 @@ return array( 'recent_payments' => 'Recent Payments', 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', - + 'total_revenue' => 'Total Revenue', diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 864e7aeb1f89..f4e52f16e67f 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -7,6 +7,9 @@
    +
    + {{ trans('texts.total_revenue') }} +
    @if (count($paidToDate)) @foreach ($paidToDate as $item) @@ -16,9 +19,6 @@ {{ Utils::formatMoney(0) }} @endif
    -
    - {{ trans('texts.in_total_revenue') }} -
  • diff --git a/resources/views/list.blade.php b/resources/views/list.blade.php index cc9d3e35ce99..915c176f8c06 100644 --- a/resources/views/list.blade.php +++ b/resources/views/list.blade.php @@ -24,13 +24,16 @@
    - + @if (Auth::user()->isPro() && $entityType == ENTITY_INVOICE) {!! Button::normal(trans('texts.quotes'))->asLinkTo(URL::to('/quotes'))->appendIcon(Icon::create('list')) !!} @elseif ($entityType == ENTITY_CLIENT) {!! Button::normal(trans('texts.credits'))->asLinkTo(URL::to('/credits'))->appendIcon(Icon::create('list')) !!} @endif - {!! Button::primary(trans("texts.new_$entityType"))->asLinkTo(URL::to("/{$entityType}s/create"))->appendIcon(Icon::create('plus-sign')) !!} + + @if ($entityType != ENTITY_TASK || Auth::user()->account->timezone_id) + {!! Button::primary(trans("texts.new_$entityType"))->asLinkTo(URL::to("/{$entityType}s/create"))->appendIcon(Icon::create('plus-sign')) !!} + @endif
    @if (isset($secEntityType)) From 07b3fdb30cee2fde4be6c7986db0cedd9d0b85aa Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Fri, 7 Aug 2015 09:14:29 +0300 Subject: [PATCH 14/16] Minor improvements --- app/Http/routes.php | 3 +- app/Libraries/Utils.php | 9 +++--- app/Models/Account.php | 1 + app/Ninja/Repositories/AccountRepository.php | 2 +- public/js/built.js | 9 +++--- public/js/pdf.pdfmake.js | 6 ++-- public/js/script.js | 3 -- resources/lang/en/texts.php | 2 ++ resources/views/header.blade.php | 11 ++++--- resources/views/user_account.blade.php | 4 +-- .../views/users/account_management.blade.php | 29 ++++++++++++++++--- 11 files changed, 51 insertions(+), 28 deletions(-) diff --git a/app/Http/routes.php b/app/Http/routes.php index a9c322632db0..706ddbd3bb9e 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,5 +1,6 @@ id === 1) { Auth::loginUsingId(1); } -*/ +*/ \ No newline at end of file diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index 1efcf4b229a8..1263b4ed6763 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -341,10 +341,11 @@ class Utils return; } - $timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); + //$timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); - $dateTime = DateTime::createFromFormat($format, $date, new DateTimeZone($timezone)); + //$dateTime = DateTime::createFromFormat($format, $date, new DateTimeZone($timezone)); + $dateTime = DateTime::createFromFormat($format, $date); return $formatResult ? $dateTime->format('Y-m-d') : $dateTime; } @@ -355,11 +356,11 @@ class Utils return ''; } - $timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); + //$timezone = Session::get(SESSION_TIMEZONE, DEFAULT_TIMEZONE); $format = Session::get(SESSION_DATE_FORMAT, DEFAULT_DATE_FORMAT); $dateTime = DateTime::createFromFormat('Y-m-d', $date); - $dateTime->setTimeZone(new DateTimeZone($timezone)); + //$dateTime->setTimeZone(new DateTimeZone($timezone)); return $formatResult ? $dateTime->format($format) : $dateTime; } diff --git a/app/Models/Account.php b/app/Models/Account.php index e8cde5293c09..ee88e2fd1fcb 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -147,6 +147,7 @@ class Account extends Eloquent public function getLogoPath() { $fileName = 'logo/' . $this->account_key; + return file_exists($fileName.'.png') && $this->utf8_invoices ? $fileName.'.png' : $fileName.'.jpg'; } diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php index 5aaa6e8d4d90..d33c08f7abdf 100644 --- a/app/Ninja/Repositories/AccountRepository.php +++ b/app/Ninja/Repositories/AccountRepository.php @@ -298,7 +298,7 @@ class AccountRepository $item->account_id = $user->account->id; $item->account_name = $user->account->getDisplayName(); $item->pro_plan_paid = $user->account->pro_plan_paid; - $item->account_key = file_exists($user->account->getLogoPath()) ? $user->account->account_key : null; + $item->logo_path = file_exists($user->account->getLogoPath()) ? $user->account->getLogoPath() : null; $data[] = $item; } diff --git a/public/js/built.js b/public/js/built.js index a47d137523b7..08fa79b13021 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -30748,9 +30748,6 @@ function displayGrid(doc, invoice, data, x, y, layout, options) { key = invoice.account[key]; } else if (key === 'tax' && invoice.tax_name) { key = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; - if (invoice.tax_name.toLowerCase().indexOf(invoiceLabels['tax'].toLowerCase()) == -1) { - key = invoiceLabels['tax'] + ': ' + key; - } } else if (key === 'discount' && NINJA.parseFloat(invoice.discount) && !parseInt(invoice.is_amount_discount)) { key = invoiceLabels[key] + ' ' + parseFloat(invoice.discount) + '%'; } else { @@ -31619,7 +31616,7 @@ NINJA.decodeJavascript = function(invoice, javascript) } // search/replace values - var regExp = new RegExp('"\\$\\\w*?Value"', 'g'); + var regExp = new RegExp('"\\$[\\\w\\\.]*?Value"', 'g'); var matches = javascript.match(regExp); if (matches) { @@ -31628,6 +31625,7 @@ NINJA.decodeJavascript = function(invoice, javascript) field = match.substring(2, match.indexOf('Value')); field = toSnakeCase(field); var value = getDescendantProp(invoice, field) || ' '; + if (field.toLowerCase().indexOf('date') >= 0 && value != ' ') { value = moment(value, 'YYYY-MM-DD').format('MMM D YYYY'); } @@ -31760,7 +31758,8 @@ NINJA.subtotals = function(invoice, removeBalance) } if (invoice.tax && invoice.tax.name || invoice.tax_name) { - data.push([{text: invoiceLabels.tax}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); + var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; + data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); } if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { diff --git a/public/js/pdf.pdfmake.js b/public/js/pdf.pdfmake.js index 168a8733567b..8ec21c1e5b08 100644 --- a/public/js/pdf.pdfmake.js +++ b/public/js/pdf.pdfmake.js @@ -142,7 +142,7 @@ NINJA.decodeJavascript = function(invoice, javascript) } // search/replace values - var regExp = new RegExp('"\\$\\\w*?Value"', 'g'); + var regExp = new RegExp('"\\$[\\\w\\\.]*?Value"', 'g'); var matches = javascript.match(regExp); if (matches) { @@ -151,6 +151,7 @@ NINJA.decodeJavascript = function(invoice, javascript) field = match.substring(2, match.indexOf('Value')); field = toSnakeCase(field); var value = getDescendantProp(invoice, field) || ' '; + if (field.toLowerCase().indexOf('date') >= 0 && value != ' ') { value = moment(value, 'YYYY-MM-DD').format('MMM D YYYY'); } @@ -283,7 +284,8 @@ NINJA.subtotals = function(invoice, removeBalance) } if (invoice.tax && invoice.tax.name || invoice.tax_name) { - data.push([{text: invoiceLabels.tax}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); + var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; + data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); } if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { diff --git a/public/js/script.js b/public/js/script.js index eabb1be9f671..221b8d0a0d38 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -877,9 +877,6 @@ function displayGrid(doc, invoice, data, x, y, layout, options) { key = invoice.account[key]; } else if (key === 'tax' && invoice.tax_name) { key = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; - if (invoice.tax_name.toLowerCase().indexOf(invoiceLabels['tax'].toLowerCase()) == -1) { - key = invoiceLabels['tax'] + ': ' + key; - } } else if (key === 'discount' && NINJA.parseFloat(invoice.discount) && !parseInt(invoice.is_amount_discount)) { key = invoiceLabels[key] + ' ' + parseFloat(invoice.discount) + '%'; } else { diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 23b684fb2577..1a159cb2c5bb 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -742,6 +742,8 @@ return array( 'outstanding' => 'Outstanding', 'manage_companies' => 'Manage Companies', 'total_revenue' => 'Total Revenue', + + 'current_user' => 'Current User', ); diff --git a/resources/views/header.blade.php b/resources/views/header.blade.php index 9abb87690796..6925992c315f 100644 --- a/resources/views/header.blade.php +++ b/resources/views/header.blade.php @@ -385,7 +385,7 @@ 'user_id' => $item->user_id, 'account_name' => $item->account_name, 'user_name' => $item->user_name, - 'account_key' => $item->account_key, + 'logo_path' => isset($item->logo_path) ? $item->logo_path : "", 'selected' => true, ]) @endif @@ -397,7 +397,7 @@ 'user_id' => $item->user_id, 'account_name' => $item->account_name, 'user_name' => $item->user_name, - 'account_key' => $item->account_key, + 'logo_path' => isset($item->logo_path) ? $item->logo_path : "", 'selected' => false, ]) @endif @@ -406,16 +406,15 @@ @include('user_account', [ 'account_name' => Auth::user()->account->name ?: trans('texts.untitled'), 'user_name' => Auth::user()->getDisplayName(), - 'account_key' => Auth::user()->account->account_key, + 'logo_path' => Auth::user()->account->getLogoPath(), 'selected' => true, ]) @endif
  • - @if (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5) -
  • {!! link_to('/login?new_company=true', trans('texts.add_company')) !!}
  • - @endif @if (count(session(SESSION_USER_ACCOUNTS)) > 1)
  • {!! link_to('/manage_companies', trans('texts.manage_companies')) !!}
  • + @elseif (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5) +
  • {!! link_to('/login?new_company=true', trans('texts.add_company')) !!}
  • @endif
  • {!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}
  • diff --git a/resources/views/user_account.blade.php b/resources/views/user_account.blade.php index 9384f621b498..4848a190e5c9 100644 --- a/resources/views/user_account.blade.php +++ b/resources/views/user_account.blade.php @@ -5,9 +5,9 @@
    @endif - @if (file_exists('logo/'.$account_key.'.jpg')) + @if (file_exists($logo_path))
    - +
    @else
     
    diff --git a/resources/views/users/account_management.blade.php b/resources/views/users/account_management.blade.php index 75fa8a500ea7..3839a0bb4377 100644 --- a/resources/views/users/account_management.blade.php +++ b/resources/views/users/account_management.blade.php @@ -2,18 +2,39 @@ @section('content') + +
    + {!! Button::success(trans('texts.add_company'))->asLinkTo('/login?new_company=true') !!} +
    +

     

    +
    +
    +
    +
    +
    - @foreach (Session::get(SESSION_USER_ACCOUNTS) as $account) + @foreach (Session::get(SESSION_USER_ACCOUNTS) as $account) - - - + + + @endforeach
    {{ $account->account_name }}{{ $account->user_name }}{!! Button::primary(trans('texts.unlink'))->small()->withAttributes(['onclick'=>"return showUnlink({$account->id}, {$account->user_id})"]) !!} + @if (isset($account->logo_path)) + {!! HTML::image($account->logo_path.'?no_cache='.time(), 'Logo', ['width' => 100]) !!} + @endif + +

    {{ $account->account_name }}
    + {{ $account->user_name }} + @if ($account->user_id == Auth::user()->id) + | {{ trans('texts.current_user')}} + @endif +

    +
    {!! Button::primary(trans('texts.unlink'))->withAttributes(['onclick'=>"return showUnlink({$account->id}, {$account->user_id})"]) !!}
    From 78bf49cd19fd8f35635ca4266328371eecc88657 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 10 Aug 2015 18:48:41 +0300 Subject: [PATCH 15/16] Recurring invoices no longer prevent invoice numbers from being sequential --- .../Commands/SendRecurringInvoices.php | 73 ++--------------- app/Http/Controllers/InvoiceController.php | 24 +++++- app/Http/Controllers/QuoteController.php | 3 +- app/Http/routes.php | 3 +- app/Models/Client.php | 4 - app/Models/EntityModel.php | 7 +- app/Models/Invoice.php | 11 ++- app/Ninja/Repositories/InvoiceRepository.php | 75 ++++++++++++++++- app/Providers/AppServiceProvider.php | 7 +- ..._122647_add_partial_amount_to_invoices.php | 2 +- public/js/built.js | 4 +- public/js/pdf.pdfmake.js | 4 +- resources/lang/da/texts.php | 7 +- resources/lang/de/texts.php | 7 +- resources/lang/en/texts.php | 7 +- resources/lang/es/texts.php | 7 +- resources/lang/es_ES/texts.php | 7 +- resources/lang/fr/texts.php | 7 +- resources/lang/fr_CA/texts.php | 7 +- resources/lang/it/texts.php | 7 +- resources/lang/lt/texts.php | 7 +- resources/lang/nb_NO/texts.php | 7 +- resources/lang/nl/texts.php | 7 +- resources/lang/pt_BR/texts.php | 7 +- resources/lang/sv/texts.php | 7 +- resources/views/invoices/edit.blade.php | 81 ++++++++++--------- storage/templates/bold.js | 4 +- storage/templates/clean.js | 13 +-- storage/templates/modern.js | 2 +- storage/templates/plain.js | 2 +- 30 files changed, 261 insertions(+), 149 deletions(-) diff --git a/app/Console/Commands/SendRecurringInvoices.php b/app/Console/Commands/SendRecurringInvoices.php index 8f65214f7fc1..8f31473c9eca 100644 --- a/app/Console/Commands/SendRecurringInvoices.php +++ b/app/Console/Commands/SendRecurringInvoices.php @@ -7,6 +7,7 @@ use Illuminate\Console\Command; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputArgument; use App\Ninja\Mailers\ContactMailer as Mailer; +use App\Ninja\Repositories\InvoiceRepository; use App\Models\Invoice; use App\Models\InvoiceItem; use App\Models\Invitation; @@ -16,12 +17,14 @@ class SendRecurringInvoices extends Command protected $name = 'ninja:send-invoices'; protected $description = 'Send recurring invoices'; protected $mailer; + protected $invoiceRepo; - public function __construct(Mailer $mailer) + public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo) { parent::__construct(); $this->mailer = $mailer; + $this->invoiceRepo = $invoiceRepo; } public function fire() @@ -34,74 +37,10 @@ class SendRecurringInvoices extends Command $this->info(count($invoices).' recurring invoice(s) found'); foreach ($invoices as $recurInvoice) { - if ($recurInvoice->client->deleted_at) { - continue; - } - - if (!$recurInvoice->user->confirmed) { - continue; - } - - $this->info('Processing Invoice '.$recurInvoice->id.' - Should send '.($recurInvoice->shouldSendToday() ? 'YES' : 'NO')); - - if (!$recurInvoice->shouldSendToday()) { - continue; - } - - $invoice = Invoice::createNew($recurInvoice); - $invoice->client_id = $recurInvoice->client_id; - $invoice->recurring_invoice_id = $recurInvoice->id; - $invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber(false, 'R'); - $invoice->amount = $recurInvoice->amount; - $invoice->balance = $recurInvoice->amount; - $invoice->invoice_date = date_create()->format('Y-m-d'); - $invoice->discount = $recurInvoice->discount; - $invoice->po_number = $recurInvoice->po_number; - $invoice->public_notes = Utils::processVariables($recurInvoice->public_notes); - $invoice->terms = Utils::processVariables($recurInvoice->terms); - $invoice->invoice_footer = Utils::processVariables($recurInvoice->invoice_footer); - $invoice->tax_name = $recurInvoice->tax_name; - $invoice->tax_rate = $recurInvoice->tax_rate; - $invoice->invoice_design_id = $recurInvoice->invoice_design_id; - $invoice->custom_value1 = $recurInvoice->custom_value1; - $invoice->custom_value2 = $recurInvoice->custom_value2; - $invoice->custom_taxes1 = $recurInvoice->custom_taxes1; - $invoice->custom_taxes2 = $recurInvoice->custom_taxes2; - $invoice->is_amount_discount = $recurInvoice->is_amount_discount; - - if ($invoice->client->payment_terms != 0) { - $days = $invoice->client->payment_terms; - if ($days == -1) { - $days = 0; - } - $invoice->due_date = date_create()->modify($days.' day')->format('Y-m-d'); - } - - $invoice->save(); - - foreach ($recurInvoice->invoice_items as $recurItem) { - $item = InvoiceItem::createNew($recurItem); - $item->product_id = $recurItem->product_id; - $item->qty = $recurItem->qty; - $item->cost = $recurItem->cost; - $item->notes = Utils::processVariables($recurItem->notes); - $item->product_key = Utils::processVariables($recurItem->product_key); - $item->tax_name = $recurItem->tax_name; - $item->tax_rate = $recurItem->tax_rate; - $invoice->invoice_items()->save($item); - } - - foreach ($recurInvoice->invitations as $recurInvitation) { - $invitation = Invitation::createNew($recurInvitation); - $invitation->contact_id = $recurInvitation->contact_id; - $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH); - $invoice->invitations()->save($invitation); - } + $this->info('Processing Invoice '.$recurInvoice->id.' - Should send '.($recurInvoice->shouldSendToday() ? 'YES' : 'NO')); + $this->invoiceRepo->createRecurringInvoice($recurInvoice); $this->mailer->sendInvoice($invoice); - - $recurInvoice->last_sent_date = Carbon::now()->toDateTimeString(); - $recurInvoice->save(); } $this->info('Done'); diff --git a/app/Http/Controllers/InvoiceController.php b/app/Http/Controllers/InvoiceController.php index 248b1be6bef3..efed3effd150 100644 --- a/app/Http/Controllers/InvoiceController.php +++ b/app/Http/Controllers/InvoiceController.php @@ -280,7 +280,7 @@ class InvoiceController extends BaseController $method = 'POST'; $url = "{$entityType}s"; } else { - Utils::trackViewed($invoice->invoice_number.' - '.$invoice->client->getDisplayName(), $invoice->getEntityType()); + Utils::trackViewed($invoice->getDisplayName().' - '.$invoice->client->getDisplayName(), $invoice->getEntityType()); $method = 'PUT'; $url = "{$entityType}s/{$publicId}"; } @@ -335,6 +335,7 @@ class InvoiceController extends BaseController 'url' => $url, 'title' => trans("texts.edit_{$entityType}"), 'client' => $invoice->client, + 'isRecurring' => $invoice->is_recurring, 'actions' => $actions); $data = array_merge($data, self::getViewModel()); @@ -358,10 +359,10 @@ class InvoiceController extends BaseController return View::make('invoices.edit', $data); } - public function create($clientPublicId = 0) + public function create($clientPublicId = 0, $isRecurring = false) { $client = null; - $invoiceNumber = Auth::user()->account->getNextInvoiceNumber(); + $invoiceNumber = $isRecurring ? microtime(true) : Auth::user()->account->getNextInvoiceNumber(); if ($clientPublicId) { $client = Client::scope($clientPublicId)->firstOrFail(); @@ -375,12 +376,18 @@ class InvoiceController extends BaseController 'method' => 'POST', 'url' => 'invoices', 'title' => trans('texts.new_invoice'), + 'isRecurring' => $isRecurring, 'client' => $client); $data = array_merge($data, self::getViewModel()); return View::make('invoices.edit', $data); } + public function createRecurring($clientPublicId = 0) + { + return self::create($clientPublicId, true); + } + private static function getViewModel() { $recurringHelp = ''; @@ -510,7 +517,16 @@ class InvoiceController extends BaseController return $this->convertQuote($publicId); } elseif ($action == 'email') { if (Auth::user()->confirmed && !Auth::user()->isDemo()) { - $response = $this->mailer->sendInvoice($invoice); + if ($invoice->is_recurring) { + if ($invoice->shouldSendToday()) { + $invoice = $this->invoiceRepo->createRecurringInvoice($invoice); + $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); diff --git a/app/Http/Controllers/QuoteController.php b/app/Http/Controllers/QuoteController.php index bb8526c424e9..589841a314bf 100644 --- a/app/Http/Controllers/QuoteController.php +++ b/app/Http/Controllers/QuoteController.php @@ -158,7 +158,8 @@ class QuoteController extends BaseController 'paymentTerms' => Cache::get('paymentTerms'), 'industries' => Cache::get('industries'), 'invoiceDesigns' => InvoiceDesign::getDesigns(), - 'invoiceLabels' => Auth::user()->account->getInvoiceLabels() + 'invoiceLabels' => Auth::user()->account->getInvoiceLabels(), + 'isRecurring' => false, ]; } diff --git a/app/Http/routes.php b/app/Http/routes.php index 706ddbd3bb9e..7c158a314490 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,6 +1,5 @@ 'auth'], function() { Route::get('tasks/create/{client_id?}', 'TaskController@create'); Route::post('tasks/bulk', 'TaskController@bulk'); - Route::get('recurring_invoices', 'InvoiceController@recurringIndex'); Route::get('api/recurring_invoices/{client_id?}', array('as'=>'api.recurring_invoices', 'uses'=>'InvoiceController@getRecurringDatatable')); Route::get('invoices/invoice_history/{invoice_id}', 'InvoiceController@invoiceHistory'); @@ -141,6 +139,7 @@ Route::group(['middleware' => 'auth'], function() { Route::resource('invoices', 'InvoiceController'); Route::get('api/invoices/{client_id?}', array('as'=>'api.invoices', 'uses'=>'InvoiceController@getDatatable')); Route::get('invoices/create/{client_id?}', 'InvoiceController@create'); + Route::get('recurring_invoices/create/{client_id?}', 'InvoiceController@createRecurring'); Route::get('invoices/{public_id}/clone', 'InvoiceController@cloneInvoice'); Route::post('invoices/bulk', 'InvoiceController@bulk'); diff --git a/app/Models/Client.php b/app/Models/Client.php index a9b6c8fe95d3..554f74556910 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -83,10 +83,6 @@ class Client extends EntityModel return $this->name; } - if (!$this->contacts || !count($this->contacts)) { - $this->load('contacts'); - } - $contact = $this->contacts()->first(); return $contact->getDisplayName(); diff --git a/app/Models/EntityModel.php b/app/Models/EntityModel.php index bf44b6f6d886..550de1d3cef0 100644 --- a/app/Models/EntityModel.php +++ b/app/Models/EntityModel.php @@ -44,7 +44,7 @@ class EntityModel extends Eloquent public function getActivityKey() { - return '[' . $this->getEntityType().':'.$this->public_id.':'.$this->getName() . ']'; + return '[' . $this->getEntityType().':'.$this->public_id.':'.$this->getDisplayName() . ']'; } /* @@ -83,6 +83,11 @@ class EntityModel extends Eloquent return $this->public_id; } + public function getDisplayName() + { + return $this->getName(); + } + // Remap ids to public_ids and show name public function toPublicArray() { diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 63700410fa18..aeebfaed6ab0 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -48,6 +48,11 @@ class Invoice extends EntityModel return $this->belongsTo('App\Models\Invoice'); } + public function recurring_invoices() + { + return $this->hasMany('App\Models\Invoice', 'recurring_invoice_id'); + } + public function invitations() { return $this->hasMany('App\Models\Invitation')->orderBy('invitations.contact_id'); @@ -55,7 +60,7 @@ class Invoice extends EntityModel public function getName() { - return $this->invoice_number; + return $this->is_recurring ? trans('texts.recurring') : $this->invoice_number; } public function getFileName() @@ -258,7 +263,9 @@ class Invoice extends EntityModel } Invoice::creating(function ($invoice) { - $invoice->account->incrementCounter($invoice->is_quote); + if (!$invoice->is_recurring) { + $invoice->account->incrementCounter($invoice->is_quote); + } }); Invoice::created(function ($invoice) { diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index e93ea47826bb..bfbf62658f45 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -1,11 +1,12 @@ select(['public_id', 'invoice_number']) ->get(); } + + public function createRecurringInvoice($recurInvoice) + { + $recurInvoice->load('account.timezone', 'invoice_items', 'client', 'user'); + + if ($recurInvoice->client->deleted_at) { + return false; + } + + if (!$recurInvoice->user->confirmed) { + return false; + } + + if (!$recurInvoice->shouldSendToday()) { + return false; + } + + $invoice = Invoice::createNew($recurInvoice); + $invoice->client_id = $recurInvoice->client_id; + $invoice->recurring_invoice_id = $recurInvoice->id; + $invoice->invoice_number = $recurInvoice->account->getNextInvoiceNumber(false, 'R'); + $invoice->amount = $recurInvoice->amount; + $invoice->balance = $recurInvoice->amount; + $invoice->invoice_date = date_create()->format('Y-m-d'); + $invoice->discount = $recurInvoice->discount; + $invoice->po_number = $recurInvoice->po_number; + $invoice->public_notes = Utils::processVariables($recurInvoice->public_notes); + $invoice->terms = Utils::processVariables($recurInvoice->terms); + $invoice->invoice_footer = Utils::processVariables($recurInvoice->invoice_footer); + $invoice->tax_name = $recurInvoice->tax_name; + $invoice->tax_rate = $recurInvoice->tax_rate; + $invoice->invoice_design_id = $recurInvoice->invoice_design_id; + $invoice->custom_value1 = $recurInvoice->custom_value1; + $invoice->custom_value2 = $recurInvoice->custom_value2; + $invoice->custom_taxes1 = $recurInvoice->custom_taxes1; + $invoice->custom_taxes2 = $recurInvoice->custom_taxes2; + $invoice->is_amount_discount = $recurInvoice->is_amount_discount; + + if ($invoice->client->payment_terms != 0) { + $days = $invoice->client->payment_terms; + if ($days == -1) { + $days = 0; + } + $invoice->due_date = date_create()->modify($days.' day')->format('Y-m-d'); + } + + $invoice->save(); + + foreach ($recurInvoice->invoice_items as $recurItem) { + $item = InvoiceItem::createNew($recurItem); + $item->product_id = $recurItem->product_id; + $item->qty = $recurItem->qty; + $item->cost = $recurItem->cost; + $item->notes = Utils::processVariables($recurItem->notes); + $item->product_key = Utils::processVariables($recurItem->product_key); + $item->tax_name = $recurItem->tax_name; + $item->tax_rate = $recurItem->tax_rate; + $invoice->invoice_items()->save($item); + } + + foreach ($recurInvoice->invitations as $recurInvitation) { + $invitation = Invitation::createNew($recurInvitation); + $invitation->contact_id = $recurInvitation->contact_id; + $invitation->invitation_key = str_random(RANDOM_KEY_LENGTH); + $invoice->invitations()->save($invitation); + } + + $recurInvoice->last_sent_date = Carbon::now()->toDateTimeString(); + $recurInvoice->save(); + + return $invoice; + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 9efba90b91af..d9fc74798f69 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -40,10 +40,13 @@ class AppServiceProvider extends ServiceProvider {