diff --git a/README.md b/README.md index e1b2cd1398..ad03017fff 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,11 @@ ### [https://www.invoiceninja.com](https://www.invoiceninja.com) ### Introduction -Most online invoicing sites are expensive. They shouldn't be. The aim of this project is to provide a free, open-source alternative. Additionally, the hope is this codebase will serve as a sample site for Laravel as well as other JavaScript technologies. +Most online invoicing sites are expensive. They shouldn't be. The aim of this project is to provide a free, open-source alternative. Additionally, the hope is the codebase will serve as a sample site for Laravel as well as other JavaScript technologies. + +For updates follow [@invoiceninja](https://twitter.com/invoiceninja) and [@hillelcoren](https://twitter.com/hillelcoren) + +Site design by [kantorp-wegl.in](http://kantorp-wegl.in/) ### Features * Core application built using Laravel 4.1 @@ -15,7 +19,7 @@ Most online invoicing sites are expensive. They shouldn't be. The aim of this pr ### Steps to setup -If you plan on submitting changes it's best to fork the repo (https://help.github.com/articles/fork-a-repo), otherwise you can just checkout the code. +If you plan on submitting changes it's best to [fork the repo](https://help.github.com/articles/fork-a-repo), otherwise you can just checkout the code. git clone git@github.com:hillelcoren/invoice-ninja.git ninja cd ninja diff --git a/app/database/seeds/ConstantsSeeder.php b/app/database/seeds/ConstantsSeeder.php index 6ca39fcd2c..0e31b564c3 100755 --- a/app/database/seeds/ConstantsSeeder.php +++ b/app/database/seeds/ConstantsSeeder.php @@ -105,7 +105,7 @@ class ConstantsSeeder extends Seeder Industry::create(array('name' => 'Travel & Luxury')); Industry::create(array('name' => 'Other')); - Size::create(array('name' => '1 = 3')); + Size::create(array('name' => '1 - 3')); Size::create(array('name' => '4 - 10')); Size::create(array('name' => '11 - 50')); Size::create(array('name' => '51 - 100')); @@ -122,6 +122,7 @@ class ConstantsSeeder extends Seeder Currency::create(array('name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); Currency::create(array('name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.')); + Currency::create(array('name' => 'Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.')); DatetimeFormat::create(array('format' => 'd/M/Y g:i a', 'label' => '10/Mar/2013')); diff --git a/app/models/Client.php b/app/models/Client.php index 9458b43cc2..6e805023bf 100755 --- a/app/models/Client.php +++ b/app/models/Client.php @@ -162,7 +162,17 @@ class Client extends EntityModel return ''; } - return link_to($this->website, $this->website, array('target'=>'_blank')); + $link = $this->website; + $title = $this->website; + $prefix = 'http://'; + + if (strlen($link) > 7 && substr($link, 0, 7) === $prefix) { + $title = substr($title, 7); + } else { + $link = $prefix . $link; + } + + return link_to($link, $title, array('target'=>'_blank')); } public function getDateCreated() diff --git a/app/views/about_us.blade.php b/app/views/about_us.blade.php index f5efb7fdea..fe0f50bcbf 100644 --- a/app/views/about_us.blade.php +++ b/app/views/about_us.blade.php @@ -64,7 +64,7 @@

Open Source Platform

-

Free yourself from online invoicing platforms with high monthly fees and limited functionality. Being open source allows us fast app development, security audits by the open-course community, and we can keep it FREE!

+

Free yourself from online invoicing platforms with high monthly fees and limited functionality. Being open source allows us fast app development, security audits by the open-course community, and we can keep it FREE!

diff --git a/app/views/accounts/payments.blade.php b/app/views/accounts/payments.blade.php index ce8a149d85..ed8a8f92a4 100755 --- a/app/views/accounts/payments.blade.php +++ b/app/views/accounts/payments.blade.php @@ -36,6 +36,8 @@ {{-- do nothing --}} @elseif ($field == 'testMode' || $field == 'developerMode') {{-- Former::checkbox($gateway->id.'_'.$field)->label(Utils::toSpaceCase($field))->text('Enable') --}} + @elseif ($field == 'username' || $field == 'password') + {{ Former::text($gateway->id.'_'.$field)->label('API '. ucfirst(Utils::toSpaceCase($field))) }} @else {{ Former::text($gateway->id.'_'.$field)->label(Utils::toSpaceCase($field)) }} @endif diff --git a/app/views/emails/invoice_paid_html.blade.php b/app/views/emails/invoice_paid_html.blade.php index 86002d20e4..5e8a50a845 100755 --- a/app/views/emails/invoice_paid_html.blade.php +++ b/app/views/emails/invoice_paid_html.blade.php @@ -14,7 +14,7 @@ To adjust your email notification settings please click here. - Regards, + Regards,

The InvoiceNinja Team diff --git a/app/views/emails/invoice_sent_html.blade.php b/app/views/emails/invoice_sent_html.blade.php index 716f92d64f..a3c17243d0 100755 --- a/app/views/emails/invoice_sent_html.blade.php +++ b/app/views/emails/invoice_sent_html.blade.php @@ -9,9 +9,9 @@ The following client {{ $clientName }} was emailed Invoice {{ $invoiceNumber }} for {{ $invoiceAmount}}.

- Regards, + Regards,

- The InvoiceNinja Team + The InvoiceNinja Team

To adjust your email notification settings please click here.

diff --git a/app/views/emails/invoice_viewed_html.blade.php b/app/views/emails/invoice_viewed_html.blade.php index e17cd52eb5..41a239b0dd 100755 --- a/app/views/emails/invoice_viewed_html.blade.php +++ b/app/views/emails/invoice_viewed_html.blade.php @@ -9,9 +9,9 @@ The following client {{ $clientName }} viewed Invoice {{ $invoiceNumber }} for {{ $invoiceAmount}}.

- Regards, + Regards,

- The InvoiceNinja Team + The InvoiceNinja Team

To adjust your email notification settings please click here.

diff --git a/app/views/header.blade.php b/app/views/header.blade.php index a09cbbb36e..6db13f6aa8 100755 --- a/app/views/header.blade.php +++ b/app/views/header.blade.php @@ -77,7 +77,7 @@ - + diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index ebb59547ea..2e8f9b31fb 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -22,6 +22,8 @@ 'product_key' => 'max:20', )); }} + +

@@ -255,7 +257,7 @@ ) , array('id'=>'primaryActions', 'style'=>'text-align:left', 'data-bind'=>'css: $root.enable.save'))->split(); --}} @else - {{ Button::success_submit('Save Invoice', array('id' => 'saveButton')) }} + {{ Button::success('Save Invoice', array('id' => 'saveButton', 'onclick' => 'onSaveClick()')) }} @endif {{ Button::normal('Email Invoice', array('id' => 'email_button', 'onclick' => 'onEmailClick()'))->append_with_icon('send'); }} @@ -423,7 +425,7 @@

Examples of dynamic invoice variables:

  • "Gym membership for the month of :MONTH" => "Gym membership for the month of July"
  • -
  • ":YEAR+1 yearly subscription" => "2014 Yearly Subscription"
  • +
  • ":YEAR+1 yearly subscription" => "2015 Yearly Subscription"
  • "Retainer payment for :QUARTER+1" => "Retainer payment for Q2"
  @@ -454,7 +456,26 @@ $(function() { - $('#country_id').combobox(); + $('#country_id').combobox().on('change', function(e) { + console.log('changed country'); + var countryId = parseInt($('input[name=country_id]').val(), 10); + var foundMatch = false; + $('#country_id option').each(function() { + var itemId = parseInt($(this).val(), 10); + if (countryId === itemId) { + foundMatch = true; + var country = {id:countryId, name:$(this).text()}; + model.invoice().client().country = country; + model.invoice().client().country_id(countryId); + return; + } + }); + if (!foundMatch) { + model.invoice().client().country = false; + model.invoice().client().country_id(0); + } + }); + $('[rel=tooltip]').tooltip(); $('#invoice_date, #due_date, #start_date, #end_date').datepicker(); @@ -470,19 +491,15 @@ model.loadClient(clientMap[clientId]); } else { model.loadClient($.parseJSON(ko.toJSON(new ClientModel()))); + model.invoice().client().country = false; } refreshPDF(); - }); //.trigger('change'); + }); //.trigger('change'); $('#terms, #public_notes, #invoice_number, #invoice_date, #due_date, #po_number, #discount, #currency_id, #invoice_design_id').change(function() { refreshPDF(); }); - $('.country_select input.form-control').on('change', function(e) { - var countryId = parseInt($('input[name=country_id]').val(), 10); - model.invoice().client().country_id(countryId); - }); - @if ($client || $invoice) $('#invoice_number').focus(); @else @@ -651,16 +668,17 @@ @if (Auth::user()->confirmed) if (confirm('Are you sure you want to email this invoice?')) { $('#action').val('email'); - $('.main_form').submit(); + $('#submitButton').click(); } @else $('#action').val('email'); - $('.main_form').submit(); + $('#submitButton').click(); @endif } function onSaveClick() { - $('.main_form').submit(); + $('#action').val(''); + $('#submitButton').click(); } function isSaveValid() { @@ -698,7 +716,7 @@ function onCloneClick() { $('#action').val('clone'); - $('.main_form').submit(); + $('#submitButton').click(); } @if ($client && $invoice) @@ -713,13 +731,13 @@ function onArchiveClick() { $('#action').val('archive'); - $('.main_form').submit(); + $('#submitButton').click(); } function onDeleteClick() { if (confirm('Are you sure you want to delete this invoice?')) { $('#action').val('delete'); - $('.main_form').submit(); + $('#submitButton').click(); } } @@ -730,8 +748,8 @@ } event.preventDefault(); - - $('.main_form').submit(); + $('#action').val(''); + $('#submitButton').click(); return false; } } @@ -1431,6 +1449,7 @@ var clientMap = {}; var $clientSelect = $('select#client'); + for (var i=0; i Invoice Ninja {{ isset($title) ? $title : '' }} - + @@ -13,7 +13,7 @@ - + diff --git a/public/js/script.js b/public/js/script.js index 3d4bae51d2..15e7f589a1 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -440,12 +440,12 @@ ko.bindingHandlers.dropdown = { /* ko.utils.registerEventHandler(element, "change", function () { - console.log("change: %s", $(element).val()); - var + console.log("change: %s", $(element).val()); + //var valueAccessor($(element).val()); //$(element).combobox('refresh'); }); - */ + */ }, update: function (element, valueAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); @@ -1290,11 +1290,12 @@ function displayClient(doc, invoice, x, y, layout) { if (!client) { return; } - + console.log('=== country: ' + (client.country ? client.country.name : false)); var data = [ getClientDisplayName(client), concatStrings(client.address1, client.address2), concatStrings(client.city, client.state, client.postal_code), + client.country ? client.country.name : false, client.contacts[0].email ]; @@ -1335,21 +1336,23 @@ function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX) } function concatStrings() { - var hasValue = false; var concatStr = ''; + var data = []; for (var i=0; i 1) { concatStr += ', '; - } else if (i < arguments.length -1) { + } else if (i < data.length -1) { concatStr += ' '; } } - return hasValue ? concatStr : false; + return data.length ? concatStr : false; } function displayGrid(doc, invoice, data, x, y, layout, hasheader, rightAlignX, rightAlignTitleX) { diff --git a/tests/acceptance/WelcomeCept.php b/tests/acceptance/WelcomeCept.php index 215c11087b..ee6916c3ce 100644 --- a/tests/acceptance/WelcomeCept.php +++ b/tests/acceptance/WelcomeCept.php @@ -2,7 +2,7 @@ $I = new WebGuy($scenario); $I->wantTo('click invoice now'); -$I->amOnPage('/rocksteady'); +$I->amOnPage('/'); $I->click('#startButton'); $I->seeInDatabase('users', ['id' => 1]); diff --git a/tests/acceptance/complete/CheckCreateNewClientFormCept.php b/tests/acceptance/complete/CheckCreateNewClientFormCept.php index ad13d3f6df..cfa8eb398e 100644 --- a/tests/acceptance/complete/CheckCreateNewClientFormCept.php +++ b/tests/acceptance/complete/CheckCreateNewClientFormCept.php @@ -11,7 +11,7 @@ $I->wantTo('Test Form:New Client. /clients/create'); -$I->amOnPage('/rocksteady'); +$I->amOnPage('/'); $I->click('#startButton');