Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Juan Luis Baptiste 2015-11-09 17:36:51 -05:00
commit 657e729ab7
65 changed files with 1411 additions and 222 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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());

View File

@ -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);
}

View File

@ -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();

View File

@ -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();

View File

@ -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()

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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');

View File

@ -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');

View File

@ -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) {

View File

@ -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 = [

View File

@ -16,4 +16,10 @@ class InvoiceItem extends EntityModel
{
return $this->belongsTo('App\Models\Product');
}
public function account()
{
return $this->belongsTo('App\Models\Account');
}
}

View File

@ -92,6 +92,7 @@ class ContactMailer extends Mailer
'invoiceId' => $invoice->id,
'invitation' => $invitation,
'account' => $account,
'invoice' => $invoice,
];
if ($account->attatchPDF()) {

View File

@ -0,0 +1,16 @@
<?php namespace App\Ninja\Presenters;
use Utils;
use Laracasts\Presenter\Presenter;
class InvoicePresenter extends Presenter {
public function balance_due()
{
$amount = $this->entity->getRequestedAmount();
$currencyId = $this->entity->client->currency_id;
return Utils::formatMoney($amount, $currencyId);
}
}

View File

@ -0,0 +1,18 @@
<?php namespace App\Ninja\Repositories;
use App\Models\Account;
class NinjaRepository
{
public function updateProPlanPaid($clientPublicId, $proPlanPaid)
{
$account = Account::whereId($clientPublicId)->first();
if (!$account) {
return;
}
$account->pro_plan_paid = $proPlanPaid;
$account->save();
}
}

View File

@ -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
];
}
}

View File

@ -1,48 +1,94 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\Client;
use App\Models\Contact;
use League\Fractal;
use League\Fractal\TransformerAbstract;
class ClientTransformer extends TransformerAbstract
/**
* @SWG\Definition(definition="Client", @SWG\Xml(name="Client"))
*/
class ClientTransformer extends EntityTransformer
{
/**
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
* @SWG\Property(property="balance", type="float", example=10, readOnly=true)
* @SWG\Property(property="paid_to_date", type="float", example=10, readOnly=true)
* @SWG\Property(property="user_id", type="integer", example=1)
* @SWG\Property(property="account_key", type="string", example="123456")
* @SWG\Property(property="updated_at", type="date-time", example="2016-01-01 12:10:00")
* @SWG\Property(property="deleted_at", type="date-time", example="2016-01-01 12:10:00")
* @SWG\Property(property="address1", type="string", example="10 Main St.")
* @SWG\Property(property="address2", type="string", example="1st Floor")
* @SWG\Property(property="city", type="string", example="New York")
* @SWG\Property(property="state", type="string", example="NY")
* @SWG\Property(property="postal_code", type="string", example=10010)
* @SWG\Property(property="country_id", type="integer", example=840)
* @SWG\Property(property="work_phone", type="string", example="(212) 555-1212")
* @SWG\Property(property="private_notes", type="string", example="Notes...")
* @SWG\Property(property="last_login", type="date-time", example="2016-01-01 12:10:00")
* @SWG\Property(property="website", type="string", example="http://www.example.com")
* @SWG\Property(property="industry_id", type="integer", example=1)
* @SWG\Property(property="size_id", type="integer", example=1)
* @SWG\Property(property="is_deleted", type="boolean", example=false)
* @SWG\Property(property="payment_terms", type="", example=30)
* @SWG\Property(property="custom_value1", type="string", example="Value")
* @SWG\Property(property="custom_value2", type="string", example="Value")
* @SWG\Property(property="vat_number", type="string", example="123456")
* @SWG\Property(property="id_number", type="string", example="123456")
* @SWG\Property(property="language_id", type="integer", example=1)
*/
protected $defaultIncludes = [
'contacts',
'invoices',
'quotes',
];
public function includeContacts($client)
public function includeContacts(Client $client)
{
return $this->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
];
}
}

View File

@ -1,18 +1,25 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\Contact;
use League\Fractal;
use League\Fractal\TransformerAbstract;
class ContactTransformer extends TransformerAbstract
class ContactTransformer extends EntityTransformer
{
public function transform(Contact $contact)
{
return [
'id' => (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
];
}
}

View File

@ -0,0 +1,14 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use League\Fractal\TransformerAbstract;
class EntityTransformer extends TransformerAbstract
{
protected $account;
public function __construct(Account $account)
{
$this->account = $account;
}
}

View File

@ -1,16 +1,28 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\InvoiceItem;
use League\Fractal;
use League\Fractal\TransformerAbstract;
class InvoiceItemTransformer extends TransformerAbstract
class InvoiceItemTransformer extends EntityTransformer
{
public function transform(InvoiceItem $item)
{
return [
'id' => (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
];
}
}

View File

@ -1,18 +1,41 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\Client;
use App\Models\Invoice;
use League\Fractal;
use League\Fractal\TransformerAbstract;
class InvoiceTransformer extends TransformerAbstract
/**
* @SWG\Definition(definition="Invoice", required={"invoice_number"}, @SWG\Xml(name="Invoice"))
*/
class InvoiceTransformer extends EntityTransformer
{
/**
* @SWG\Property(property="id", type="integer", example=1, readOnly=true)
* @SWG\Property(property="amount", type="float", example=10, readOnly=true)
* @SWG\Property(property="balance", type="float", example=10, readOnly=true)
* @SWG\Property(property="client_id", type="integer", example=1)
* @SWG\Property(property="invoice_number", type="string", example="0001")
* @SWG\Property(property="invoice_status_id", type="integer", example=1)
*/
protected $client;
public function __construct(Account $account, Client $client)
{
parent::__construct($account);
$this->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
];
}
}

View File

@ -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,
];

View File

@ -1,11 +1,12 @@
<?php namespace App\Ninja\Transformers;
use App\Models\User;
use App\Models\Account;
use League\Fractal;
use League\Fractal\TransformerAbstract;
use League\Fractal\Resource\Item;
class UserAccountTransformer extends TransformerAbstract
class UserAccountTransformer extends EntityTransformer
{
protected $defaultIncludes = [
'user'
@ -13,14 +14,16 @@ class UserAccountTransformer extends TransformerAbstract
protected $tokenName;
public function __construct($tokenName)
public function __construct(Account $account, $tokenName)
{
parent::__construct($account);
$this->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)

View File

@ -1,18 +1,27 @@
<?php namespace App\Ninja\Transformers;
use App\Models\Account;
use App\Models\User;
use League\Fractal;
use League\Fractal\TransformerAbstract;
class UserTransformer extends TransformerAbstract
class UserTransformer extends EntityTransformer
{
public function transform(User $user)
{
return [
'id' => (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
];
}
}

View File

@ -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 ?: '');
}
],
[

View File

@ -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",

122
composer.lock generated
View File

@ -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,

View File

@ -150,7 +150,7 @@ return [
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
'Illuminate\Html\HtmlServiceProvider',
'Laravel\Socialite\SocialiteServiceProvider',
'Jlapp\Swaggervel\SwaggervelServiceProvider',
/*
* Application Service Providers...

97
config/swaggervel.php Normal file
View File

@ -0,0 +1,97 @@
<?php
/**
* Created by PhpStorm.
* User: Jordan
* Date: 04/07/14
* Time: 3:54 PM
*/
return array(
/*
|--------------------------------------------------------------------------
| Absolute path to location where parsed swagger annotations will be stored
|--------------------------------------------------------------------------
*/
'doc-dir' => 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'
),*/
);

View File

@ -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;
}

View File

@ -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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -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));
}

View File

@ -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);

View File

@ -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) {

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -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',
);

View File

@ -18,9 +18,12 @@
</style>
{!! 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 @@
</div>
<div class="panel-body form-padding-right">
{!! Former::text('address1') !!}
{!! Former::text('address2') !!}
{!! Former::text('city') !!}
{!! Former::text('state') !!}
{!! Former::text('postal_code') !!}
{!! Former::select('country_id')->addOption('','')
->fromQuery($countries, 'name', 'id') !!}
{!! Former::text('address1')->autocomplete('address-line1') !!}
{!! Former::text('address2')->autocomplete('address-line2') !!}
{!! Former::text('city')->autocomplete('address-level2') !!}
{!! Former::text('state')->autocomplete('address-level1') !!}
{!! Former::text('postal_code')->autocomplete('postal-code') !!}
{!! Former::select('country_id')
->addOption('','')
->fromQuery($countries, 'name', 'id') !!}
</div>
</div>

View File

@ -14,10 +14,13 @@
<div class="row">
{!! Former::open($url)
->autocomplete('off')
->rules(
['email' => 'email']
)->addClass('col-md-12 warn-on-exit')
->method($method) !!}
@include('partials.autocomplete_fix')
@if ($client)
{!! Former::populate($client) !!}
@ -127,6 +130,20 @@
->fromQuery($industries, 'name', 'id') !!}
{!! Former::textarea('private_notes') !!}
@if (isset($proPlanPaid))
{!! Former::populateField('pro_plan_paid', $proPlanPaid) !!}
{!! Former::text('pro_plan_paid')
->data_date_format('yyyy-mm-dd')
->addGroupClass('pro_plan_paid_date')
->append('<i class="glyphicon glyphicon-calendar"></i>') !!}
<script type="text/javascript">
$(function() {
$('#pro_plan_paid').datepicker();
});
</script>
@endif
</div>
</div>

View File

@ -251,17 +251,12 @@
</div>
@endif
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
<script type="text/javascript">
$(function() {
$('.normalDropDown:not(.dropdown-toggle)').click(function() {
window.location = '{{ URL::to('invoices/create') }}';
});
});
((window.gitter = {}).chat = {}).options = {
room: '{{ GITTER_ROOM }}',
};
</script>
@stop

View File

@ -4,7 +4,7 @@
<meta charset="utf-8">
</head>
<body>
@if (false)
@if (Utils::isNinjaDev())
@include('emails.view_action', ['link' => $link, 'entityType' => $entityType])
@endif
{!! $body !!}

View File

@ -1,17 +1,36 @@
<script type="application/ld+json">
{
"@context":"http://schema.org",
"@type":"EmailMessage",
"description":"View your {{ $entityType }}",
"action": {
"@type": "ViewAction",
"url": "{!! $link !!}",
"name": "View {{ $entityType }}"
},
"publisher": {
"@type": "Organization",
"name": "Invoice Ninja",
"url": "{!! NINJA_WEB_URL !!}"
}
}
[
@if ($entityType == ENTITY_INVOICE)
{
"@context": "http://schema.org",
"@type": "Invoice",
"paymentStatus": "PaymentDue",
@if ($invoice->due_date)
"paymentDue": "{{ $invoice->due_date }}T00:00:00+00:00",
@endif
"provider": {
"@type": "Organization",
"name": "{{ $account->getDisplayName() }}"
},
"broker": {
"@type": "Organization",
"name": "Invoice Ninja",
"url": "{!! NINJA_WEB_URL !!}"
},
"totalPaymentDue": {
"@type": "PriceSpecification",
"price": "{{ $invoice->present()->balance_due }}"
}
},
@endif
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"action": {
"@type": "ViewAction",
"url": "{!! $link !!}",
"name": "{{ trans("view_{$entityType}") }}"
}
}
]
</script>

View File

@ -539,7 +539,7 @@
<div style="background-color: #fff; padding-right:20px" id="signUpDiv" onkeyup="validateSignUp()" onclick="validateSignUp()" onkeydown="checkForEnter(event)">
<br/>
{!! Former::open('signup/submit')->addClass('signUpForm') !!}
{!! Former::open('signup/submit')->addClass('signUpForm')->autocomplete('on') !!}
@if (Auth::check())
{!! Former::populateField('new_first_name', Auth::user()->first_name) !!}
@ -580,10 +580,23 @@
@endif
{{ Former::setOption('TwitterBootstrap3.labelWidths.large', 1) }}
{{ Former::setOption('TwitterBootstrap3.labelWidths.small', 1) }}
{!! Former::text('new_first_name')->placeholder(trans('texts.first_name'))->label(' ') !!}
{!! Former::text('new_last_name')->placeholder(trans('texts.last_name'))->label(' ') !!}
{!! Former::text('new_email')->placeholder(trans('texts.email'))->label(' ') !!}
{!! Former::password('new_password')->placeholder(trans('texts.password'))->label(' ') !!}
{!! Former::text('new_first_name')
->placeholder(trans('texts.first_name'))
->autocomplete('given-name')
->label(' ') !!}
{!! Former::text('new_last_name')
->placeholder(trans('texts.last_name'))
->autocomplete('family-name')
->label(' ') !!}
{!! Former::text('new_email')
->placeholder(trans('texts.email'))
->autocomplete('email')
->label(' ') !!}
{!! Former::password('new_password')
->placeholder(trans('texts.password'))
->label(' ') !!}
{{ Former::setOption('TwitterBootstrap3.labelWidths.large', 4) }}
{{ Former::setOption('TwitterBootstrap3.labelWidths.small', 4) }}
</div>
@ -702,8 +715,18 @@
<h4 class="modal-title" id="myModalLabel">{{ trans('texts.white_label_header') }}</h4>
</div>
<div style="background-color: #fff; padding:20px">
<div class="panel-body">
<p>{{ trans('texts.white_label_text')}}</p>
<div class="row">
<div class="col-md-6">
<h4>{{ trans('texts.before') }}</h4>
{!! HTML::image('images/pro_plan/white_label_before.png', 'before', ['width' => '100%']) !!}
</div>
<div class="col-md-6">
<h4>{{ trans('texts.after') }}</h4>
{!! HTML::image('images/pro_plan/white_label_after.png', 'after', ['width' => '100%']) !!}
</div>
</div>
</div>
<div class="modal-footer" id="signUpFooter" style="margin-top: 0px">

View File

@ -30,12 +30,17 @@
</ol>
@endif
{!! Former::open($url)->method($method)->addClass('warn-on-exit')->rules(array(
'client' => 'required',
'invoice_number' => 'required',
'product_key' => 'max:255'
)) !!}
{!! Former::open($url)
->method($method)
->addClass('warn-on-exit')
->autocomplete('off')
->rules(array(
'client' => 'required',
'invoice_number' => 'required',
'product_key' => 'max:255'
)) !!}
@include('partials.autocomplete_fix')
<input type="submit" style="display:none" name="submitButton" id="submitButton">
@ -48,7 +53,7 @@
@if ($invoice->id || $data)
<div class="form-group">
<label for="client" class="control-label col-lg-4 col-sm-4">Client</label>
<label for="client" class="control-label col-lg-4 col-sm-4">{{ trans('texts.client') }}</label>
<div class="col-lg-8 col-sm-8">
<h4><div data-bind="text: getClientDisplayName(ko.toJS(client()))"></div></h4>
<a id="editClientLink" class="pointer" data-bind="click: $root.showClientForm">{{ trans('texts.edit_client') }}</a> |
@ -497,7 +502,8 @@
{!! Former::text('last_name')->data_bind("value: last_name, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][last_name]'}") !!}
{!! Former::text('email')->data_bind("value: email, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][email]', id:'email'+\$index()}") !!}
attr: {name: 'client[contacts][' + \$index() + '][email]', id:'email'+\$index()}")
->addClass('client-email') !!}
{!! Former::text('phone')->data_bind("value: phone, valueUpdate: 'afterkeydown',
attr: {name: 'client[contacts][' + \$index() + '][phone]'}") !!}
@ -838,7 +844,7 @@
function createInvoiceModel() {
var invoice = ko.toJS(window.model).invoice;
invoice.is_pro = {{ Auth::user()->isPro() ? 'true' : 'false' }};
//invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
invoice.contact = _.findWhere(invoice.client.contacts, {send_invoice: true});
if (invoice.is_recurring) {
@ -1126,4 +1132,4 @@
</script>
@stop
@stop

View File

@ -125,9 +125,9 @@ function ViewModel(data) {
self.clientFormComplete = function() {
trackEvent('/activity', '/save_client_form');
var email = $('#email0').val();
var firstName = $('#first_name').val();
var lastName = $('#last_name').val();
var email = $("[name='client[contacts][0][email]']").val();
var firstName = $("[name='client[contacts][0][first_name]']").val();
var lastName = $("[name='client[contacts][0][last_name]']").val();
var name = $('#name').val();
if (name) {
@ -139,10 +139,10 @@ function ViewModel(data) {
}
var isValid = true;
$("input[name='email']").each(function(item, value) {
$('input.client-email').each(function(item, value) {
var email = $(value).val();
if (!name && (!email || !isValidEmailAddress(email))) {
isValid = false;
isValid = false;
}
});

View File

@ -0,0 +1,4 @@
<!-- http://stackoverflow.com/a/30873633/497368 -->
<div style="display: none;">
<input type="text" id="PreventChromeAutocomplete" name="PreventChromeAutocomplete" autocomplete="address-level4" />
</div>

View File

@ -1,5 +1,14 @@
@extends('public.header')
@section('head')
@parent
<!--
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
-->
@stop
@section('content')
<style type="text/css">
@ -133,21 +142,23 @@ header h3 em {
</style>
{!! Former::vertical_open($url)->rules(array(
'first_name' => 'required',
'last_name' => 'required',
'card_number' => 'required',
'expiration_month' => 'required',
'expiration_year' => 'required',
'cvv' => 'required',
'address1' => 'required',
'city' => 'required',
'state' => 'required',
'postal_code' => 'required',
'country_id' => 'required',
'phone' => 'required',
'email' => 'required|email'
)) !!}
{!! Former::vertical_open($url)
->autocomplete('on')
->rules(array(
'first_name' => 'required',
'last_name' => 'required',
'card_number' => 'required',
'expiration_month' => 'required',
'expiration_year' => 'required',
'cvv' => 'required',
'address1' => 'required',
'city' => 'required',
'state' => 'required',
'postal_code' => 'required',
'country_id' => 'required',
'phone' => 'required',
'email' => 'required|email'
)) !!}
@if ($client)
{{ Former::populate($client) }}
@ -191,16 +202,25 @@ header h3 em {
<h3>{{ trans('texts.contact_information') }}</h3>
<div class="row">
<div class="col-md-6">
{!! Former::text('first_name')->placeholder(trans('texts.first_name'))->label('') !!}
{!! Former::text('first_name')
->placeholder(trans('texts.first_name'))
->autocomplete('given-name')
->label('') !!}
</div>
<div class="col-md-6">
{!! Former::text('last_name')->placeholder(trans('texts.last_name'))->label('') !!}
{!! Former::text('last_name')
->placeholder(trans('texts.last_name'))
->autocomplete('family-name')
->label('') !!}
</div>
</div>
@if (isset($paymentTitle))
<div class="row">
<div class="col-md-12">
{!! Former::text('email')->placeholder(trans('texts.email'))->label('') !!}
{!! Former::text('email')
->placeholder(trans('texts.email'))
->autocomplete('email')
->label('') !!}
</div>
</div>
@endif
@ -211,26 +231,45 @@ header h3 em {
<h3>{{ trans('texts.billing_address') }} &nbsp;<span class="help">{{ trans('texts.payment_footer1') }}</span></h3>
<div class="row">
<div class="col-md-6">
{!! Former::text('address1')->placeholder(trans('texts.address1'))->label('') !!}
{!! Former::text('address1')
->autocomplete('address-line1')
->placeholder(trans('texts.address1'))
->label('') !!}
</div>
<div class="col-md-6">
{!! Former::text('address2')->placeholder(trans('texts.address2'))->label('') !!}
</div>
</div>
<div class="row">
<div class="col-md-6">
{!! Former::text('city')->placeholder(trans('texts.city'))->label('') !!}
</div>
<div class="col-md-6">
{!! Former::text('state')->placeholder(trans('texts.state'))->label('') !!}
{!! Former::text('address2')
->autocomplete('address-line2')
->placeholder(trans('texts.address2'))
->label('') !!}
</div>
</div>
<div class="row">
<div class="col-md-6">
{!! Former::text('postal_code')->placeholder(trans('texts.postal_code'))->label('') !!}
{!! Former::text('city')
->autocomplete('address-level2')
->placeholder(trans('texts.city'))
->label('') !!}
</div>
<div class="col-md-6">
{!! Former::select('country_id')->placeholder(trans('texts.country_id'))->fromQuery($countries, 'name', 'id')->label('')->addGroupClass('country-select') !!}
{!! Former::text('state')
->autocomplete('address-level1')
->placeholder(trans('texts.state'))
->label('') !!}
</div>
</div>
<div class="row">
<div class="col-md-6">
{!! Former::text('postal_code')
->autocomplete('postal-code')
->placeholder(trans('texts.postal_code'))
->label('') !!}
</div>
<div class="col-md-6">
{!! Former::select('country_id')
->placeholder(trans('texts.country_id'))
->fromQuery($countries, 'name', 'id')
->addGroupClass('country-select')
->label('') !!}
</div>
</div>
@ -240,43 +279,57 @@ header h3 em {
<h3>{{ trans('texts.billing_method') }}</h3>
<div class="row">
<div class="col-md-9">
{!! Former::text('card_number')->placeholder(trans('texts.card_number'))->label('') !!}
{!! Former::text($gateway->isGateway(GATEWAY_STRIPE) ? 'card_number' : 'card_number')
->placeholder(trans('texts.card_number'))
->autocomplete('cc-number')
->data_stripe('number')
->label('') !!}
</div>
<div class="col-md-3">
{!! Former::text('cvv')->placeholder(trans('texts.cvv'))->label('') !!}
{!! Former::text($gateway->isGateway(GATEWAY_STRIPE) ? 'cvv' : 'cvv')
->placeholder(trans('texts.cvv'))
->autocomplete('off')
->data_stripe('cvc')
->label('') !!}
</div>
</div>
<div class="row">
<div class="col-md-6">
{!! Former::select('expiration_month')->placeholder(trans('texts.expiration_month'))
->addOption('01 - January', '1')
->addOption('02 - February', '2')
->addOption('03 - March', '3')
->addOption('04 - April', '4')
->addOption('05 - May', '5')
->addOption('06 - June', '6')
->addOption('07 - July', '7')
->addOption('08 - August', '8')
->addOption('09 - September', '9')
->addOption('10 - October', '10')
->addOption('11 - November', '11')
->addOption('12 - December', '12')->label('')
!!}
{!! Former::select($gateway->isGateway(GATEWAY_STRIPE) ? 'expiration_month' : 'expiration_month')
->autocomplete('cc-exp-month')
->data_stripe('exp-month')
->placeholder(trans('texts.expiration_month'))
->addOption('01 - January', '1')
->addOption('02 - February', '2')
->addOption('03 - March', '3')
->addOption('04 - April', '4')
->addOption('05 - May', '5')
->addOption('06 - June', '6')
->addOption('07 - July', '7')
->addOption('08 - August', '8')
->addOption('09 - September', '9')
->addOption('10 - October', '10')
->addOption('11 - November', '11')
->addOption('12 - December', '12')->label('')
!!}
</div>
<div class="col-md-6">
{!! Former::select('expiration_year')->placeholder(trans('texts.expiration_year'))
->addOption('2015', '2015')
->addOption('2016', '2016')
->addOption('2017', '2017')
->addOption('2018', '2018')
->addOption('2019', '2019')
->addOption('2020', '2020')
->addOption('2021', '2021')
->addOption('2022', '2022')
->addOption('2023', '2023')
->addOption('2024', '2024')
->addOption('2025', '2025')->label('')
!!}
{!! Former::select($gateway->isGateway(GATEWAY_STRIPE) ? 'expiration_year' : 'expiration_year')
->autocomplete('cc-exp-year')
->data_stripe('exp-year')
->placeholder(trans('texts.expiration_year'))
->addOption('2015', '2015')
->addOption('2016', '2016')
->addOption('2017', '2017')
->addOption('2018', '2018')
->addOption('2019', '2019')
->addOption('2020', '2020')
->addOption('2021', '2021')
->addOption('2022', '2022')
->addOption('2023', '2023')
->addOption('2024', '2024')
->addOption('2025', '2025')->label('')
!!}
</div>
</div>
@ -322,16 +375,6 @@ header h3 em {
</div>
<!--
@if (isset($paymentTitle))
<h2>{{ $paymentTitle }}<br/>
@if (isset($paymentSubtitle))
<small>{{ $paymentSubtitle }}</small>
@endif
</h2>&nbsp;<p/>
@endif
-->
{!! Former::close() !!}
<script type="text/javascript">

View File

View File

@ -0,0 +1,123 @@
<?php
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');
header("Access-Control-Allow-Headers: X-Requested-With");
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Swagger UI</title>
<link rel="icon" type="image/png" href="vendor/swaggervel/images/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="vendor/swaggervel/images/favicon-16x16.png" sizes="16x16" />
<link href='vendor/swaggervel/css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='vendor/swaggervel/css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='vendor/swaggervel/css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='vendor/swaggervel/css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='vendor/swaggervel/css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script src='vendor/swaggervel/lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/handlebars-2.0.0.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/underscore-min.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/backbone-min.js' type='text/javascript'></script>
<script src='vendor/swaggervel/swagger-ui.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/marked.js' type='text/javascript'></script>
<script src='vendor/swaggervel/lib/swagger-oauth.js' type='text/javascript'></script>
<!-- Some basic translations -->
<!-- <script src='lang/translator.js' type='text/javascript'></script> -->
<!-- <script src='lang/ru.js' type='text/javascript'></script> -->
<!-- <script src='lang/en.js' type='text/javascript'></script> -->
<script type="text/javascript">
function log() {
if ('console' in window) {
console.log.apply(console, arguments);
}
}
$(function () {
var url = window.location.search.match(/url=([^&]+)/);
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "{!! $urlToDocs !!}";
}
// Pre load translate...
if (window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],
onComplete: function (swaggerApi, swaggerUi) {
log("Loaded SwaggerUI");
@if (isset($requestHeaders))
@foreach($requestHeaders as $requestKey => $requestValue)
window.authorizations.add("{!!$requestKey!!}", new ApiKeyAuthorization("{!!$requestKey!!}", "{!!$requestValue!!}", "header"));
@endforeach
@endif
if (window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
$('pre code').each(function (i, e) {
hljs.highlightBlock(e)
});
addApiKeyAuthorization();
},
onFailure: function (data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
apisSorter: "alpha",
showRequestHeaders: false
});
function addApiKeyAuthorization() {
var key = encodeURIComponent($('#input_apiKey')[0].value);
if (key && key.trim() != "") {
var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("X-Ninja-Token", key, "header");
window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
var ajaxRequest = new SwaggerClient.ApiKeyAuthorization("X-Requested-With", "XMLHttpRequest", "header");
window.swaggerUi.api.clientAuthorizations.add("ajax", ajaxRequest);
log("added key " + key);
}
}
$('#input_apiKey').change(addApiKeyAuthorization);
window.swaggerUi.load();
});
</script>
</head>
<body class="swagger-section">
<div id='header'>
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.io">swagger</a>
<form id='api_selector'>
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
<div class='input'><input placeholder="API Token" id="input_apiKey" name="apiKey" type="text" value="{{ env('TEST_API_TOKEN') }}"/></div>
<div class='input'><a id="explore" href="#" data-sw-translate>Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap" data-sw-translate>&nbsp;</div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>