diff --git a/LICENSE b/LICENSE index eaa9f1e3672c..83e6795919db 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ Attribution Assurance License -Copyright (c) 2014 by Hillel Coren +Copyright (c) 2015 by Hillel Coren http://www.hillelcoren.com All Rights Reserved diff --git a/app/Http/Controllers/AccountApiController.php b/app/Http/Controllers/AccountApiController.php index ed5d64468f61..1b6d1103bd97 100644 --- a/app/Http/Controllers/AccountApiController.php +++ b/app/Http/Controllers/AccountApiController.php @@ -10,13 +10,12 @@ use App\Models\AccountToken; use App\Ninja\Repositories\AccountRepository; use Illuminate\Http\Request; use League\Fractal; -use League\Fractal\Resource\Item; -use League\Fractal\Resource\Collection; use League\Fractal\Manager; use App\Ninja\Serializers\ArraySerializer; use App\Ninja\Transformers\AccountTransformer; use App\Ninja\Transformers\UserAccountTransformer; use App\Http\Controllers\BaseAPIController; +use Swagger\Annotations as SWG; class AccountApiController extends BaseAPIController { @@ -47,21 +46,28 @@ class AccountApiController extends BaseAPIController private function processLogin(Request $request) { // Create a new token only if one does not already exist - $this->accountRepo->createTokens(Auth::user(), $request->token_name); + $user = Auth::user(); + $this->accountRepo->createTokens($user, $request->token_name); - $users = $this->accountRepo->findUsers(Auth::user(), 'account.account_tokens'); - $resource = new Collection($users, new UserAccountTransformer($request->token_name)); + $users = $this->accountRepo->findUsers($user, 'account.account_tokens'); + $data = $this->createCollection($users, new UserAccountTransformer($user->account, $request->token_name)); - return $this->returnData($resource, 'user_accounts'); + $response = [ + 'user_accounts' => $data, + 'default_url' => SITE_URL + ]; + + return $this->response($response); } - public function show($accountKey) + public function show() { - $account = $this->accountRepo->findByKey($accountKey); + $account = Auth::user()->account; + $account->load('clients.getInvoices.invoice_items', 'users'); - $resource = new Item($account, new AccountTransformer); + $response = $this->createItem($account, new AccountTransformer); - return $this->returnData($resource); + return $this->response($response); } } diff --git a/app/Http/Controllers/BaseAPIController.php b/app/Http/Controllers/BaseAPIController.php index 0d11964b64ea..ac10d6678622 100644 --- a/app/Http/Controllers/BaseAPIController.php +++ b/app/Http/Controllers/BaseAPIController.php @@ -4,8 +4,40 @@ use Utils; use Response; use League\Fractal; use League\Fractal\Manager; +use League\Fractal\Resource\Item; +use League\Fractal\Resource\Collection; use App\Ninja\Serializers\ArraySerializer; +/** + * @SWG\Swagger( + * schemes={"http","https"}, + * host="ninja.dev", + * basePath="/api/v1", + * @SWG\Info( + * version="1.0.0", + * title="Invoice Ninja API", + * description="An open-source invoicing and time-tracking app built with Laravel", + * termsOfService="", + * @SWG\Contact( + * email="contact@invoiceninja.com" + * ), + * @SWG\License( + * name="Attribution Assurance License", + * url="https://raw.githubusercontent.com/invoiceninja/invoiceninja/master/LICENSE" + * ) + * ), + * @SWG\ExternalDocumentation( + * description="Find out more about Invoice Ninja", + * url="https://www.invoiceninja.com" + * ), + * @SWG\SecurityScheme( + * securityDefinition="api_key", + * type="apiKey", + * in="header", + * name="TOKEN" + * ) + * ) + */ class BaseAPIController extends Controller { protected $manager; @@ -16,14 +48,20 @@ class BaseAPIController extends Controller $this->manager->setSerializer(new ArraySerializer()); } - protected function returnData($resource, $class = false) + protected function createItem($data, $transformer) { - $response = $this->manager->createData($resource)->toArray(); + $resource = new Item($data, $transformer); + return $this->manager->createData($resource)->toArray(); + } - if ($class) { - $response = [$class => $response]; - } - + protected function createCollection($data, $transformer) + { + $resource = new Collection($data, $transformer); + return $this->manager->createData($resource)->toArray(); + } + + protected function response($response) + { $response = json_encode($response, JSON_PRETTY_PRINT); $headers = Utils::getApiHeaders(); diff --git a/app/Http/Controllers/ClientApiController.php b/app/Http/Controllers/ClientApiController.php index b847a54d349b..c4cce4d570ad 100644 --- a/app/Http/Controllers/ClientApiController.php +++ b/app/Http/Controllers/ClientApiController.php @@ -23,6 +23,22 @@ class ClientApiController extends Controller return Response::make('', 200, $headers); } + /** + * @SWG\Get( + * path="/clients", + * summary="List of clients", + * tags={"client"}, + * @SWG\Response( + * response=200, + * description="A list with clients", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Client")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function index() { $clients = Client::scope() @@ -37,6 +53,27 @@ class ClientApiController extends Controller return Response::make($response, 200, $headers); } + /** + * @SWG\Post( + * path="/clients", + * tags={"client"}, + * summary="Create a client", + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/Client") + * ), + * @SWG\Response( + * response=200, + * description="New client", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Client")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function store(CreateClientRequest $request) { $client = $this->clientRepo->save($request->input()); diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php index c281798ecd7c..124d7bc574d1 100644 --- a/app/Http/Controllers/ClientController.php +++ b/app/Http/Controllers/ClientController.php @@ -13,6 +13,7 @@ use Cache; use App\Models\Activity; use App\Models\Client; +use App\Models\Account; use App\Models\Contact; use App\Models\Invoice; use App\Models\Size; @@ -154,6 +155,12 @@ class ClientController extends BaseController $data = array_merge($data, self::getViewModel()); + if (Auth::user()->account->isNinjaAccount()) { + if ($account = Account::whereId($client->public_id)->first()) { + $data['proPlanPaid'] = $account['pro_plan_paid']; + } + } + return View::make('clients.edit', $data); } diff --git a/app/Http/Controllers/InvoiceApiController.php b/app/Http/Controllers/InvoiceApiController.php index b0d7aede0710..2be9b2d70fc3 100644 --- a/app/Http/Controllers/InvoiceApiController.php +++ b/app/Http/Controllers/InvoiceApiController.php @@ -24,6 +24,22 @@ class InvoiceApiController extends Controller $this->mailer = $mailer; } + /** + * @SWG\Get( + * path="/invoices", + * summary="List of invoices", + * tags={"invoice"}, + * @SWG\Response( + * response=200, + * description="A list with invoices", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Invoice")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function index($clientPublicId = false) { $invoices = Invoice::scope() @@ -54,6 +70,28 @@ class InvoiceApiController extends Controller return Response::make($response, 200, $headers); } + + /** + * @SWG\Post( + * path="/invoices", + * tags={"invoice"}, + * summary="Create an invoice", + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/Invoice") + * ), + * @SWG\Response( + * response=200, + * description="New invoice", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Invoice")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function store() { $data = Input::all(); diff --git a/app/Http/Controllers/PaymentApiController.php b/app/Http/Controllers/PaymentApiController.php index d83fcac494c8..f23a26969fb0 100644 --- a/app/Http/Controllers/PaymentApiController.php +++ b/app/Http/Controllers/PaymentApiController.php @@ -16,6 +16,22 @@ class PaymentApiController extends Controller $this->paymentRepo = $paymentRepo; } + /** + * @SWG\Get( + * path="/payments", + * tags={"payment"}, + * summary="List of payments", + * @SWG\Response( + * response=200, + * description="A list with payments", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Payment")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function index($clientPublicId = false) { $payments = Payment::scope() @@ -37,6 +53,27 @@ class PaymentApiController extends Controller } + /** + * @SWG\Post( + * path="/payments", + * summary="Create a payment", + * tags={"payment"}, + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/Payment") + * ), + * @SWG\Response( + * response=200, + * description="New payment", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Payment")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function store() { $data = Input::all(); diff --git a/app/Http/Controllers/QuoteApiController.php b/app/Http/Controllers/QuoteApiController.php index 24fd1639215f..055f718fb179 100644 --- a/app/Http/Controllers/QuoteApiController.php +++ b/app/Http/Controllers/QuoteApiController.php @@ -14,6 +14,22 @@ class QuoteApiController extends Controller $this->invoiceRepo = $invoiceRepo; } + /** + * @SWG\Get( + * path="/quotes", + * tags={"quote"}, + * summary="List of quotes", + * @SWG\Response( + * response=200, + * description="A list with quotes", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Invoice")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function index($clientPublicId = false) { $invoices = Invoice::scope() diff --git a/app/Http/Controllers/TaskApiController.php b/app/Http/Controllers/TaskApiController.php index c15ea9fb659a..ddbd11f7ae92 100644 --- a/app/Http/Controllers/TaskApiController.php +++ b/app/Http/Controllers/TaskApiController.php @@ -15,6 +15,22 @@ class TaskApiController extends Controller $this->taskRepo = $taskRepo; } + /** + * @SWG\Get( + * path="/tasks", + * tags={"task"}, + * summary="List of tasks", + * @SWG\Response( + * response=200, + * description="A list with tasks", + * @SWG\Schema(type="array", @SWG\Items(ref="#/definitions/Task")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function index($clientPublicId = false) { $tasks = Task::scope()->with('client'); @@ -34,6 +50,27 @@ class TaskApiController extends Controller return Response::make($response, 200, $headers); } + /** + * @SWG\Post( + * path="/tasks", + * tags={"task"}, + * summary="Create a task", + * @SWG\Parameter( + * in="body", + * name="body", + * @SWG\Schema(ref="#/definitions/Task") + * ), + * @SWG\Response( + * response=200, + * description="New task", + * @SWG\Schema(type="object", @SWG\Items(ref="#/definitions/Task")) + * ), + * @SWG\Response( + * response="default", + * description="an ""unexpected"" error" + * ) + * ) + */ public function store() { $data = Input::all(); diff --git a/app/Http/Middleware/ApiCheck.php b/app/Http/Middleware/ApiCheck.php index 9323b4605645..5632e7de4e90 100644 --- a/app/Http/Middleware/ApiCheck.php +++ b/app/Http/Middleware/ApiCheck.php @@ -35,7 +35,7 @@ class ApiCheck { Session::set('token_id', $token->id); } else { sleep(3); - return Response::make('Invalid token', 403, $headers); + return Response::json('Invalid token', 403, $headers); } } @@ -44,7 +44,7 @@ class ApiCheck { } if (!Utils::isPro() && !$loggingIn) { - return Response::make('API requires pro plan', 403, $headers); + return Response::json('API requires pro plan', 403, $headers); } else { $key = Auth::check() ? Auth::user()->account->id : $request->getClientIp(); @@ -68,7 +68,7 @@ class ApiCheck { if ($new_hour_throttle > $hour) { $wait = ceil($new_hour_throttle - $hour); sleep(1); - return Response::make("Please wait {$wait} second(s)", 403, $headers); + return Response::json("Please wait {$wait} second(s)", 403, $headers); } Cache::put("hour_throttle:{$key}", $new_hour_throttle, 10); diff --git a/app/Http/routes.php b/app/Http/routes.php index 7f0af9a9893f..89268cced4dd 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -192,8 +192,7 @@ Route::group(['middleware' => 'api', 'prefix' => 'api/v1'], function() { Route::resource('ping', 'ClientApiController@ping'); Route::post('login', 'AccountApiController@login'); - Route::get('accounts', 'AccountApiController@index'); - Route::get('accounts/{account_key}', 'AccountApiController@show'); + Route::get('accounts', 'AccountApiController@show'); Route::resource('clients', 'ClientApiController'); Route::get('quotes/{client_id?}', 'QuoteApiController@index'); Route::resource('quotes', 'QuoteApiController'); @@ -418,7 +417,7 @@ if (!defined('CONTACT_EMAIL')) { define('NINJA_GATEWAY_CONFIG', 'NINJA_GATEWAY_CONFIG'); define('NINJA_WEB_URL', 'https://www.invoiceninja.com'); define('NINJA_APP_URL', 'https://app.invoiceninja.com'); - define('NINJA_VERSION', '2.4.5'); + define('NINJA_VERSION', '2.4.6'); define('NINJA_DATE', '2000-01-01'); define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com'); @@ -428,7 +427,6 @@ if (!defined('CONTACT_EMAIL')) { define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html'); define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/'); define('PHP_DATE_FORMATS', 'http://php.net/manual/en/function.date.php'); - define('GITTER_ROOM', 'hillelcoren/invoice-ninja'); define('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/affiliates/'); define('COUNT_FREE_DESIGNS', 4); diff --git a/app/Models/Client.php b/app/Models/Client.php index bb8f104dc246..9552b62609d1 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -59,6 +59,27 @@ class Client extends EntityModel return $this->hasMany('App\Models\Invoice'); } + public function getInvoices() + { + return $this->hasMany('App\Models\Invoice') + ->where('is_quote', '=', false) + ->where('is_recurring', '=', false); + } + + public function getRecurringInvoices() + { + return $this->hasMany('App\Models\Invoice') + ->where('is_quote', '=', false) + ->where('is_recurring', '=', true); + } + + public function getQuotes() + { + return $this->hasMany('App\Models\Invoice') + ->where('is_quote', '=', true) + ->where('is_recurring', '=', false); + } + public function payments() { return $this->hasMany('App\Models\Payment'); diff --git a/app/Models/Contact.php b/app/Models/Contact.php index 782a7e47424a..cc5f6d27963d 100644 --- a/app/Models/Contact.php +++ b/app/Models/Contact.php @@ -22,6 +22,11 @@ class Contact extends EntityModel public static $fieldEmail = 'Contact - Email'; public static $fieldPhone = 'Contact - Phone'; + public function account() + { + return $this->belongsTo('App\Models\Account'); + } + public function client() { return $this->belongsTo('App\Models\Client'); diff --git a/app/Models/Gateway.php b/app/Models/Gateway.php index 166c5a4929d6..55fc2056f45c 100644 --- a/app/Models/Gateway.php +++ b/app/Models/Gateway.php @@ -39,6 +39,11 @@ class Gateway extends Eloquent return '/images/gateways/logo_'.$this->provider.'.png'; } + public function isGateway($gatewayId) + { + return $this->id == $gatewayId; + } + public static function getPaymentTypeLinks() { $data = []; foreach (self::$paymentTypes as $type) { diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index ab4d9bc14be9..2655611b8f50 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -2,9 +2,9 @@ use Utils; use DateTime; -use App\Models\BalanceAffecting; use Illuminate\Database\Eloquent\SoftDeletes; - +use Laracasts\Presenter\PresentableTrait; +use App\Models\BalanceAffecting; use App\Events\QuoteWasCreated; use App\Events\QuoteWasUpdated; use App\Events\InvoiceWasCreated; @@ -14,10 +14,12 @@ use App\Events\QuoteInvitationWasEmailed; class Invoice extends EntityModel implements BalanceAffecting { + use PresentableTrait; use SoftDeletes { SoftDeletes::trashed as parentTrashed; } + protected $presenter = 'App\Ninja\Presenters\InvoicePresenter'; protected $dates = ['deleted_at']; protected $casts = [ diff --git a/app/Models/InvoiceItem.php b/app/Models/InvoiceItem.php index 396a1c713413..b7b3c8ffc8e9 100644 --- a/app/Models/InvoiceItem.php +++ b/app/Models/InvoiceItem.php @@ -16,4 +16,10 @@ class InvoiceItem extends EntityModel { return $this->belongsTo('App\Models\Product'); } + + public function account() + { + return $this->belongsTo('App\Models\Account'); + } + } diff --git a/app/Ninja/Mailers/ContactMailer.php b/app/Ninja/Mailers/ContactMailer.php index 9858ee66ccfc..1f485138fe99 100644 --- a/app/Ninja/Mailers/ContactMailer.php +++ b/app/Ninja/Mailers/ContactMailer.php @@ -92,6 +92,7 @@ class ContactMailer extends Mailer 'invoiceId' => $invoice->id, 'invitation' => $invitation, 'account' => $account, + 'invoice' => $invoice, ]; if ($account->attatchPDF()) { diff --git a/app/Ninja/Presenters/InvoicePresenter.php b/app/Ninja/Presenters/InvoicePresenter.php new file mode 100644 index 000000000000..5f3cd32270b1 --- /dev/null +++ b/app/Ninja/Presenters/InvoicePresenter.php @@ -0,0 +1,16 @@ +entity->getRequestedAmount(); + $currencyId = $this->entity->client->currency_id; + + return Utils::formatMoney($amount, $currencyId); + } + +} \ No newline at end of file diff --git a/app/Ninja/Repositories/NinjaRepository.php b/app/Ninja/Repositories/NinjaRepository.php new file mode 100644 index 000000000000..3f9c1fa4f19e --- /dev/null +++ b/app/Ninja/Repositories/NinjaRepository.php @@ -0,0 +1,18 @@ +first(); + + if (!$account) { + return; + } + + $account->pro_plan_paid = $proPlanPaid; + $account->save(); + } +} diff --git a/app/Ninja/Transformers/AccountTransformer.php b/app/Ninja/Transformers/AccountTransformer.php index e10938ebe235..ef075967d13d 100644 --- a/app/Ninja/Transformers/AccountTransformer.php +++ b/app/Ninja/Transformers/AccountTransformer.php @@ -12,14 +12,14 @@ class AccountTransformer extends TransformerAbstract 'clients', ]; - public function includeUsers($account) + public function includeUsers(Account $account) { - return $this->collection($account->users, new UserTransformer); + return $this->collection($account->users, new UserTransformer($account)); } - public function includeClients($account) + public function includeClients(Account $account) { - return $this->collection($account->clients, new ClientTransformer); + return $this->collection($account->clients, new ClientTransformer($account)); } public function transform(Account $account) @@ -27,6 +27,31 @@ class AccountTransformer extends TransformerAbstract return [ 'account_key' => $account->account_key, 'name' => $account->present()->name, + 'currency_id' => (int) $account->currency_id, + 'timezone_id' => (int) $account->timezone_id, + 'date_format_id' => (int) $account->date_format_id, + 'datetime_format_id' => (int) $account->datetime_format_id, + 'updated_at' => $account->updated_at, + 'deleted_at' => $account->deleted_at, + 'address1' => $account->address1, + 'address2' => $account->address2, + 'city' => $account->city, + 'state' => $account->state, + 'postal_code' => $account->postal_code, + 'country_id' => (int) $account->country_id, + 'invoice_terms' => $account->invoice_terms, + 'email_footer' => $account->email_footer, + 'industry_id' => (int) $account->industry_id, + 'size_id' => (int) $account->size_id, + 'invoice_taxes' => (bool) $account->invoice_taxes, + 'invoice_item_taxes' => (bool) $account->invoice_item_taxes, + 'invoice_design_id' => (int) $account->invoice_design_id, + 'work_phone' => $account->work_phone, + 'work_email' => $account->work_email, + 'language_id' => (int) $account->language_id, + 'fill_products' => (bool) $account->fill_products, + 'update_products' => (bool) $account->update_products, + 'vat_number' => $account->vat_number ]; } } \ No newline at end of file diff --git a/app/Ninja/Transformers/ClientTransformer.php b/app/Ninja/Transformers/ClientTransformer.php index c3041b063b18..3f03ed7e2bc2 100644 --- a/app/Ninja/Transformers/ClientTransformer.php +++ b/app/Ninja/Transformers/ClientTransformer.php @@ -1,48 +1,94 @@ collection($client->contacts, new ContactTransformer); + return $this->collection($client->contacts, new ContactTransformer($this->account)); } - public function includeInvoices($client) + public function includeInvoices(Client $client) { - $invoices = $client->invoices->filter(function($invoice) { - return !$invoice->is_quote && !$invoice->is_recurring; - }); - - return $this->collection($invoices, new InvoiceTransformer); + return $this->collection($client->getInvoices, new InvoiceTransformer($this->account, $client)); } - public function includeQuotes($client) + public function includeQuotes(Client $client) { - $invoices = $client->invoices->filter(function($invoice) { - return $invoice->is_quote && !$invoice->is_recurring; - }); - - return $this->collection($invoices, new QuoteTransformer); + return $this->collection($client->getQuotes, new QuoteTransformer($this->account, $client)); } public function transform(Client $client) { return [ - 'id' => (int) $client->public_id, + 'public_id' => (int) $client->public_id, 'name' => $client->name, 'balance' => (float) $client->balance, 'paid_to_date' => (float) $client->paid_to_date, + 'user_id' => (int) $client->user_id, + 'account_key' => $this->account->account_key, + 'updated_at' => $client->updated_at, + 'deleted_at' => $client->deleted_at, + 'address1' => $client->address1, + 'address2' => $client->address2, + 'city' => $client->city, + 'state' => $client->state, + 'postal_code' => $client->postal_code, + 'country_id' => (int) $client->country_id, + 'work_phone' => $client->work_phone, + 'private_notes' => $client->private_notes, + 'last_login' => $client->last_login, + 'website' => $client->website, + 'industry_id' => (int) $client->industry_id, + 'size_id' => (int) $client->size_id, + 'is_deleted' => (bool) $client->is_deleted, + 'payment_terms' => (int) $client->payment_terms, + 'vat_number' => $client->vat_number, + 'id_number' => $client->id_number, + 'language_id' => (int) $client->language_id ]; } } \ No newline at end of file diff --git a/app/Ninja/Transformers/ContactTransformer.php b/app/Ninja/Transformers/ContactTransformer.php index fb63952567fe..0752e504eaf4 100644 --- a/app/Ninja/Transformers/ContactTransformer.php +++ b/app/Ninja/Transformers/ContactTransformer.php @@ -1,18 +1,25 @@ (int) $contact->public_id, + 'public_id' => (int) $contact->public_id, 'first_name' => $contact->first_name, 'last_name' => $contact->last_name, 'email' => $contact->email, + 'user_id' => (int) $contact->user_id, + 'updated_at' => $contact->updated_at, + 'deleted_at' => $contact->deleted_at, + 'is_primary' => (bool) $contact->is_primary, + 'phone' => $contact->phone, + 'last_login' => $contact->last_login, + 'account_key' => $this->account->account_key ]; } } \ No newline at end of file diff --git a/app/Ninja/Transformers/EntityTransformer.php b/app/Ninja/Transformers/EntityTransformer.php new file mode 100644 index 000000000000..11ba0d1fc356 --- /dev/null +++ b/app/Ninja/Transformers/EntityTransformer.php @@ -0,0 +1,14 @@ +account = $account; + } +} diff --git a/app/Ninja/Transformers/InvoiceItemTransformer.php b/app/Ninja/Transformers/InvoiceItemTransformer.php index b3186afcebb2..3f72de9c847f 100644 --- a/app/Ninja/Transformers/InvoiceItemTransformer.php +++ b/app/Ninja/Transformers/InvoiceItemTransformer.php @@ -1,16 +1,28 @@ (int) $item->public_id, + 'public_id' => (int) $item->public_id, 'product_key' => $item->product_key, + 'account_key' => $this->account->account_key, + 'user_id' => (int) $item->user_id, + 'invoice_id' => (int) $item->invoice_id, + 'product_id' => (int) $item->product_id, + 'updated_at' => $item->updated_at, + 'deleted_at' => $item->deleted_at, + 'product_key' => $item->product_key, + 'notes' => $item->notes, + 'cost' => (float) $item->cost, + 'qty' => (float) $item->qty, + 'tax_name' => $item->tax_name, + 'tax_rate' => $item->tax_rate ]; } } \ No newline at end of file diff --git a/app/Ninja/Transformers/InvoiceTransformer.php b/app/Ninja/Transformers/InvoiceTransformer.php index 5e1dff91db2c..c5d47f14d3e3 100644 --- a/app/Ninja/Transformers/InvoiceTransformer.php +++ b/app/Ninja/Transformers/InvoiceTransformer.php @@ -1,18 +1,41 @@ client = $client; + } + protected $defaultIncludes = [ 'invoice_items', ]; - public function includeInvoiceItems($invoice) + public function includeInvoiceItems(Invoice $invoice) { - return $this->collection($invoice->invoice_items, new InvoiceItemTransformer); + return $this->collection($invoice->invoice_items, new InvoiceItemTransformer($this->account)); } public function transform(Invoice $invoice) @@ -22,6 +45,33 @@ class InvoiceTransformer extends TransformerAbstract 'invoice_number' => $invoice->invoice_number, 'amount' => (float) $invoice->amount, 'balance' => (float) $invoice->balance, + 'client_id' => (int) $this->client->public_id, + 'invoice_status_id' => (int) $invoice->invoice_status_id, + 'updated_at' => $invoice->updated_at, + 'deleted_at' => $invoice->deleted_at, + 'invoice_number' => $invoice->invoice_number, + 'discount' => (double) $invoice->discount, + 'po_number' => $invoice->po_number, + 'invoice_date' => $invoice->invoice_date, + 'due_date' => $invoice->due_date, + 'terms' => $invoice->terms, + 'public_notes' => $invoice->public_notes, + 'is_deleted' => (bool) $invoice->is_deleted, + 'is_recurring' => (bool) $invoice->is_recurring, + 'frequency_id' => (int) $invoice->frequency_id, + 'start_date' => $invoice->start_date, + 'end_date' => $invoice->end_date, + 'last_sent_date' => $invoice->last_sent_date, + 'recurring_invoice_id' => (int) $invoice->recurring_invoice_id, + 'tax_name' => $invoice->tax_name, + 'tax_rate' => (float) $invoice->tax_rate, + 'amount' => (float) $invoice->amount, + 'balance' => (float) $invoice->balance, + 'is_amount_discount' => (bool) $invoice->is_amount_discount, + 'invoice_footer' => $invoice->invoice_footer, + 'partial' => (float) $invoice->partial, + 'has_tasks' => (bool) $invoice->has_tasks, + 'auto_bill' => (bool) $invoice->auto_bill ]; } } \ No newline at end of file diff --git a/app/Ninja/Transformers/QuoteTransformer.php b/app/Ninja/Transformers/QuoteTransformer.php index 7b3cc752d5d0..dbb2f669fecc 100644 --- a/app/Ninja/Transformers/QuoteTransformer.php +++ b/app/Ninja/Transformers/QuoteTransformer.php @@ -2,9 +2,8 @@ use App\Models\Invoice; use League\Fractal; -use League\Fractal\TransformerAbstract; -class QuoteTransformer extends TransformerAbstract +class QuoteTransformer extends EntityTransformer { protected $defaultIncludes = [ 'invoice_items', @@ -18,7 +17,7 @@ class QuoteTransformer extends TransformerAbstract public function transform(Invoice $invoice) { return [ - 'id' => (int) $invoice->public_id, + 'public_id' => (int) $invoice->public_id, 'quote_number' => $invoice->invoice_number, 'amount' => (float) $invoice->amount, ]; diff --git a/app/Ninja/Transformers/UserAccountTransformer.php b/app/Ninja/Transformers/UserAccountTransformer.php index 2b3724a2f601..7f82ca3183b7 100644 --- a/app/Ninja/Transformers/UserAccountTransformer.php +++ b/app/Ninja/Transformers/UserAccountTransformer.php @@ -1,11 +1,12 @@ tokenName = $tokenName; } public function includeUser(User $user) { - return $this->item($user, new UserTransformer); + return $this->item($user, new UserTransformer($this->account)); } public function transform(User $user) diff --git a/app/Ninja/Transformers/UserTransformer.php b/app/Ninja/Transformers/UserTransformer.php index f088bed87904..e73ad2bd0450 100644 --- a/app/Ninja/Transformers/UserTransformer.php +++ b/app/Ninja/Transformers/UserTransformer.php @@ -1,18 +1,27 @@ (int) ($user->public_id + 1), + 'public_id' => (int) ($user->public_id + 1), 'first_name' => $user->first_name, 'last_name' => $user->last_name, 'email' => $user->email, + 'account_key' => $user->account->account_key, + 'updated_at' => $user->updated_at, + 'deleted_at' => $user->deleted_at, + 'phone' => $user->phone, + 'username' => $user->username, + 'registered' => (bool) $user->registered, + 'confirmed' => (bool) $user->confirmed, + 'oauth_user_id' => $user->oauth_user_id, + 'oauth_provider_id' => $user->oauth_provider_id ]; } } \ No newline at end of file diff --git a/app/Services/ClientService.php b/app/Services/ClientService.php index f28e5d25d023..3093df1f3ae6 100644 --- a/app/Services/ClientService.php +++ b/app/Services/ClientService.php @@ -5,16 +5,17 @@ use URL; use Auth; use App\Services\BaseService; use App\Ninja\Repositories\ClientRepository; - +use App\Ninja\Repositories\NinjaRepository; class ClientService extends BaseService { protected $clientRepo; protected $datatableService; - public function __construct(ClientRepository $clientRepo, DatatableService $datatableService) + public function __construct(ClientRepository $clientRepo, DatatableService $datatableService, NinjaRepository $ninjaRepo) { $this->clientRepo = $clientRepo; + $this->ninjaRepo = $ninjaRepo; $this->datatableService = $datatableService; } @@ -25,6 +26,10 @@ class ClientService extends BaseService public function save($data) { + if (Auth::user()->account->isNinjaAccount() && isset($data['pro_plan_paid'])) { + $this->ninjaRepo->updateProPlanPaid($data['public_id'], $data['pro_plan_paid']); + } + return $this->clientRepo->save($data); } @@ -41,7 +46,7 @@ class ClientService extends BaseService [ 'name', function ($model) { - return link_to("clients/{$model->public_id}", $model->name); + return link_to("clients/{$model->public_id}", $model->name ?: ''); } ], [ @@ -53,7 +58,7 @@ class ClientService extends BaseService [ 'email', function ($model) { - return link_to("clients/{$model->public_id}", $model->email); + return link_to("clients/{$model->public_id}", $model->email ?: ''); } ], [ diff --git a/composer.json b/composer.json index 20c80fd00036..476b304de727 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,8 @@ "justinbusschau/omnipay-secpay": "~2.0", "labs7in0/omnipay-wechat": "dev-master", "collizo4sky/omnipay-wepay": "~1.0", - "laracasts/presenter": "dev-master" + "laracasts/presenter": "dev-master", + "jlapp/swaggervel": "master-dev" }, "require-dev": { "phpunit/phpunit": "~4.0", diff --git a/composer.lock b/composer.lock index dc3c86d86fa1..5280b5bfb5ff 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "4c2d5d48a648e380f3acf2943b91e6bc", + "hash": "fb15622e77287d516219e55ebb01ea3e", "packages": [ { "name": "agmscode/omnipay-agms", @@ -1517,16 +1517,16 @@ }, { "name": "doctrine/inflector", - "version": "v1.0.1", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604" + "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/0bcb2e79d8571787f18b7eb036ed3d004908e604", - "reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", + "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", "shasum": "" }, "require": { @@ -1538,7 +1538,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1.x-dev" } }, "autoload": { @@ -1580,7 +1580,7 @@ "singularize", "string" ], - "time": "2014-12-20 21:24:13" + "time": "2015-11-06 14:35:42" }, { "name": "doctrine/lexer", @@ -2464,6 +2464,51 @@ ], "time": "2015-03-11 20:06:43" }, + { + "name": "jlapp/swaggervel", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/slampenny/Swaggervel.git", + "reference": "ea47fafde4984278e27a8044a1b1b0bcfd79130c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slampenny/Swaggervel/zipball/ea47fafde4984278e27a8044a1b1b0bcfd79130c", + "reference": "ea47fafde4984278e27a8044a1b1b0bcfd79130c", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "zircote/swagger-php": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Jlapp\\Swaggervel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "jlapp", + "email": "jordan@jordanlapp.com" + } + ], + "description": "A great way to integrate Swagger into Laravel", + "keywords": [ + "L4", + "api", + "documentation", + "l5", + "laravel", + "swagger" + ], + "time": "2015-08-18 15:33:39" + }, { "name": "jsanc623/phpbenchtime", "version": "2.1.0", @@ -6968,6 +7013,66 @@ ], "description": "A Swiftmailer Transport for Postmark.", "time": "2015-03-19 13:06:11" + }, + { + "name": "zircote/swagger-php", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/zircote/swagger-php.git", + "reference": "f6624cc067d7894ec32943f5b94cf282c683f7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zircote/swagger-php/zipball/f6624cc067d7894ec32943f5b94cf282c683f7c7", + "reference": "f6624cc067d7894ec32943f5b94cf282c683f7c7", + "shasum": "" + }, + "require": { + "doctrine/annotations": "*", + "php": ">=5.4.0", + "symfony/finder": "*" + }, + "require-dev": { + "zendframework/zend-form": "*" + }, + "bin": [ + "bin/swagger" + ], + "type": "library", + "autoload": { + "psr-4": { + "Swagger\\": "src" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache2" + ], + "authors": [ + { + "name": "Robert Allen", + "email": "zircote@gmail.com", + "homepage": "http://www.zircote.com" + }, + { + "name": "Bob Fanger", + "email": "bfanger@gmail.com", + "homepage": "http://bfanger.nl" + } + ], + "description": "Swagger-PHP - Generate interactive documentation for your RESTful API using phpdoc annotations", + "homepage": "https://github.com/zircote/swagger-php/", + "keywords": [ + "api", + "json", + "rest", + "service discovery" + ], + "time": "2015-10-18 13:05:54" } ], "packages-dev": [ @@ -8377,7 +8482,8 @@ "dercoder/omnipay-paysafecard": 20, "meebio/omnipay-secure-trading": 20, "labs7in0/omnipay-wechat": 20, - "laracasts/presenter": 20 + "laracasts/presenter": 20, + "jlapp/swaggervel": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/config/app.php b/config/app.php index e5fcf2eebc9a..4aa26f919466 100644 --- a/config/app.php +++ b/config/app.php @@ -150,7 +150,7 @@ return [ 'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', 'Illuminate\Html\HtmlServiceProvider', 'Laravel\Socialite\SocialiteServiceProvider', - + 'Jlapp\Swaggervel\SwaggervelServiceProvider', /* * Application Service Providers... diff --git a/config/swaggervel.php b/config/swaggervel.php new file mode 100644 index 000000000000..341b47ed830a --- /dev/null +++ b/config/swaggervel.php @@ -0,0 +1,97 @@ + storage_path() . '/docs', + + /* + |-------------------------------------------------------------------------- + | Relative path to access parsed swagger annotations. + |-------------------------------------------------------------------------- + */ + 'doc-route' => 'docs', + + /* + |-------------------------------------------------------------------------- + | Absolute path to directory containing the swagger annotations are stored. + |-------------------------------------------------------------------------- + */ + "app-dir" => "app", + + /* + |-------------------------------------------------------------------------- + | Absolute path to directories that you would like to exclude from swagger generation + |-------------------------------------------------------------------------- + */ + "excludes" => array( + storage_path(), + base_path()."/tests", + base_path()."/resources/views", + base_path()."/config", + base_path()."/vendor" + ), + + /* + |-------------------------------------------------------------------------- + | Turn this off to remove swagger generation on production + |-------------------------------------------------------------------------- + */ + "generateAlways" => env('APP_DEBUG'), + + "api-key" => "auth_token", + + /* + |-------------------------------------------------------------------------- + | Edit to set the api's version number + |-------------------------------------------------------------------------- + */ + "default-api-version" => "v1", + + /* + |-------------------------------------------------------------------------- + | Edit to set the swagger version number + |-------------------------------------------------------------------------- + */ + "default-swagger-version" => "2.0", + + /* + |-------------------------------------------------------------------------- + | Edit to set the api's base path + |-------------------------------------------------------------------------- + */ + "default-base-path" => "", + + /* + |-------------------------------------------------------------------------- + | Edit to trust the proxy's ip address - needed for AWS Load Balancer + |-------------------------------------------------------------------------- + */ + "behind-reverse-proxy" => false, + /* + |-------------------------------------------------------------------------- + | Uncomment to add response headers when swagger is generated + |-------------------------------------------------------------------------- + */ + /*"viewHeaders" => array( + 'Content-Type' => 'text/plain' + ),*/ + + /* + |-------------------------------------------------------------------------- + | Uncomment to add request headers when swagger performs requests + |-------------------------------------------------------------------------- + */ + /*"requestHeaders" => array( + 'TestMe' => 'testValue' + ),*/ +); diff --git a/public/css/built.css b/public/css/built.css index 816fafacb28a..10af8e73e106 100644 --- a/public/css/built.css +++ b/public/css/built.css @@ -2354,7 +2354,7 @@ body { background: #f8f8f8 !important; font-size: 15px; } html { - overflow-y: scroll; + /* overflow-y: scroll; */ } .bold { font-weight: 700; } a {color:#0b4d78;} @@ -3377,8 +3377,4 @@ ul.user-accounts a:hover div.remove { width: 2px; content: ""; background-color: #e37329; -} - -.gitter-open-chat-button { - background-color: #0b4d78 !important; } \ No newline at end of file diff --git a/public/css/style.css b/public/css/style.css index 35480c54911f..7f0aca5307d5 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -3,7 +3,7 @@ body { background: #f8f8f8 !important; font-size: 15px; } html { - overflow-y: scroll; + /* overflow-y: scroll; */ } .bold { font-weight: 700; } a {color:#0b4d78;} @@ -1026,8 +1026,4 @@ ul.user-accounts a:hover div.remove { width: 2px; content: ""; background-color: #e37329; -} - -.gitter-open-chat-button { - background-color: #0b4d78 !important; } \ No newline at end of file diff --git a/public/images/pro_plan/white_label_after.png b/public/images/pro_plan/white_label_after.png new file mode 100644 index 000000000000..e5201dffcab2 Binary files /dev/null and b/public/images/pro_plan/white_label_after.png differ diff --git a/public/images/pro_plan/white_label_before.png b/public/images/pro_plan/white_label_before.png new file mode 100644 index 000000000000..66a3ebde7176 Binary files /dev/null and b/public/images/pro_plan/white_label_before.png differ diff --git a/public/js/built.js b/public/js/built.js index 4127db4eafd4..7e1ea06b3edf 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -29880,11 +29880,11 @@ links:["Africa/Abidjan|Africa/Bamako","Africa/Abidjan|Africa/Banjul","Africa/Abi var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; var isFirefox = typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; -var isChrome = !!window.chrome && !isOpera; // Chrome 1+ +var isEdge = navigator.userAgent.indexOf('Edge/') >= 0; +var isChrome = !!window.chrome && !isOpera && !isEdge; // Chrome 1+ var isChromium = isChrome && navigator.userAgent.indexOf('Chromium') >= 0; var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6 - var invoiceOld; var refreshTimer; function generatePDF(invoice, javascript, force, cb) { @@ -31628,7 +31628,7 @@ function GetPdfMake(invoice, javascript, callback) { } // only show the footer on the last page - if (key === 'footer') { + if (invoice.is_pro && key === 'footer') { return function(page, pages) { return page === pages ? val : ''; } @@ -31638,6 +31638,7 @@ function GetPdfMake(invoice, javascript, callback) { if (key === 'text') { val = NINJA.parseMarkdownText(val, true); } + /* if (key === 'stack') { val = NINJA.parseMarkdownStack(val); @@ -32231,7 +32232,7 @@ NINJA.parseRegExpLine = function(line, regExp, formatter, groupText) var parts = []; var lastIndex = 0; - while (match = regExp.exec(line + '\n')) { + while (match = regExp.exec(line)) { if (match.index > lastIndex) { parts.push(line.substring(lastIndex, match.index)); } diff --git a/public/js/pdf.pdfmake.js b/public/js/pdf.pdfmake.js index 4a795553b763..fd57a6bf6270 100644 --- a/public/js/pdf.pdfmake.js +++ b/public/js/pdf.pdfmake.js @@ -55,7 +55,7 @@ function GetPdfMake(invoice, javascript, callback) { } // only show the footer on the last page - if (key === 'footer') { + if (invoice.is_pro && key === 'footer') { return function(page, pages) { return page === pages ? val : ''; } @@ -65,6 +65,7 @@ function GetPdfMake(invoice, javascript, callback) { if (key === 'text') { val = NINJA.parseMarkdownText(val, true); } + /* if (key === 'stack') { val = NINJA.parseMarkdownStack(val); diff --git a/public/js/script.js b/public/js/script.js index 61d58c7f8a74..da30e0d4c4ac 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -2,11 +2,11 @@ var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; var isFirefox = typeof InstallTrigger !== 'undefined'; // Firefox 1.0+ var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0; -var isChrome = !!window.chrome && !isOpera; // Chrome 1+ +var isEdge = navigator.userAgent.indexOf('Edge/') >= 0; +var isChrome = !!window.chrome && !isOpera && !isEdge; // Chrome 1+ var isChromium = isChrome && navigator.userAgent.indexOf('Chromium') >= 0; var isIE = /*@cc_on!@*/false || !!document.documentMode; // At least IE6 - var invoiceOld; var refreshTimer; function generatePDF(invoice, javascript, force, cb) { diff --git a/resources/lang/da/texts.php b/resources/lang/da/texts.php index 85ae4b1df9e1..55af0a5ad7f5 100644 --- a/resources/lang/da/texts.php +++ b/resources/lang/da/texts.php @@ -882,6 +882,32 @@ 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/de/texts.php b/resources/lang/de/texts.php index 85827ff5bd21..26cea549d170 100644 --- a/resources/lang/de/texts.php +++ b/resources/lang/de/texts.php @@ -891,5 +891,24 @@ return array( 'default_invoice_terms' => 'Standard-Rechnungsbedingungen', 'default_invoice_footer' => 'Standard-Rechnungsfußzeile', 'quote_footer' => 'Angebots-Fußzeile', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 2a0ffc3986db..5d0993ebad58 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -470,7 +470,7 @@ return array( 'id_number' => 'ID Number', 'white_label_link' => 'White label', - 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the top of the client pages.', + 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the client portal and help support our project.', 'white_label_header' => 'White Label', 'bought_white_label' => 'Successfully enabled white label license', 'white_labeled' => 'White labeled', @@ -908,5 +908,9 @@ return array( 'restored_recurring_invoice' => 'Successfully restored recurring invoice', 'archived' => 'Archived', 'untitled_account' => 'Untitled Company', + + 'before' => 'Before', + 'after' => 'After', + ); diff --git a/resources/lang/es/texts.php b/resources/lang/es/texts.php index b989926cb1bf..a9f91b1394b0 100644 --- a/resources/lang/es/texts.php +++ b/resources/lang/es/texts.php @@ -860,6 +860,32 @@ return array( 'payment' => 'pago', 'system' => 'Sistema', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/es_ES/texts.php b/resources/lang/es_ES/texts.php index 7c59cdc829e3..74c16fb5e8ea 100644 --- a/resources/lang/es_ES/texts.php +++ b/resources/lang/es_ES/texts.php @@ -881,5 +881,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/fr/texts.php b/resources/lang/fr/texts.php index 8651fb475503..28662b5f3cc7 100644 --- a/resources/lang/fr/texts.php +++ b/resources/lang/fr/texts.php @@ -875,5 +875,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/fr_CA/texts.php b/resources/lang/fr_CA/texts.php index 50e4f43e288c..0658ff11f552 100644 --- a/resources/lang/fr_CA/texts.php +++ b/resources/lang/fr_CA/texts.php @@ -875,5 +875,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/it/texts.php b/resources/lang/it/texts.php index fece6b644e6e..3f4d458f3412 100644 --- a/resources/lang/it/texts.php +++ b/resources/lang/it/texts.php @@ -465,7 +465,7 @@ return array( 'id_number' => 'ID Number', 'white_label_link' => 'White label', - 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the top of the client pages.', + 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the client portal and help support our project.', 'white_label_header' => 'White Label', 'bought_white_label' => 'Successfully enabled white label license', 'white_labeled' => 'White labeled', @@ -877,5 +877,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/lt/texts.php b/resources/lang/lt/texts.php index 9bd47ae4adf0..328a5058720c 100644 --- a/resources/lang/lt/texts.php +++ b/resources/lang/lt/texts.php @@ -474,7 +474,7 @@ return array( 'id_number' => 'ID Number', 'white_label_link' => 'White label', - 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the top of the client pages.', + 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the client portal and help support our project.', 'white_label_header' => 'White Label', 'bought_white_label' => 'Successfully enabled white label license', 'white_labeled' => 'White labeled', @@ -884,6 +884,32 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/nb_NO/texts.php b/resources/lang/nb_NO/texts.php index 16fd7c7bbb60..e92a62fca11b 100644 --- a/resources/lang/nb_NO/texts.php +++ b/resources/lang/nb_NO/texts.php @@ -472,7 +472,7 @@ return array( 'id_number' => 'ID Number', 'white_label_link' => 'White label', - 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the top of the client pages.', + 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the client portal and help support our project.', 'white_label_header' => 'White Label', 'bought_white_label' => 'Successfully enabled white label license', 'white_labeled' => 'White labeled', @@ -882,5 +882,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); \ No newline at end of file diff --git a/resources/lang/nl/texts.php b/resources/lang/nl/texts.php index 2b8b55f98680..6ab529243a44 100644 --- a/resources/lang/nl/texts.php +++ b/resources/lang/nl/texts.php @@ -877,5 +877,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/pt_BR/texts.php b/resources/lang/pt_BR/texts.php index dce56a1e39d8..21b1f6119258 100644 --- a/resources/lang/pt_BR/texts.php +++ b/resources/lang/pt_BR/texts.php @@ -887,5 +887,21 @@ return array( 'free' => 'Grátis', 'quote_is_approved' => 'Orçamento aprovado.', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/lang/sv/texts.php b/resources/lang/sv/texts.php index e605fd758f7b..44bd13b1e030 100644 --- a/resources/lang/sv/texts.php +++ b/resources/lang/sv/texts.php @@ -880,5 +880,31 @@ return array( 'payment' => 'Payment', 'system' => 'System', + 'signature' => 'Email Signature', + 'default_messages' => 'Default Messages', + 'quote_terms' => 'Quote Terms', + 'default_quote_terms' => 'Default Quote Terms', + 'default_invoice_terms' => 'Default Invoice Terms', + 'default_invoice_footer' => 'Default Invoice Footer', + 'quote_footer' => 'Quote Footer', + 'free' => 'Free', + + 'quote_is_approved' => 'This quote is approved', + 'apply_credit' => 'Apply Credit', + 'system_settings' => 'System Settings', + 'archive_token' => 'Archive Token', + 'archived_token' => 'Successfully archived token', + 'archive_user' => 'Archive User', + 'archived_user' => 'Successfully archived user', + 'archive_account_gateway' => 'Archive Gateway', + 'archived_account_gateway' => 'Successfully archived gateway', + 'archive_recurring_invoice' => 'Archive Recurring Invoice', + 'archived_recurring_invoice' => 'Successfully archived recurring invoice', + 'delete_recurring_invoice' => 'Delete Recurring Invoice', + 'deleted_recurring_invoice' => 'Successfully deleted recurring invoice', + 'restore_recurring_invoice' => 'Restore Recurring Invoice', + 'restored_recurring_invoice' => 'Successfully restored recurring invoice', + 'archived' => 'Archived', + 'untitled_account' => 'Untitled Company', ); diff --git a/resources/views/accounts/details.blade.php b/resources/views/accounts/details.blade.php index d7e669d77652..3d8a0d3f42c4 100644 --- a/resources/views/accounts/details.blade.php +++ b/resources/views/accounts/details.blade.php @@ -18,9 +18,12 @@ - {!! Former::open_for_files()->addClass('warn-on-exit')->rules(array( - 'name' => 'required', - )) !!} + {!! Former::open_for_files() + ->addClass('warn-on-exit') + ->autocomplete('on') + ->rules([ + 'name' => 'required' + ]) !!} {{ Former::populate($account) }} @@ -62,13 +65,14 @@
{{ trans('texts.white_label_text')}}
+