mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-22 04:10:59 -04:00
Merge remote-tracking branch 'remotes/ninja/master'
This commit is contained in:
commit
ae557645fc
@ -51,7 +51,7 @@ module.exports = function(grunt) {
|
|||||||
'public/vendor/knockout-mapping/build/output/knockout.mapping-latest.js',
|
'public/vendor/knockout-mapping/build/output/knockout.mapping-latest.js',
|
||||||
'public/vendor/knockout-sortable/build/knockout-sortable.min.js',
|
'public/vendor/knockout-sortable/build/knockout-sortable.min.js',
|
||||||
'public/vendor/underscore/underscore.js',
|
'public/vendor/underscore/underscore.js',
|
||||||
'public/vendor/bootstrap-datepicker/js/bootstrap-datepicker.js',
|
'public/vendor/bootstrap-datepicker/dist/js/bootstrap-datepicker.js',
|
||||||
'public/vendor/typeahead.js/dist/typeahead.min.js',
|
'public/vendor/typeahead.js/dist/typeahead.min.js',
|
||||||
'public/vendor/accounting/accounting.min.js',
|
'public/vendor/accounting/accounting.min.js',
|
||||||
'public/vendor/spectrum/spectrum.js',
|
'public/vendor/spectrum/spectrum.js',
|
||||||
@ -65,7 +65,7 @@ module.exports = function(grunt) {
|
|||||||
'public/js/lightbox.min.js',
|
'public/js/lightbox.min.js',
|
||||||
'public/js/bootstrap-combobox.js',
|
'public/js/bootstrap-combobox.js',
|
||||||
'public/js/script.js',
|
'public/js/script.js',
|
||||||
'public/js/pdf.pdfmake.js'
|
'public/js/pdf.pdfmake.js',
|
||||||
],
|
],
|
||||||
dest: 'public/js/built.js',
|
dest: 'public/js/built.js',
|
||||||
nonull: true
|
nonull: true
|
||||||
@ -91,7 +91,7 @@ module.exports = function(grunt) {
|
|||||||
'public/vendor/datatables/media/css/jquery.dataTables.css',
|
'public/vendor/datatables/media/css/jquery.dataTables.css',
|
||||||
'public/vendor/datatables-bootstrap3/BS3/assets/css/datatables.css',
|
'public/vendor/datatables-bootstrap3/BS3/assets/css/datatables.css',
|
||||||
'public/vendor/font-awesome/css/font-awesome.min.css',
|
'public/vendor/font-awesome/css/font-awesome.min.css',
|
||||||
'public/vendor/bootstrap-datepicker/css/datepicker3.css',
|
'public/vendor/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css',
|
||||||
'public/vendor/spectrum/spectrum.css',
|
'public/vendor/spectrum/spectrum.css',
|
||||||
'public/css/bootstrap-combobox.css',
|
'public/css/bootstrap-combobox.css',
|
||||||
'public/css/typeahead.js-bootstrap.css',
|
'public/css/typeahead.js-bootstrap.css',
|
||||||
|
@ -84,9 +84,10 @@ class AccountController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user = false;
|
$user = false;
|
||||||
$guestKey = Input::get('guest_key');
|
$guestKey = Input::get('guest_key'); // local storage key to login until registered
|
||||||
|
$prevUserId = Session::pull(PREV_USER_ID); // last user id used to link to new account
|
||||||
|
|
||||||
if ($guestKey) {
|
if ($guestKey && !$prevUserId) {
|
||||||
$user = User::where('password', '=', $guestKey)->first();
|
$user = User::where('password', '=', $guestKey)->first();
|
||||||
|
|
||||||
if ($user && $user->registered) {
|
if ($user && $user->registered) {
|
||||||
@ -99,6 +100,11 @@ class AccountController extends BaseController
|
|||||||
$user = $account->users()->first();
|
$user = $account->users()->first();
|
||||||
|
|
||||||
Session::forget(RECENTLY_VIEWED);
|
Session::forget(RECENTLY_VIEWED);
|
||||||
|
|
||||||
|
if ($prevUserId) {
|
||||||
|
$users = $this->accountRepo->associateAccounts($user->id, $prevUserId);
|
||||||
|
Session::put(SESSION_USER_ACCOUNTS, $users);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Auth::login($user, true);
|
Auth::login($user, true);
|
||||||
@ -154,6 +160,7 @@ class AccountController extends BaseController
|
|||||||
'currencies' => Cache::get('currencies'),
|
'currencies' => Cache::get('currencies'),
|
||||||
'languages' => Cache::get('languages'),
|
'languages' => Cache::get('languages'),
|
||||||
'showUser' => Auth::user()->id === Auth::user()->account->users()->first()->id,
|
'showUser' => Auth::user()->id === Auth::user()->account->users()->first()->id,
|
||||||
|
'title' => trans('texts.company_details'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return View::make('accounts.details', $data);
|
return View::make('accounts.details', $data);
|
||||||
@ -166,21 +173,26 @@ class AccountController extends BaseController
|
|||||||
if ($count == 0) {
|
if ($count == 0) {
|
||||||
return Redirect::to('gateways/create');
|
return Redirect::to('gateways/create');
|
||||||
} else {
|
} else {
|
||||||
return View::make('accounts.payments', ['showAdd' => $count < 3]);
|
return View::make('accounts.payments', [
|
||||||
|
'showAdd' => $count < 3,
|
||||||
|
'title' => trans('texts.online_payments')
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
} elseif ($section == ACCOUNT_NOTIFICATIONS) {
|
} elseif ($section == ACCOUNT_NOTIFICATIONS) {
|
||||||
$data = [
|
$data = [
|
||||||
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
|
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
|
||||||
|
'title' => trans('texts.notifications'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return View::make('accounts.notifications', $data);
|
return View::make('accounts.notifications', $data);
|
||||||
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
|
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
|
||||||
return View::make('accounts.import_export');
|
return View::make('accounts.import_export', ['title' => trans('texts.import_export')]);
|
||||||
} elseif ($section == ACCOUNT_ADVANCED_SETTINGS) {
|
} elseif ($section == ACCOUNT_ADVANCED_SETTINGS) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
$data = [
|
$data = [
|
||||||
'account' => $account,
|
'account' => $account,
|
||||||
'feature' => $subSection,
|
'feature' => $subSection,
|
||||||
|
'title' => trans('texts.invoice_settings'),
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($subSection == ACCOUNT_INVOICE_DESIGN) {
|
if ($subSection == ACCOUNT_INVOICE_DESIGN) {
|
||||||
@ -212,17 +224,22 @@ class AccountController extends BaseController
|
|||||||
$data['invoice'] = $invoice;
|
$data['invoice'] = $invoice;
|
||||||
$data['invoiceDesigns'] = InvoiceDesign::availableDesigns();
|
$data['invoiceDesigns'] = InvoiceDesign::availableDesigns();
|
||||||
$data['invoiceLabels'] = json_decode($account->invoice_labels) ?: [];
|
$data['invoiceLabels'] = json_decode($account->invoice_labels) ?: [];
|
||||||
|
$data['title'] = trans('texts.invoice_design');
|
||||||
} else if ($subSection == ACCOUNT_EMAIL_TEMPLATES) {
|
} else if ($subSection == ACCOUNT_EMAIL_TEMPLATES) {
|
||||||
$data['invoiceEmail'] = $account->getEmailTemplate(ENTITY_INVOICE);
|
$data['invoiceEmail'] = $account->getEmailTemplate(ENTITY_INVOICE);
|
||||||
$data['quoteEmail'] = $account->getEmailTemplate(ENTITY_QUOTE);
|
$data['quoteEmail'] = $account->getEmailTemplate(ENTITY_QUOTE);
|
||||||
$data['paymentEmail'] = $account->getEmailTemplate(ENTITY_PAYMENT);
|
$data['paymentEmail'] = $account->getEmailTemplate(ENTITY_PAYMENT);
|
||||||
$data['emailFooter'] = $account->getEmailFooter();
|
$data['emailFooter'] = $account->getEmailFooter();
|
||||||
|
$data['title'] = trans('texts.email_templates');
|
||||||
|
} else if ($subSection == ACCOUNT_USER_MANAGEMENT) {
|
||||||
|
$data['title'] = trans('texts.users_and_tokens');
|
||||||
}
|
}
|
||||||
|
|
||||||
return View::make("accounts.{$subSection}", $data);
|
return View::make("accounts.{$subSection}", $data);
|
||||||
} elseif ($section == ACCOUNT_PRODUCTS) {
|
} elseif ($section == ACCOUNT_PRODUCTS) {
|
||||||
$data = [
|
$data = [
|
||||||
'account' => Auth::user()->account,
|
'account' => Auth::user()->account,
|
||||||
|
'title' => trans('texts.product_library'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return View::make('accounts.products', $data);
|
return View::make('accounts.products', $data);
|
||||||
@ -704,8 +721,6 @@ class AccountController extends BaseController
|
|||||||
|
|
||||||
if (Utils::isNinja()) {
|
if (Utils::isNinja()) {
|
||||||
$this->userMailer->sendConfirmation($user);
|
$this->userMailer->sendConfirmation($user);
|
||||||
} else {
|
|
||||||
$this->accountRepo->registerUser($user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$activities = Activity::scope()->get();
|
$activities = Activity::scope()->get();
|
||||||
@ -761,6 +776,7 @@ class AccountController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
$this->accountRepo->unlinkAccount($account);
|
||||||
$account->forceDelete();
|
$account->forceDelete();
|
||||||
|
|
||||||
Auth::logout();
|
Auth::logout();
|
||||||
|
@ -200,7 +200,7 @@ class AccountGatewayController extends BaseController
|
|||||||
$fields = $gateway->getFields();
|
$fields = $gateway->getFields();
|
||||||
$optional = array_merge(Gateway::$hiddenFields, Gateway::$optionalFields);
|
$optional = array_merge(Gateway::$hiddenFields, Gateway::$optionalFields);
|
||||||
|
|
||||||
if (Utils::isNinja() && $gatewayId == GATEWAY_DWOLLA) {
|
if ($gatewayId == GATEWAY_DWOLLA) {
|
||||||
$optional = array_merge($optional, ['key', 'secret']);
|
$optional = array_merge($optional, ['key', 'secret']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ use Session;
|
|||||||
use Cookie;
|
use Cookie;
|
||||||
use Response;
|
use Response;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Account;
|
||||||
|
use App\Models\Industry;
|
||||||
use App\Ninja\Mailers\Mailer;
|
use App\Ninja\Mailers\Mailer;
|
||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
use Redirect;
|
use Redirect;
|
||||||
@ -32,24 +34,16 @@ class AppController extends BaseController
|
|||||||
|
|
||||||
public function showSetup()
|
public function showSetup()
|
||||||
{
|
{
|
||||||
if (Utils::isNinja() || Utils::isDatabaseSetup()) {
|
if (Utils::isNinja() || (Utils::isDatabaseSetup() && Account::count() > 0)) {
|
||||||
return Redirect::to('/');
|
return Redirect::to('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
$view = View::make('setup');
|
return View::make('setup');
|
||||||
|
|
||||||
/*
|
|
||||||
$cookie = Cookie::forget('ninja_session', '/', 'www.ninja.dev');
|
|
||||||
Cookie::queue($cookie);
|
|
||||||
return Response::make($view)->withCookie($cookie);
|
|
||||||
*/
|
|
||||||
|
|
||||||
return Response::make($view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doSetup()
|
public function doSetup()
|
||||||
{
|
{
|
||||||
if (Utils::isNinja() || Utils::isDatabaseSetup()) {
|
if (Utils::isNinja() || (Utils::isDatabaseSetup() && Account::count() > 0)) {
|
||||||
return Redirect::to('/');
|
return Redirect::to('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +98,9 @@ class AppController extends BaseController
|
|||||||
// == DB Migrate & Seed == //
|
// == DB Migrate & Seed == //
|
||||||
// Artisan::call('migrate:rollback', array('--force' => true)); // Debug Purposes
|
// Artisan::call('migrate:rollback', array('--force' => true)); // Debug Purposes
|
||||||
Artisan::call('migrate', array('--force' => true));
|
Artisan::call('migrate', array('--force' => true));
|
||||||
|
if (Industry::count() == 0) {
|
||||||
Artisan::call('db:seed', array('--force' => true));
|
Artisan::call('db:seed', array('--force' => true));
|
||||||
|
}
|
||||||
Artisan::call('optimize', array('--force' => true));
|
Artisan::call('optimize', array('--force' => true));
|
||||||
|
|
||||||
$firstName = trim(Input::get('first_name'));
|
$firstName = trim(Input::get('first_name'));
|
||||||
@ -114,8 +110,6 @@ class AppController extends BaseController
|
|||||||
$account = $this->accountRepo->create($firstName, $lastName, $email, $password);
|
$account = $this->accountRepo->create($firstName, $lastName, $email, $password);
|
||||||
$user = $account->users()->first();
|
$user = $account->users()->first();
|
||||||
|
|
||||||
//Auth::login($user, true);
|
|
||||||
|
|
||||||
return Redirect::to('/login');
|
return Redirect::to('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +162,9 @@ class AppController extends BaseController
|
|||||||
if (!Utils::isNinja() && !Utils::isDatabaseSetup()) {
|
if (!Utils::isNinja() && !Utils::isDatabaseSetup()) {
|
||||||
try {
|
try {
|
||||||
Artisan::call('migrate', array('--force' => true));
|
Artisan::call('migrate', array('--force' => true));
|
||||||
|
if (Industry::count() == 0) {
|
||||||
Artisan::call('db:seed', array('--force' => true));
|
Artisan::call('db:seed', array('--force' => true));
|
||||||
|
}
|
||||||
Artisan::call('optimize', array('--force' => true));
|
Artisan::call('optimize', array('--force' => true));
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Response::make($e->getMessage(), 500);
|
Response::make($e->getMessage(), 500);
|
||||||
|
@ -60,12 +60,18 @@ class AuthController extends Controller {
|
|||||||
public function postLoginWrapper(Request $request)
|
public function postLoginWrapper(Request $request)
|
||||||
{
|
{
|
||||||
$userId = Auth::check() ? Auth::user()->id : null;
|
$userId = Auth::check() ? Auth::user()->id : null;
|
||||||
|
$user = User::where('email', '=', $request->input('email'))->first();
|
||||||
|
|
||||||
|
if ($user->failed_logins >= 3) {
|
||||||
|
Session::flash('error', 'These credentials do not match our records.');
|
||||||
|
return redirect()->to('login');
|
||||||
|
}
|
||||||
|
|
||||||
$response = self::postLogin($request);
|
$response = self::postLogin($request);
|
||||||
|
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
Event::fire(new UserLoggedIn());
|
Event::fire(new UserLoggedIn());
|
||||||
|
|
||||||
if (Utils::isPro()) {
|
|
||||||
$users = false;
|
$users = false;
|
||||||
// we're linking a new account
|
// we're linking a new account
|
||||||
if ($userId && Auth::user()->id != $userId) {
|
if ($userId && Auth::user()->id != $userId) {
|
||||||
@ -77,7 +83,9 @@ class AuthController extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Session::put(SESSION_USER_ACCOUNTS, $users);
|
Session::put(SESSION_USER_ACCOUNTS, $users);
|
||||||
}
|
} elseif ($user) {
|
||||||
|
$user->failed_logins = $user->failed_logins + 1;
|
||||||
|
$user->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
@ -85,6 +93,12 @@ class AuthController extends Controller {
|
|||||||
|
|
||||||
public function getLogoutWrapper()
|
public function getLogoutWrapper()
|
||||||
{
|
{
|
||||||
|
if (Auth::check() && !Auth::user()->registered) {
|
||||||
|
$account = Auth::user()->account;
|
||||||
|
$this->accountRepo->unlinkAccount($account);
|
||||||
|
$account->forceDelete();
|
||||||
|
}
|
||||||
|
|
||||||
$response = self::getLogout();
|
$response = self::getLogout();
|
||||||
|
|
||||||
Session::flush();
|
Session::flush();
|
||||||
|
@ -24,8 +24,11 @@ class ClientApiController extends Controller
|
|||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$clients = Client::scope()->with('contacts')->orderBy('created_at', 'desc')->get();
|
$clients = Client::scope()
|
||||||
$clients = Utils::remapPublicIds($clients->toArray());
|
->with('country', 'contacts', 'industry', 'size', 'currency')
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->get();
|
||||||
|
$clients = Utils::remapPublicIds($clients);
|
||||||
|
|
||||||
$response = json_encode($clients, JSON_PRETTY_PRINT);
|
$response = json_encode($clients, JSON_PRETTY_PRINT);
|
||||||
$headers = Utils::getApiHeaders(count($clients));
|
$headers = Utils::getApiHeaders(count($clients));
|
||||||
@ -43,9 +46,9 @@ class ClientApiController extends Controller
|
|||||||
|
|
||||||
return Response::make($error, 500, $headers);
|
return Response::make($error, 500, $headers);
|
||||||
} else {
|
} else {
|
||||||
$client = $this->clientRepo->save(false, $data, false);
|
$client = $this->clientRepo->save(isset($data['id']) ? $data['id'] : false, $data, false);
|
||||||
$client->load('contacts');
|
$client = Client::scope($client->public_id)->with('country', 'contacts', 'industry', 'size', 'currency')->first();
|
||||||
$client = Utils::remapPublicIds($client->toArray());
|
$client = Utils::remapPublicIds([$client]);
|
||||||
$response = json_encode($client, JSON_PRETTY_PRINT);
|
$response = json_encode($client, JSON_PRETTY_PRINT);
|
||||||
$headers = Utils::getApiHeaders();
|
$headers = Utils::getApiHeaders();
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ class DashboardController extends BaseController
|
|||||||
'activities' => $activities,
|
'activities' => $activities,
|
||||||
'pastDue' => $pastDue,
|
'pastDue' => $pastDue,
|
||||||
'upcoming' => $upcoming,
|
'upcoming' => $upcoming,
|
||||||
|
'title' => trans('texts.dashboard'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return View::make('dashboard', $data);
|
return View::make('dashboard', $data);
|
||||||
|
@ -27,10 +27,8 @@ class HomeController extends BaseController
|
|||||||
{
|
{
|
||||||
Session::reflash();
|
Session::reflash();
|
||||||
|
|
||||||
if (!Utils::isDatabaseSetup()) {
|
if (!Utils::isNinja() && (!Utils::isDatabaseSetup() || Account::count() == 0)) {
|
||||||
return Redirect::to('/setup');
|
return Redirect::to('/setup');
|
||||||
} elseif (Account::count() == 0) {
|
|
||||||
return Redirect::to('/invoice_now');
|
|
||||||
} elseif (Auth::check()) {
|
} elseif (Auth::check()) {
|
||||||
return Redirect::to('/dashboard');
|
return Redirect::to('/dashboard');
|
||||||
} else {
|
} else {
|
||||||
@ -45,7 +43,8 @@ class HomeController extends BaseController
|
|||||||
|
|
||||||
public function invoiceNow()
|
public function invoiceNow()
|
||||||
{
|
{
|
||||||
if (Auth::check() && Input::get('logout')) {
|
if (Auth::check() && Input::get('new_account')) {
|
||||||
|
Session::put(PREV_USER_ID, Auth::user()->id);
|
||||||
Auth::user()->clearSession();
|
Auth::user()->clearSession();
|
||||||
Auth::logout();
|
Auth::logout();
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ class InvoiceApiController extends Controller
|
|||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$invoices = Invoice::scope()->with('invitations')->where('invoices.is_quote', '=', false)->orderBy('created_at', 'desc')->get();
|
$invoices = Invoice::scope()->with('client', 'invitations.account')->where('invoices.is_quote', '=', false)->orderBy('created_at', 'desc')->get();
|
||||||
|
|
||||||
// Add the first invitation link to the data
|
// Add the first invitation link to the data
|
||||||
foreach ($invoices as $key => $invoice) {
|
foreach ($invoices as $key => $invoice) {
|
||||||
@ -36,7 +36,7 @@ class InvoiceApiController extends Controller
|
|||||||
unset($invoice['invitations']);
|
unset($invoice['invitations']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoices = Utils::remapPublicIds($invoices->toArray());
|
$invoices = Utils::remapPublicIds($invoices);
|
||||||
|
|
||||||
$response = json_encode($invoices, JSON_PRETTY_PRINT);
|
$response = json_encode($invoices, JSON_PRETTY_PRINT);
|
||||||
$headers = Utils::getApiHeaders(count($invoices));
|
$headers = Utils::getApiHeaders(count($invoices));
|
||||||
@ -99,7 +99,6 @@ class InvoiceApiController extends Controller
|
|||||||
$data = self::prepareData($data);
|
$data = self::prepareData($data);
|
||||||
$data['client_id'] = $client->id;
|
$data['client_id'] = $client->id;
|
||||||
$invoice = $this->invoiceRepo->save(false, $data, false);
|
$invoice = $this->invoiceRepo->save(false, $data, false);
|
||||||
$invoice->load('invoice_items');
|
|
||||||
|
|
||||||
$invitation = Invitation::createNew();
|
$invitation = Invitation::createNew();
|
||||||
$invitation->invoice_id = $invoice->id;
|
$invitation->invoice_id = $invoice->id;
|
||||||
@ -112,12 +111,8 @@ class InvoiceApiController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prepare the return data
|
// prepare the return data
|
||||||
$invoice = $invoice->toArray();
|
$invoice = Invoice::scope($invoice->public_id)->with('client', 'invoice_items', 'invitations')->first();
|
||||||
$invoice['link'] = $invitation->getLink();
|
$invoice = Utils::remapPublicIds([$invoice]);
|
||||||
unset($invoice['account']);
|
|
||||||
unset($invoice['client']);
|
|
||||||
$invoice = Utils::remapPublicIds($invoice);
|
|
||||||
$invoice['client_id'] = $client->public_id;
|
|
||||||
|
|
||||||
$response = json_encode($invoice, JSON_PRETTY_PRINT);
|
$response = json_encode($invoice, JSON_PRETTY_PRINT);
|
||||||
}
|
}
|
||||||
|
@ -236,6 +236,11 @@ class InvoiceController extends BaseController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$paymentURL = '';
|
||||||
|
if (count($paymentTypes)) {
|
||||||
|
$paymentURL = $paymentTypes[0]['url'];
|
||||||
|
}
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'isConverted' => $invoice->quote_invoice_id ? true : false,
|
'isConverted' => $invoice->quote_invoice_id ? true : false,
|
||||||
'showBreadcrumbs' => false,
|
'showBreadcrumbs' => false,
|
||||||
@ -244,7 +249,8 @@ class InvoiceController extends BaseController
|
|||||||
'invitation' => $invitation,
|
'invitation' => $invitation,
|
||||||
'invoiceLabels' => $account->getInvoiceLabels(),
|
'invoiceLabels' => $account->getInvoiceLabels(),
|
||||||
'contact' => $contact,
|
'contact' => $contact,
|
||||||
'paymentTypes' => $paymentTypes
|
'paymentTypes' => $paymentTypes,
|
||||||
|
'paymentURL' => $paymentURL
|
||||||
);
|
);
|
||||||
|
|
||||||
return View::make('invoices.view', $data);
|
return View::make('invoices.view', $data);
|
||||||
@ -505,9 +511,13 @@ class InvoiceController extends BaseController
|
|||||||
return $this->convertQuote($publicId);
|
return $this->convertQuote($publicId);
|
||||||
} elseif ($action == 'email') {
|
} elseif ($action == 'email') {
|
||||||
if (Auth::user()->confirmed && !Auth::user()->isDemo()) {
|
if (Auth::user()->confirmed && !Auth::user()->isDemo()) {
|
||||||
|
$response = $this->mailer->sendInvoice($invoice);
|
||||||
|
if ($response === true) {
|
||||||
$message = trans("texts.emailed_{$entityType}");
|
$message = trans("texts.emailed_{$entityType}");
|
||||||
$this->mailer->sendInvoice($invoice);
|
|
||||||
Session::flash('message', $message);
|
Session::flash('message', $message);
|
||||||
|
} else {
|
||||||
|
Session::flash('error', $response);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$errorMessage = trans(Auth::user()->registered ? 'texts.confirmation_required' : 'texts.registration_required');
|
$errorMessage = trans(Auth::user()->registered ? 'texts.confirmation_required' : 'texts.registration_required');
|
||||||
Session::flash('error', $errorMessage);
|
Session::flash('error', $errorMessage);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
<?php namespace App\Http\Controllers;
|
<?php namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Input;
|
||||||
use Utils;
|
use Utils;
|
||||||
use Response;
|
use Response;
|
||||||
use App\Models\Payment;
|
use App\Models\Payment;
|
||||||
|
use App\Models\Invoice;
|
||||||
use App\Ninja\Repositories\PaymentRepository;
|
use App\Ninja\Repositories\PaymentRepository;
|
||||||
|
|
||||||
class PaymentApiController extends Controller
|
class PaymentApiController extends Controller
|
||||||
@ -16,8 +18,11 @@ class PaymentApiController extends Controller
|
|||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$payments = Payment::scope()->orderBy('created_at', 'desc')->get();
|
$payments = Payment::scope()
|
||||||
$payments = Utils::remapPublicIds($payments->toArray());
|
->with('client', 'contact', 'invitation', 'user', 'invoice')
|
||||||
|
->orderBy('created_at', 'desc')
|
||||||
|
->get();
|
||||||
|
$payments = Utils::remapPublicIds($payments);
|
||||||
|
|
||||||
$response = json_encode($payments, JSON_PRETTY_PRINT);
|
$response = json_encode($payments, JSON_PRETTY_PRINT);
|
||||||
$headers = Utils::getApiHeaders(count($payments));
|
$headers = Utils::getApiHeaders(count($payments));
|
||||||
@ -25,15 +30,38 @@ class PaymentApiController extends Controller
|
|||||||
return Response::make($response, 200, $headers);
|
return Response::make($response, 200, $headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
public function store()
|
public function store()
|
||||||
{
|
{
|
||||||
$data = Input::all();
|
$data = Input::all();
|
||||||
$invoice = $this->invoiceRepo->save(false, $data, false);
|
$error = false;
|
||||||
|
|
||||||
$response = json_encode($invoice, JSON_PRETTY_PRINT);
|
if (isset($data['invoice_id'])) {
|
||||||
|
$invoice = Invoice::scope($data['invoice_id'])->with('client')->first();
|
||||||
|
|
||||||
|
if ($invoice) {
|
||||||
|
$data['invoice'] = $invoice->public_id;
|
||||||
|
$data['client'] = $invoice->client->public_id;
|
||||||
|
} else {
|
||||||
|
$error = trans('validation.not_in', ['attribute' => 'invoice_id']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$error = trans('validation.not_in', ['attribute' => 'invoice_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($data['transaction_reference'])) {
|
||||||
|
$data['transaction_reference'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$error) {
|
||||||
|
$payment = $this->paymentRepo->save(false, $data);
|
||||||
|
$payment = Payment::scope($payment->public_id)->with('client', 'contact', 'user', 'invoice')->first();
|
||||||
|
|
||||||
|
$payment = Utils::remapPublicIds([$payment]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = json_encode($error ?: $payment, JSON_PRETTY_PRINT);
|
||||||
$headers = Utils::getApiHeaders();
|
$headers = Utils::getApiHeaders();
|
||||||
return Response::make($response, 200, $headers);
|
return Response::make($response, 200, $headers);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
@ -460,10 +460,11 @@ class PaymentController extends BaseController
|
|||||||
$this->contactMailer->sendLicensePaymentConfirmation($name, $license->email, $affiliate->price, $license->license_key, $license->product_id);
|
$this->contactMailer->sendLicensePaymentConfirmation($name, $license->email, $affiliate->price, $license->license_key, $license->product_id);
|
||||||
|
|
||||||
if (Session::has('return_url')) {
|
if (Session::has('return_url')) {
|
||||||
return Redirect::away(Session::get('return_url')."?license_key={$license->license_key}&product_id=".Session::get('product_id'));
|
$data['redirectTo'] = Session::get('return_url')."?license_key={$license->license_key}&product_id=".Session::get('product_id');
|
||||||
} else {
|
$data['message'] = "Redirecting to " . Session::get('return_url');
|
||||||
return View::make('public.license', $data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return View::make('public.license', $data);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
$errorMessage = trans('texts.payment_error');
|
$errorMessage = trans('texts.payment_error');
|
||||||
Session::flash('error', $errorMessage);
|
Session::flash('error', $errorMessage);
|
||||||
@ -685,6 +686,14 @@ class PaymentController extends BaseController
|
|||||||
$accountGateway = $invoice->client->account->getGatewayByType(Session::get('payment_type'));
|
$accountGateway = $invoice->client->account->getGatewayByType(Session::get('payment_type'));
|
||||||
$gateway = self::createGateway($accountGateway);
|
$gateway = self::createGateway($accountGateway);
|
||||||
|
|
||||||
|
// Check for Dwolla payment error
|
||||||
|
if ($accountGateway->isGateway(GATEWAY_DWOLLA) && Input::get('error')) {
|
||||||
|
$errorMessage = trans('texts.payment_error')."\n\n".Input::get('error_description');
|
||||||
|
Session::flash('error', $errorMessage);
|
||||||
|
Utils::logError($errorMessage);
|
||||||
|
return Redirect::to('view/'.$invitation->invitation_key);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (method_exists($gateway, 'completePurchase')) {
|
if (method_exists($gateway, 'completePurchase')) {
|
||||||
$details = self::getPaymentDetails($invitation);
|
$details = self::getPaymentDetails($invitation);
|
||||||
|
@ -16,8 +16,8 @@ class QuoteApiController extends Controller
|
|||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$invoices = Invoice::scope()->where('invoices.is_quote', '=', true)->orderBy('created_at', 'desc')->get();
|
$invoices = Invoice::scope()->with('client', 'user')->where('invoices.is_quote', '=', true)->orderBy('created_at', 'desc')->get();
|
||||||
$invoices = Utils::remapPublicIds($invoices->toArray());
|
$invoices = Utils::remapPublicIds($invoices);
|
||||||
|
|
||||||
$response = json_encode($invoices, JSON_PRETTY_PRINT);
|
$response = json_encode($invoices, JSON_PRETTY_PRINT);
|
||||||
$headers = Utils::getApiHeaders(count($invoices));
|
$headers = Utils::getApiHeaders(count($invoices));
|
||||||
|
@ -243,6 +243,7 @@ class ReportController extends BaseController
|
|||||||
'reportType' => $reportType,
|
'reportType' => $reportType,
|
||||||
'enableChart' => $enableChart,
|
'enableChart' => $enableChart,
|
||||||
'enableReport' => $enableReport,
|
'enableReport' => $enableReport,
|
||||||
|
'title' => trans('texts.charts_and_reports'),
|
||||||
];
|
];
|
||||||
|
|
||||||
return View::make('reports.chart_builder', $params);
|
return View::make('reports.chart_builder', $params);
|
||||||
|
@ -301,11 +301,13 @@ class UserController extends BaseController
|
|||||||
* Log the user out of the application.
|
* Log the user out of the application.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
public function logout()
|
public function logout()
|
||||||
{
|
{
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
if (!Auth::user()->registered) {
|
if (!Auth::user()->registered) {
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
$this->accountRepo->unlinkAccount($account);
|
||||||
$account->forceDelete();
|
$account->forceDelete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -315,6 +317,7 @@ class UserController extends BaseController
|
|||||||
|
|
||||||
return Redirect::to('/')->with('clearGuestKey', true);
|
return Redirect::to('/')->with('clearGuestKey', true);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public function changePassword()
|
public function changePassword()
|
||||||
{
|
{
|
||||||
@ -352,6 +355,10 @@ class UserController extends BaseController
|
|||||||
if ($account->hasUserId($newUserId) && $account->hasUserId($oldUserId)) {
|
if ($account->hasUserId($newUserId) && $account->hasUserId($oldUserId)) {
|
||||||
Auth::loginUsingId($newUserId);
|
Auth::loginUsingId($newUserId);
|
||||||
Auth::user()->account->loadLocalizationSettings();
|
Auth::user()->account->loadLocalizationSettings();
|
||||||
|
|
||||||
|
// regenerate token to prevent open pages
|
||||||
|
// from saving under the wrong account
|
||||||
|
Session::put('_token', str_random(40));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,7 +367,7 @@ class UserController extends BaseController
|
|||||||
|
|
||||||
public function unlinkAccount($userAccountId, $userId)
|
public function unlinkAccount($userAccountId, $userId)
|
||||||
{
|
{
|
||||||
$this->accountRepo->unlinkAccount($userAccountId, $userId);
|
$this->accountRepo->unlinkUser($userAccountId, $userId);
|
||||||
$referer = Request::header('referer');
|
$referer = Request::header('referer');
|
||||||
|
|
||||||
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
|
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
|
||||||
|
@ -157,6 +157,14 @@ class StartupCheck
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $next($request);
|
if (preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
|
||||||
|
Session::flash('error', trans('texts.old_browser'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// for security prevent displaying within an iframe
|
||||||
|
$response = $next($request);
|
||||||
|
$response->headers->set('X-Frame-Options', 'DENY');
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -354,6 +354,7 @@ define('EVENT_CREATE_PAYMENT', 4);
|
|||||||
|
|
||||||
define('REQUESTED_PRO_PLAN', 'REQUESTED_PRO_PLAN');
|
define('REQUESTED_PRO_PLAN', 'REQUESTED_PRO_PLAN');
|
||||||
define('DEMO_ACCOUNT_ID', 'DEMO_ACCOUNT_ID');
|
define('DEMO_ACCOUNT_ID', 'DEMO_ACCOUNT_ID');
|
||||||
|
define('PREV_USER_ID', 'PREV_USER_ID');
|
||||||
define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h');
|
define('NINJA_ACCOUNT_KEY', 'zg4ylmzDkdkPOT8yoKQw9LTWaoZJx79h');
|
||||||
define('NINJA_GATEWAY_ID', GATEWAY_STRIPE);
|
define('NINJA_GATEWAY_ID', GATEWAY_STRIPE);
|
||||||
define('NINJA_GATEWAY_CONFIG', '');
|
define('NINJA_GATEWAY_CONFIG', '');
|
||||||
@ -364,6 +365,7 @@ define('NINJA_DATE', '2000-01-01');
|
|||||||
define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com');
|
define('NINJA_FROM_EMAIL', 'maildelivery@invoiceninja.com');
|
||||||
define('RELEASES_URL', 'https://github.com/hillelcoren/invoice-ninja/releases/');
|
define('RELEASES_URL', 'https://github.com/hillelcoren/invoice-ninja/releases/');
|
||||||
define('ZAPIER_URL', 'https://zapier.com/developer/invite/11276/85cf0ee4beae8e802c6c579eb4e351f1/');
|
define('ZAPIER_URL', 'https://zapier.com/developer/invite/11276/85cf0ee4beae8e802c6c579eb4e351f1/');
|
||||||
|
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
|
||||||
|
|
||||||
define('COUNT_FREE_DESIGNS', 4);
|
define('COUNT_FREE_DESIGNS', 4);
|
||||||
define('PRODUCT_ONE_CLICK_INSTALL', 1);
|
define('PRODUCT_ONE_CLICK_INSTALL', 1);
|
||||||
|
@ -61,7 +61,7 @@ class Utils
|
|||||||
|
|
||||||
public static function allowNewAccounts()
|
public static function allowNewAccounts()
|
||||||
{
|
{
|
||||||
return isset($_ENV['ALLOW_NEW_ACCOUNTS']) && $_ENV['ALLOW_NEW_ACCOUNTS'] == 'true';
|
return Utils::isNinja() || (isset($_ENV['ALLOW_NEW_ACCOUNTS']) && $_ENV['ALLOW_NEW_ACCOUNTS'] == 'true');
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isPro()
|
public static function isPro()
|
||||||
@ -568,7 +568,8 @@ class Utils
|
|||||||
{
|
{
|
||||||
$curl = curl_init();
|
$curl = curl_init();
|
||||||
|
|
||||||
$jsonEncodedData = json_encode($data->toJson());
|
$jsonEncodedData = json_encode($data->toPublicArray());
|
||||||
|
|
||||||
$opts = [
|
$opts = [
|
||||||
CURLOPT_URL => $subscription->target_url,
|
CURLOPT_URL => $subscription->target_url,
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
@ -591,27 +592,39 @@ class Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function remapPublicIds(array $data)
|
public static function remapPublicIds($items)
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
|
|
||||||
foreach ($data as $key => $val) {
|
foreach ($items as $item) {
|
||||||
if ($key === 'public_id') {
|
$return[] = $item->toPublicArray();
|
||||||
$key = 'id';
|
|
||||||
} elseif (strpos($key, '_id')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_array($val)) {
|
|
||||||
$val = Utils::remapPublicIds($val);
|
|
||||||
}
|
|
||||||
|
|
||||||
$return[$key] = $val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function hideIds($data)
|
||||||
|
{
|
||||||
|
$publicId = null;
|
||||||
|
|
||||||
|
foreach ($data as $key => $val) {
|
||||||
|
if (is_array($val)) {
|
||||||
|
$data[$key] = Utils::hideIds($val);
|
||||||
|
} else if ($key == 'id' || strpos($key, '_id')) {
|
||||||
|
if ($key == 'public_id') {
|
||||||
|
$publicId = $val;
|
||||||
|
}
|
||||||
|
unset($data[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($publicId) {
|
||||||
|
$data['id'] = $publicId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
public static function getApiHeaders($count = 0)
|
public static function getApiHeaders($count = 0)
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use Utils;
|
use Utils;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Carbon;
|
use Carbon;
|
||||||
|
use Session;
|
||||||
use App\Events\UserLoggedIn;
|
use App\Events\UserLoggedIn;
|
||||||
use App\Ninja\Repositories\AccountRepository;
|
use App\Ninja\Repositories\AccountRepository;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
@ -32,13 +33,16 @@ class HandleUserLoggedIn {
|
|||||||
{
|
{
|
||||||
$account = Auth::user()->account;
|
$account = Auth::user()->account;
|
||||||
|
|
||||||
if (!Utils::isNinja() && empty($account->last_login)) {
|
if (!Utils::isNinja() && Auth::user()->id == 1 && empty($account->last_login)) {
|
||||||
$this->accountRepo->registerUser(Auth::user());
|
$this->accountRepo->registerUser(Auth::user());
|
||||||
}
|
}
|
||||||
|
|
||||||
$account->last_login = Carbon::now()->toDateTimeString();
|
$account->last_login = Carbon::now()->toDateTimeString();
|
||||||
$account->save();
|
$account->save();
|
||||||
|
|
||||||
|
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
|
||||||
|
Session::put(SESSION_USER_ACCOUNTS, $users);
|
||||||
|
|
||||||
$account->loadLocalizationSettings();
|
$account->loadLocalizationSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,6 +133,13 @@ class Account extends Eloquent
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public function hasLogo()
|
||||||
|
{
|
||||||
|
file_exists($this->getLogoPath());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public function getLogoPath()
|
public function getLogoPath()
|
||||||
{
|
{
|
||||||
return 'logo/'.$this->account_key.'.jpg';
|
return 'logo/'.$this->account_key.'.jpg';
|
||||||
@ -250,6 +257,7 @@ class Account extends Eloquent
|
|||||||
'date',
|
'date',
|
||||||
'rate',
|
'rate',
|
||||||
'hours',
|
'hours',
|
||||||
|
'balance',
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($fields as $field) {
|
foreach ($fields as $field) {
|
||||||
|
@ -34,5 +34,9 @@ class AccountGateway extends EntityModel
|
|||||||
public function isPaymentType($type) {
|
public function isPaymentType($type) {
|
||||||
return $this->getPaymentType() == $type;
|
return $this->getPaymentType() == $type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isGateway($gatewayId) {
|
||||||
|
return $this->gateway_id == $gatewayId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ class Client extends EntityModel
|
|||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
return $this->getDisplayName();
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDisplayName()
|
public function getDisplayName()
|
||||||
@ -84,6 +84,7 @@ class Client extends EntityModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->load('contacts');
|
$this->load('contacts');
|
||||||
|
|
||||||
$contact = $this->contacts()->first();
|
$contact = $this->contacts()->first();
|
||||||
|
|
||||||
return $contact->getDisplayName();
|
return $contact->getDisplayName();
|
||||||
|
@ -38,6 +38,11 @@ class Contact extends EntityModel
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
public function getDisplayName()
|
public function getDisplayName()
|
||||||
{
|
{
|
||||||
if ($this->getFullName()) {
|
if ($this->getFullName()) {
|
||||||
|
@ -7,4 +7,9 @@ class Country extends Eloquent
|
|||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
protected $visible = ['id', 'name'];
|
protected $visible = ['id', 'name'];
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,9 @@ use Eloquent;
|
|||||||
class Currency extends Eloquent
|
class Currency extends Eloquent
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,4 +77,34 @@ class EntityModel extends Eloquent
|
|||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->public_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remap ids to public_ids and show name
|
||||||
|
public function toPublicArray()
|
||||||
|
{
|
||||||
|
$data = $this->toArray();
|
||||||
|
|
||||||
|
foreach ($this->attributes as $key => $val) {
|
||||||
|
if (strpos($key, '_id')) {
|
||||||
|
list($field, $id) = explode('_', $key);
|
||||||
|
if ($field == 'account') {
|
||||||
|
// do nothing
|
||||||
|
} else {
|
||||||
|
$entity = @$this->$field;
|
||||||
|
if ($entity) {
|
||||||
|
$data["{$field}_name"] = $entity->getName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = Utils::hideIds($data);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,9 @@ use Eloquent;
|
|||||||
class Industry extends Eloquent
|
class Industry extends Eloquent
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,10 @@ class Invitation extends EntityModel
|
|||||||
|
|
||||||
public function getLink()
|
public function getLink()
|
||||||
{
|
{
|
||||||
|
if (!$this->account) {
|
||||||
$this->load('account');
|
$this->load('account');
|
||||||
|
}
|
||||||
|
|
||||||
$url = SITE_URL;
|
$url = SITE_URL;
|
||||||
|
|
||||||
if ($this->account->subdomain) {
|
if ($this->account->subdomain) {
|
||||||
@ -41,4 +44,9 @@ class Invitation extends EntityModel
|
|||||||
|
|
||||||
return "{$url}/view/{$this->invitation_key}";
|
return "{$url}/view/{$this->invitation_key}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->invitation_key;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,11 @@ class Invoice extends EntityModel
|
|||||||
return $this->belongsTo('App\Models\InvoiceDesign');
|
return $this->belongsTo('App\Models\InvoiceDesign');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function recurring_invoice()
|
||||||
|
{
|
||||||
|
return $this->belongsTo('App\Models\Invoice');
|
||||||
|
}
|
||||||
|
|
||||||
public function invitations()
|
public function invitations()
|
||||||
{
|
{
|
||||||
return $this->hasMany('App\Models\Invitation')->orderBy('invitations.contact_id');
|
return $this->hasMany('App\Models\Invitation')->orderBy('invitations.contact_id');
|
||||||
|
@ -5,4 +5,9 @@ use Eloquent;
|
|||||||
class Size extends Eloquent
|
class Size extends Eloquent
|
||||||
{
|
{
|
||||||
public $timestamps = false;
|
public $timestamps = false;
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,11 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
return $this->belongsTo('App\Models\Theme');
|
return $this->belongsTo('App\Models\Theme');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
public function getPersonType()
|
public function getPersonType()
|
||||||
{
|
{
|
||||||
return PERSON_USER;
|
return PERSON_USER;
|
||||||
@ -196,4 +201,15 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function updateUser($user)
|
||||||
|
{
|
||||||
|
if ($user->password != !$user->getOriginal('password')) {
|
||||||
|
$user->failed_logins = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
User::updating(function ($user) {
|
||||||
|
User::updateUser($user);
|
||||||
|
});
|
||||||
|
@ -54,7 +54,11 @@ class ContactMailer extends Mailer
|
|||||||
$data['invoice_id'] = $invoice->id;
|
$data['invoice_id'] = $invoice->id;
|
||||||
|
|
||||||
$fromEmail = $invitation->user->email;
|
$fromEmail = $invitation->user->email;
|
||||||
$this->sendTo($invitation->contact->email, $fromEmail, $accountName, $subject, $view, $data);
|
$response = $this->sendTo($invitation->contact->email, $fromEmail, $accountName, $subject, $view, $data);
|
||||||
|
|
||||||
|
if ($response !== true) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
Activity::emailInvoice($invitation);
|
Activity::emailInvoice($invitation);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?php namespace App\Ninja\Mailers;
|
<?php namespace App\Ninja\Mailers;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
use Mail;
|
use Mail;
|
||||||
use Utils;
|
use Utils;
|
||||||
use App\Models\Invoice;
|
use App\Models\Invoice;
|
||||||
@ -13,13 +14,11 @@ class Mailer
|
|||||||
'emails.'.$view.'_text',
|
'emails.'.$view.'_text',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
try {
|
||||||
Mail::send($views, $data, function ($message) use ($toEmail, $fromEmail, $fromName, $subject, $data) {
|
Mail::send($views, $data, function ($message) use ($toEmail, $fromEmail, $fromName, $subject, $data) {
|
||||||
$replyEmail = $fromEmail;
|
|
||||||
|
|
||||||
// http://stackoverflow.com/questions/2421234/gmail-appearing-to-ignore-reply-to
|
$replyEmail = $fromEmail;
|
||||||
if (Utils::isNinja() && $toEmail != CONTACT_EMAIL) {
|
$fromEmail = CONTACT_EMAIL;
|
||||||
$fromEmail = NINJA_FROM_EMAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($data['invoice_id'])) {
|
if(isset($data['invoice_id'])) {
|
||||||
$invoice = Invoice::with('account')->where('id', '=', $data['invoice_id'])->get()->first();
|
$invoice = Invoice::with('account')->where('id', '=', $data['invoice_id'])->get()->first();
|
||||||
@ -31,8 +30,14 @@ class Mailer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//$message->setEncoder(\Swift_Encoding::get8BitEncoding());
|
|
||||||
$message->to($toEmail)->from($fromEmail, $fromName)->replyTo($replyEmail, $fromName)->subject($subject);
|
$message->to($toEmail)->from($fromEmail, $fromName)->replyTo($replyEmail, $fromName)->subject($subject);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$response = $e->getResponse()->getBody()->getContents();
|
||||||
|
$response = json_decode($response);
|
||||||
|
return nl2br($response->Message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -294,6 +294,7 @@ class AccountRepository
|
|||||||
$item->account_id = $user->account->id;
|
$item->account_id = $user->account->id;
|
||||||
$item->account_name = $user->account->getDisplayName();
|
$item->account_name = $user->account->getDisplayName();
|
||||||
$item->pro_plan_paid = $user->account->pro_plan_paid;
|
$item->pro_plan_paid = $user->account->pro_plan_paid;
|
||||||
|
$item->account_key = file_exists($user->account->getLogoPath()) ? $user->account->account_key : null;
|
||||||
$data[] = $item;
|
$data[] = $item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,11 +364,19 @@ class AccountRepository
|
|||||||
return $users;
|
return $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function unlinkAccount($userAccountId, $userId) {
|
public function unlinkAccount($account) {
|
||||||
|
foreach ($account->users as $user) {
|
||||||
|
if ($userAccount = self::findUserAccounts($user->id)) {
|
||||||
|
$userAccount->removeUserId($user->id);
|
||||||
|
$userAccount->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unlinkUser($userAccountId, $userId) {
|
||||||
|
|
||||||
$userAccount = UserAccount::whereId($userAccountId)->first();
|
$userAccount = UserAccount::whereId($userAccountId)->first();
|
||||||
|
if ($userAccount->hasUserId($userId)) {
|
||||||
if ($userAccount->hasUserId(Auth::user()->id)) {
|
|
||||||
$userAccount->removeUserId($userId);
|
$userAccount->removeUserId($userId);
|
||||||
$userAccount->save();
|
$userAccount->save();
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,14 @@ class PaymentRepository
|
|||||||
$payment->payment_type_id = $paymentTypeId;
|
$payment->payment_type_id = $paymentTypeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isset($input['payment_date_sql'])) {
|
||||||
|
$payment->payment_date = $input['payment_date_sql'];
|
||||||
|
} elseif (isset($input['payment_date'])) {
|
||||||
$payment->payment_date = Utils::toSqlDate($input['payment_date']);
|
$payment->payment_date = Utils::toSqlDate($input['payment_date']);
|
||||||
|
} else {
|
||||||
|
$payment->payment_date = date('Y-m-d');
|
||||||
|
}
|
||||||
|
|
||||||
$payment->transaction_reference = trim($input['transaction_reference']);
|
$payment->transaction_reference = trim($input['transaction_reference']);
|
||||||
|
|
||||||
if (!$publicId) {
|
if (!$publicId) {
|
||||||
|
26
bower.json
26
bower.json
@ -2,22 +2,22 @@
|
|||||||
"name": "hillelcoren/invoice-ninja",
|
"name": "hillelcoren/invoice-ninja",
|
||||||
"version": "0.9.0",
|
"version": "0.9.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jquery": "~1.11",
|
"jquery": "1.11.3",
|
||||||
"bootstrap": "~3.*",
|
"bootstrap": "3.3.1",
|
||||||
"jquery-ui": "~1.*",
|
"jquery-ui": "1.11.2",
|
||||||
"datatables": "1.10.4",
|
"datatables": "1.10.4",
|
||||||
"datatables-bootstrap3": "*",
|
"datatables-bootstrap3": "*",
|
||||||
"knockout.js": "~3.*",
|
"knockout.js": "3.1.0",
|
||||||
"knockout-mapping": "*",
|
"knockout-mapping": "2.4.1",
|
||||||
"knockout-sortable": "*",
|
"knockout-sortable": "0.9.3",
|
||||||
"font-awesome": "~4.*",
|
"font-awesome": "~4.*",
|
||||||
"underscore": "~1.*",
|
"underscore": "1.7.0",
|
||||||
"jspdf": "*",
|
"jspdf": "1.0.272",
|
||||||
"bootstrap-datepicker": "~1.*",
|
"bootstrap-datepicker": "1.4.0",
|
||||||
"typeahead.js": "~0.9.3",
|
"typeahead.js": "0.9.3",
|
||||||
"accounting": "~0.*",
|
"accounting": "0.3.2",
|
||||||
"spectrum": "~1.3.4",
|
"spectrum": "1.3.4",
|
||||||
"d3": "~3.4.11",
|
"d3": "3.4.11",
|
||||||
"handsontable": "*",
|
"handsontable": "*",
|
||||||
"pdfmake": "*",
|
"pdfmake": "*",
|
||||||
"moment": "*"
|
"moment": "*"
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
|
||||||
|
class SupportLockingAccount extends Migration {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function($table)
|
||||||
|
{
|
||||||
|
$table->smallInteger('failed_logins')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('account_gateways', function($table)
|
||||||
|
{
|
||||||
|
$table->boolean('show_address')->default(true)->nullable();
|
||||||
|
$table->boolean('update_address')->default(true)->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function($table)
|
||||||
|
{
|
||||||
|
$table->dropColumn('failed_logins');
|
||||||
|
});
|
||||||
|
|
||||||
|
Schema::table('account_gateways', function($table)
|
||||||
|
{
|
||||||
|
$table->dropColumn('show_address');
|
||||||
|
$table->dropColumn('update_address');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
60
public/css/built.css
vendored
60
public/css/built.css
vendored
File diff suppressed because one or more lines are too long
4
public/css/built.public.css
vendored
4
public/css/built.public.css
vendored
File diff suppressed because one or more lines are too long
BIN
public/fonts/fontawesome-webfont.woff2
Normal file
BIN
public/fonts/fontawesome-webfont.woff2
Normal file
Binary file not shown.
@ -27152,31 +27152,13 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
}
|
}
|
||||||
}.call(this));
|
}.call(this));
|
||||||
|
|
||||||
/* =========================================================
|
/*!
|
||||||
* bootstrap-datepicker.js
|
* Datepicker for Bootstrap v1.4.0 (https://github.com/eternicode/bootstrap-datepicker)
|
||||||
* Repo: https://github.com/eternicode/bootstrap-datepicker/
|
|
||||||
* Demo: http://eternicode.github.io/bootstrap-datepicker/
|
|
||||||
* Docs: http://bootstrap-datepicker.readthedocs.org/
|
|
||||||
* Forked from http://www.eyecon.ro/bootstrap-datepicker
|
|
||||||
* =========================================================
|
|
||||||
* Started by Stefan Petre; improvements by Andrew Rowls + contributors
|
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Copyright 2012 Stefan Petre
|
||||||
* you may not use this file except in compliance with the License.
|
* Improvements by Andrew Rowls
|
||||||
* You may obtain a copy of the License at
|
* Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
*
|
*/(function($, undefined){
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
* ========================================================= */
|
|
||||||
|
|
||||||
(function($, undefined){
|
|
||||||
|
|
||||||
var $window = $(window);
|
|
||||||
|
|
||||||
function UTCDate(){
|
function UTCDate(){
|
||||||
return new Date(Date.UTC.apply(Date, arguments));
|
return new Date(Date.UTC.apply(Date, arguments));
|
||||||
@ -27185,6 +27167,13 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
var today = new Date();
|
var today = new Date();
|
||||||
return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
|
return UTCDate(today.getFullYear(), today.getMonth(), today.getDate());
|
||||||
}
|
}
|
||||||
|
function isUTCEquals(date1, date2) {
|
||||||
|
return (
|
||||||
|
date1.getUTCFullYear() === date2.getUTCFullYear() &&
|
||||||
|
date1.getUTCMonth() === date2.getUTCMonth() &&
|
||||||
|
date1.getUTCDate() === date2.getUTCDate()
|
||||||
|
);
|
||||||
|
}
|
||||||
function alias(method){
|
function alias(method){
|
||||||
return function(){
|
return function(){
|
||||||
return this[method].apply(this, arguments);
|
return this[method].apply(this, arguments);
|
||||||
@ -27238,16 +27227,16 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
// Picker object
|
// Picker object
|
||||||
|
|
||||||
var Datepicker = function(element, options){
|
var Datepicker = function(element, options){
|
||||||
this.dates = new DateArray();
|
|
||||||
this.viewDate = UTCToday();
|
|
||||||
this.focusDate = null;
|
|
||||||
|
|
||||||
this._process_options(options);
|
this._process_options(options);
|
||||||
|
|
||||||
|
this.dates = new DateArray();
|
||||||
|
this.viewDate = this.o.defaultViewDate;
|
||||||
|
this.focusDate = null;
|
||||||
|
|
||||||
this.element = $(element);
|
this.element = $(element);
|
||||||
this.isInline = false;
|
this.isInline = false;
|
||||||
this.isInput = this.element.is('input');
|
this.isInput = this.element.is('input');
|
||||||
this.component = this.element.is('.date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
|
this.component = this.element.hasClass('date') ? this.element.find('.add-on, .input-group-addon, .btn') : false;
|
||||||
this.hasInput = this.component && this.element.find('input').length;
|
this.hasInput = this.component && this.element.find('input').length;
|
||||||
if (this.component && this.component.length === 0)
|
if (this.component && this.component.length === 0)
|
||||||
this.component = false;
|
this.component = false;
|
||||||
@ -27270,7 +27259,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this.viewMode = this.o.startView;
|
this.viewMode = this.o.startView;
|
||||||
|
|
||||||
if (this.o.calendarWeeks)
|
if (this.o.calendarWeeks)
|
||||||
this.picker.find('tfoot th.today, tfoot th.clear')
|
this.picker.find('tfoot .today, tfoot .clear')
|
||||||
.attr('colspan', function(i, val){
|
.attr('colspan', function(i, val){
|
||||||
return parseInt(val) + 1;
|
return parseInt(val) + 1;
|
||||||
});
|
});
|
||||||
@ -27280,6 +27269,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this.setStartDate(this._o.startDate);
|
this.setStartDate(this._o.startDate);
|
||||||
this.setEndDate(this._o.endDate);
|
this.setEndDate(this._o.endDate);
|
||||||
this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
|
this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled);
|
||||||
|
this.setDatesDisabled(this.o.datesDisabled);
|
||||||
|
|
||||||
this.fillDow();
|
this.fillDow();
|
||||||
this.fillMonths();
|
this.fillMonths();
|
||||||
@ -27346,8 +27336,6 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
o.multidate = Number(o.multidate) || false;
|
o.multidate = Number(o.multidate) || false;
|
||||||
if (o.multidate !== false)
|
if (o.multidate !== false)
|
||||||
o.multidate = Math.max(0, o.multidate);
|
o.multidate = Math.max(0, o.multidate);
|
||||||
else
|
|
||||||
o.multidate = 1;
|
|
||||||
}
|
}
|
||||||
o.multidateSeparator = String(o.multidateSeparator);
|
o.multidateSeparator = String(o.multidateSeparator);
|
||||||
|
|
||||||
@ -27385,10 +27373,20 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
return parseInt(d, 10);
|
return parseInt(d, 10);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
o.datesDisabled = o.datesDisabled||[];
|
||||||
|
if (!$.isArray(o.datesDisabled)) {
|
||||||
|
var datesDisabled = [];
|
||||||
|
datesDisabled.push(DPGlobal.parseDate(o.datesDisabled, format, o.language));
|
||||||
|
o.datesDisabled = datesDisabled;
|
||||||
|
}
|
||||||
|
o.datesDisabled = $.map(o.datesDisabled,function(d){
|
||||||
|
return DPGlobal.parseDate(d, format, o.language);
|
||||||
|
});
|
||||||
|
|
||||||
var plc = String(o.orientation).toLowerCase().split(/\s+/g),
|
var plc = String(o.orientation).toLowerCase().split(/\s+/g),
|
||||||
_plc = o.orientation.toLowerCase();
|
_plc = o.orientation.toLowerCase();
|
||||||
plc = $.grep(plc, function(word){
|
plc = $.grep(plc, function(word){
|
||||||
return (/^auto|left|right|top|bottom$/).test(word);
|
return /^auto|left|right|top|bottom$/.test(word);
|
||||||
});
|
});
|
||||||
o.orientation = {x: 'auto', y: 'auto'};
|
o.orientation = {x: 'auto', y: 'auto'};
|
||||||
if (!_plc || _plc === 'auto')
|
if (!_plc || _plc === 'auto')
|
||||||
@ -27407,15 +27405,24 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
_plc = $.grep(plc, function(word){
|
_plc = $.grep(plc, function(word){
|
||||||
return (/^left|right$/).test(word);
|
return /^left|right$/.test(word);
|
||||||
});
|
});
|
||||||
o.orientation.x = _plc[0] || 'auto';
|
o.orientation.x = _plc[0] || 'auto';
|
||||||
|
|
||||||
_plc = $.grep(plc, function(word){
|
_plc = $.grep(plc, function(word){
|
||||||
return (/^top|bottom$/).test(word);
|
return /^top|bottom$/.test(word);
|
||||||
});
|
});
|
||||||
o.orientation.y = _plc[0] || 'auto';
|
o.orientation.y = _plc[0] || 'auto';
|
||||||
}
|
}
|
||||||
|
if (o.defaultViewDate) {
|
||||||
|
var year = o.defaultViewDate.year || new Date().getFullYear();
|
||||||
|
var month = o.defaultViewDate.month || 0;
|
||||||
|
var day = o.defaultViewDate.day || 1;
|
||||||
|
o.defaultViewDate = UTCDate(year, month, day);
|
||||||
|
} else {
|
||||||
|
o.defaultViewDate = UTCToday();
|
||||||
|
}
|
||||||
|
o.showOnFocus = o.showOnFocus !== undefined ? o.showOnFocus : true;
|
||||||
},
|
},
|
||||||
_events: [],
|
_events: [],
|
||||||
_secondaryEvents: [],
|
_secondaryEvents: [],
|
||||||
@ -27448,29 +27455,27 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_buildEvents: function(){
|
_buildEvents: function(){
|
||||||
if (this.isInput){ // single input
|
var events = {
|
||||||
this._events = [
|
|
||||||
[this.element, {
|
|
||||||
focus: $.proxy(this.show, this),
|
|
||||||
keyup: $.proxy(function(e){
|
keyup: $.proxy(function(e){
|
||||||
if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
|
if ($.inArray(e.keyCode, [27, 37, 39, 38, 40, 32, 13, 9]) === -1)
|
||||||
this.update();
|
this.update();
|
||||||
}, this),
|
}, this),
|
||||||
keydown: $.proxy(this.keydown, this)
|
keydown: $.proxy(this.keydown, this)
|
||||||
}]
|
};
|
||||||
|
|
||||||
|
if (this.o.showOnFocus === true) {
|
||||||
|
events.focus = $.proxy(this.show, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isInput) { // single input
|
||||||
|
this._events = [
|
||||||
|
[this.element, events]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
else if (this.component && this.hasInput) { // component: input + button
|
else if (this.component && this.hasInput) { // component: input + button
|
||||||
this._events = [
|
this._events = [
|
||||||
// For components that are not readonly, allow keyboard nav
|
// For components that are not readonly, allow keyboard nav
|
||||||
[this.element.find('input'), {
|
[this.element.find('input'), events],
|
||||||
focus: $.proxy(this.show, this),
|
|
||||||
keyup: $.proxy(function(e){
|
|
||||||
if ($.inArray(e.keyCode, [27,37,39,38,40,32,13,9]) === -1)
|
|
||||||
this.update();
|
|
||||||
}, this),
|
|
||||||
keydown: $.proxy(this.keydown, this)
|
|
||||||
}],
|
|
||||||
[this.component, {
|
[this.component, {
|
||||||
click: $.proxy(this.show, this)
|
click: $.proxy(this.show, this)
|
||||||
}]
|
}]
|
||||||
@ -27562,19 +27567,25 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
},
|
},
|
||||||
|
|
||||||
show: function(){
|
show: function(){
|
||||||
|
if (this.element.attr('readonly') && this.o.enableOnReadonly === false)
|
||||||
|
return;
|
||||||
if (!this.isInline)
|
if (!this.isInline)
|
||||||
this.picker.appendTo('body');
|
this.picker.appendTo(this.o.container);
|
||||||
this.picker.show();
|
|
||||||
this.place();
|
this.place();
|
||||||
|
this.picker.show();
|
||||||
this._attachSecondaryEvents();
|
this._attachSecondaryEvents();
|
||||||
this._trigger('show');
|
this._trigger('show');
|
||||||
|
if ((window.navigator.msMaxTouchPoints || 'ontouchstart' in document) && this.o.disableTouchKeyboard) {
|
||||||
|
$(this.element).blur();
|
||||||
|
}
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
hide: function(){
|
hide: function(){
|
||||||
if (this.isInline)
|
if (this.isInline)
|
||||||
return;
|
return this;
|
||||||
if (!this.picker.is(':visible'))
|
if (!this.picker.is(':visible'))
|
||||||
return;
|
return this;
|
||||||
this.focusDate = null;
|
this.focusDate = null;
|
||||||
this.picker.hide().detach();
|
this.picker.hide().detach();
|
||||||
this._detachSecondaryEvents();
|
this._detachSecondaryEvents();
|
||||||
@ -27590,6 +27601,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
)
|
)
|
||||||
this.setValue();
|
this.setValue();
|
||||||
this._trigger('hide');
|
this._trigger('hide');
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
remove: function(){
|
remove: function(){
|
||||||
@ -27601,6 +27613,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
if (!this.isInput){
|
if (!this.isInput){
|
||||||
delete this.element.data().date;
|
delete this.element.data().date;
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
_utc_to_local: function(utc){
|
_utc_to_local: function(utc){
|
||||||
@ -27631,14 +27644,39 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
},
|
},
|
||||||
|
|
||||||
getUTCDate: function(){
|
getUTCDate: function(){
|
||||||
return new Date(this.dates.get(-1));
|
var selected_date = this.dates.get(-1);
|
||||||
|
if (typeof selected_date !== 'undefined') {
|
||||||
|
return new Date(selected_date);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearDates: function(){
|
||||||
|
var element;
|
||||||
|
if (this.isInput) {
|
||||||
|
element = this.element;
|
||||||
|
} else if (this.component) {
|
||||||
|
element = this.element.find('input');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
element.val('').change();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
this._trigger('changeDate');
|
||||||
|
|
||||||
|
if (this.o.autoclose) {
|
||||||
|
this.hide();
|
||||||
|
}
|
||||||
|
},
|
||||||
setDates: function(){
|
setDates: function(){
|
||||||
var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
|
var args = $.isArray(arguments[0]) ? arguments[0] : arguments;
|
||||||
this.update.apply(this, args);
|
this.update.apply(this, args);
|
||||||
this._trigger('changeDate');
|
this._trigger('changeDate');
|
||||||
this.setValue();
|
this.setValue();
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
setUTCDates: function(){
|
setUTCDates: function(){
|
||||||
@ -27646,6 +27684,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this.update.apply(this, $.map(args, this._utc_to_local));
|
this.update.apply(this, $.map(args, this._utc_to_local));
|
||||||
this._trigger('changeDate');
|
this._trigger('changeDate');
|
||||||
this.setValue();
|
this.setValue();
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
setDate: alias('setDates'),
|
setDate: alias('setDates'),
|
||||||
@ -27661,6 +27700,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
else {
|
else {
|
||||||
this.element.val(formatted).change();
|
this.element.val(formatted).change();
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormattedDate: function(format){
|
getFormattedDate: function(format){
|
||||||
@ -27677,29 +27717,39 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this._process_options({startDate: startDate});
|
this._process_options({startDate: startDate});
|
||||||
this.update();
|
this.update();
|
||||||
this.updateNavArrows();
|
this.updateNavArrows();
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
setEndDate: function(endDate){
|
setEndDate: function(endDate){
|
||||||
this._process_options({endDate: endDate});
|
this._process_options({endDate: endDate});
|
||||||
this.update();
|
this.update();
|
||||||
this.updateNavArrows();
|
this.updateNavArrows();
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
setDaysOfWeekDisabled: function(daysOfWeekDisabled){
|
setDaysOfWeekDisabled: function(daysOfWeekDisabled){
|
||||||
this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
|
this._process_options({daysOfWeekDisabled: daysOfWeekDisabled});
|
||||||
this.update();
|
this.update();
|
||||||
this.updateNavArrows();
|
this.updateNavArrows();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
setDatesDisabled: function(datesDisabled){
|
||||||
|
this._process_options({datesDisabled: datesDisabled});
|
||||||
|
this.update();
|
||||||
|
this.updateNavArrows();
|
||||||
},
|
},
|
||||||
|
|
||||||
place: function(){
|
place: function(){
|
||||||
if (this.isInline)
|
if (this.isInline)
|
||||||
return;
|
return this;
|
||||||
var calendarWidth = this.picker.outerWidth(),
|
var calendarWidth = this.picker.outerWidth(),
|
||||||
calendarHeight = this.picker.outerHeight(),
|
calendarHeight = this.picker.outerHeight(),
|
||||||
visualPadding = 10,
|
visualPadding = 10,
|
||||||
windowWidth = $window.width(),
|
windowWidth = $(this.o.container).width(),
|
||||||
windowHeight = $window.height(),
|
windowHeight = $(this.o.container).height(),
|
||||||
scrollTop = $window.scrollTop();
|
scrollTop = $(this.o.container).scrollTop(),
|
||||||
|
appendOffset = $(this.o.container).offset();
|
||||||
|
|
||||||
var parentsZindex = [];
|
var parentsZindex = [];
|
||||||
this.element.parents().each(function(){
|
this.element.parents().each(function(){
|
||||||
@ -27710,8 +27760,8 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
var offset = this.component ? this.component.parent().offset() : this.element.offset();
|
var offset = this.component ? this.component.parent().offset() : this.element.offset();
|
||||||
var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
|
var height = this.component ? this.component.outerHeight(true) : this.element.outerHeight(false);
|
||||||
var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
|
var width = this.component ? this.component.outerWidth(true) : this.element.outerWidth(false);
|
||||||
var left = offset.left,
|
var left = offset.left - appendOffset.left,
|
||||||
top = offset.top;
|
top = offset.top - appendOffset.top;
|
||||||
|
|
||||||
this.picker.removeClass(
|
this.picker.removeClass(
|
||||||
'datepicker-orient-top datepicker-orient-bottom '+
|
'datepicker-orient-top datepicker-orient-bottom '+
|
||||||
@ -27726,12 +27776,18 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
// auto x orientation is best-placement: if it crosses a window
|
// auto x orientation is best-placement: if it crosses a window
|
||||||
// edge, fudge it sideways
|
// edge, fudge it sideways
|
||||||
else {
|
else {
|
||||||
|
if (offset.left < 0) {
|
||||||
|
// component is outside the window on the left side. Move it into visible range
|
||||||
|
this.picker.addClass('datepicker-orient-left');
|
||||||
|
left -= offset.left - visualPadding;
|
||||||
|
} else if (left + calendarWidth > windowWidth) {
|
||||||
|
// the calendar passes the widow right edge. Align it to component right side
|
||||||
|
this.picker.addClass('datepicker-orient-right');
|
||||||
|
left = offset.left + width - calendarWidth;
|
||||||
|
} else {
|
||||||
// Default to left
|
// Default to left
|
||||||
this.picker.addClass('datepicker-orient-left');
|
this.picker.addClass('datepicker-orient-left');
|
||||||
if (offset.left < 0)
|
}
|
||||||
left -= offset.left - visualPadding;
|
|
||||||
else if (offset.left + calendarWidth > windowWidth)
|
|
||||||
left = windowWidth - calendarWidth - visualPadding;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto y orientation is best-situation: top or bottom, no fudging,
|
// auto y orientation is best-situation: top or bottom, no fudging,
|
||||||
@ -27739,8 +27795,8 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
var yorient = this.o.orientation.y,
|
var yorient = this.o.orientation.y,
|
||||||
top_overflow, bottom_overflow;
|
top_overflow, bottom_overflow;
|
||||||
if (yorient === 'auto'){
|
if (yorient === 'auto'){
|
||||||
top_overflow = -scrollTop + offset.top - calendarHeight;
|
top_overflow = -scrollTop + top - calendarHeight;
|
||||||
bottom_overflow = scrollTop + windowHeight - (offset.top + height + calendarHeight);
|
bottom_overflow = scrollTop + windowHeight - (top + height + calendarHeight);
|
||||||
if (Math.max(top_overflow, bottom_overflow) === bottom_overflow)
|
if (Math.max(top_overflow, bottom_overflow) === bottom_overflow)
|
||||||
yorient = 'top';
|
yorient = 'top';
|
||||||
else
|
else
|
||||||
@ -27752,17 +27808,27 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
else
|
else
|
||||||
top -= calendarHeight + parseInt(this.picker.css('padding-top'));
|
top -= calendarHeight + parseInt(this.picker.css('padding-top'));
|
||||||
|
|
||||||
|
if (this.o.rtl) {
|
||||||
|
var right = windowWidth - (left + width);
|
||||||
|
this.picker.css({
|
||||||
|
top: top,
|
||||||
|
right: right,
|
||||||
|
zIndex: zIndex
|
||||||
|
});
|
||||||
|
} else {
|
||||||
this.picker.css({
|
this.picker.css({
|
||||||
top: top,
|
top: top,
|
||||||
left: left,
|
left: left,
|
||||||
zIndex: zIndex
|
zIndex: zIndex
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
_allow_update: true,
|
_allow_update: true,
|
||||||
update: function(){
|
update: function(){
|
||||||
if (!this._allow_update)
|
if (!this._allow_update)
|
||||||
return;
|
return this;
|
||||||
|
|
||||||
var oldDates = this.dates.copy(),
|
var oldDates = this.dates.copy(),
|
||||||
dates = [],
|
dates = [],
|
||||||
@ -27818,15 +27884,19 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this._trigger('clearDate');
|
this._trigger('clearDate');
|
||||||
|
|
||||||
this.fill();
|
this.fill();
|
||||||
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
fillDow: function(){
|
fillDow: function(){
|
||||||
var dowCnt = this.o.weekStart,
|
var dowCnt = this.o.weekStart,
|
||||||
html = '<tr>';
|
html = '<tr>';
|
||||||
if (this.o.calendarWeeks){
|
if (this.o.calendarWeeks){
|
||||||
var cell = '<th class="cw"> </th>';
|
this.picker.find('.datepicker-days thead tr:first-child .datepicker-switch')
|
||||||
|
.attr('colspan', function(i, val){
|
||||||
|
return parseInt(val) + 1;
|
||||||
|
});
|
||||||
|
var cell = '<th class="cw"> </th>';
|
||||||
html += cell;
|
html += cell;
|
||||||
this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
|
|
||||||
}
|
}
|
||||||
while (dowCnt < this.o.weekStart + 7){
|
while (dowCnt < this.o.weekStart + 7){
|
||||||
html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
|
html += '<th class="dow">'+dates[this.o.language].daysMin[(dowCnt++)%7]+'</th>';
|
||||||
@ -27880,6 +27950,12 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
$.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1){
|
$.inArray(date.getUTCDay(), this.o.daysOfWeekDisabled) !== -1){
|
||||||
cls.push('disabled');
|
cls.push('disabled');
|
||||||
}
|
}
|
||||||
|
if (this.o.datesDisabled.length > 0 &&
|
||||||
|
$.grep(this.o.datesDisabled, function(d){
|
||||||
|
return isUTCEquals(date, d); }).length > 0) {
|
||||||
|
cls.push('disabled', 'disabled-date');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.range){
|
if (this.range){
|
||||||
if (date > this.range[0] && date < this.range[this.range.length-1]){
|
if (date > this.range[0] && date < this.range[this.range.length-1]){
|
||||||
cls.push('range');
|
cls.push('range');
|
||||||
@ -27902,13 +27978,14 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
todaytxt = dates[this.o.language].today || dates['en'].today || '',
|
todaytxt = dates[this.o.language].today || dates['en'].today || '',
|
||||||
cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
|
cleartxt = dates[this.o.language].clear || dates['en'].clear || '',
|
||||||
tooltip;
|
tooltip;
|
||||||
if (isNaN(year) || isNaN(month)) return;
|
if (isNaN(year) || isNaN(month))
|
||||||
this.picker.find('.datepicker-days thead th.datepicker-switch')
|
return;
|
||||||
|
this.picker.find('.datepicker-days thead .datepicker-switch')
|
||||||
.text(dates[this.o.language].months[month]+' '+year);
|
.text(dates[this.o.language].months[month]+' '+year);
|
||||||
this.picker.find('tfoot th.today')
|
this.picker.find('tfoot .today')
|
||||||
.text(todaytxt)
|
.text(todaytxt)
|
||||||
.toggle(this.o.todayBtn !== false);
|
.toggle(this.o.todayBtn !== false);
|
||||||
this.picker.find('tfoot th.clear')
|
this.picker.find('tfoot .clear')
|
||||||
.text(cleartxt)
|
.text(cleartxt)
|
||||||
.toggle(this.o.clearBtn !== false);
|
.toggle(this.o.clearBtn !== false);
|
||||||
this.updateNavArrows();
|
this.updateNavArrows();
|
||||||
@ -27991,6 +28068,18 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
months.slice(endMonth+1).addClass('disabled');
|
months.slice(endMonth+1).addClass('disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.o.beforeShowMonth !== $.noop){
|
||||||
|
var that = this;
|
||||||
|
$.each(months, function(i, month){
|
||||||
|
if (!$(month).hasClass('disabled')) {
|
||||||
|
var moDate = new Date(year, i, 1);
|
||||||
|
var before = that.o.beforeShowMonth(moDate);
|
||||||
|
if (before === false)
|
||||||
|
$(month).addClass('disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
html = '';
|
html = '';
|
||||||
year = parseInt(year/10, 10) * 10;
|
year = parseInt(year/10, 10) * 10;
|
||||||
var yearCont = this.picker.find('.datepicker-years')
|
var yearCont = this.picker.find('.datepicker-years')
|
||||||
@ -28096,24 +28185,14 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this._setDate(date, which);
|
this._setDate(date, which);
|
||||||
break;
|
break;
|
||||||
case 'clear':
|
case 'clear':
|
||||||
var element;
|
this.clearDates();
|
||||||
if (this.isInput)
|
|
||||||
element = this.element;
|
|
||||||
else if (this.component)
|
|
||||||
element = this.element.find('input');
|
|
||||||
if (element)
|
|
||||||
element.val("").change();
|
|
||||||
this.update();
|
|
||||||
this._trigger('changeDate');
|
|
||||||
if (this.o.autoclose)
|
|
||||||
this.hide();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'span':
|
case 'span':
|
||||||
if (!target.is('.disabled')){
|
if (!target.hasClass('disabled')){
|
||||||
this.viewDate.setUTCDate(1);
|
this.viewDate.setUTCDate(1);
|
||||||
if (target.is('.month')){
|
if (target.hasClass('month')){
|
||||||
day = 1;
|
day = 1;
|
||||||
month = target.parent().find('span').index(target);
|
month = target.parent().find('span').index(target);
|
||||||
year = this.viewDate.getUTCFullYear();
|
year = this.viewDate.getUTCFullYear();
|
||||||
@ -28138,11 +28217,11 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'td':
|
case 'td':
|
||||||
if (target.is('.day') && !target.is('.disabled')){
|
if (target.hasClass('day') && !target.hasClass('disabled')){
|
||||||
day = parseInt(target.text(), 10)||1;
|
day = parseInt(target.text(), 10)||1;
|
||||||
year = this.viewDate.getUTCFullYear();
|
year = this.viewDate.getUTCFullYear();
|
||||||
month = this.viewDate.getUTCMonth();
|
month = this.viewDate.getUTCMonth();
|
||||||
if (target.is('.old')){
|
if (target.hasClass('old')){
|
||||||
if (month === 0){
|
if (month === 0){
|
||||||
month = 11;
|
month = 11;
|
||||||
year -= 1;
|
year -= 1;
|
||||||
@ -28151,7 +28230,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
month -= 1;
|
month -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (target.is('.new')){
|
else if (target.hasClass('new')){
|
||||||
if (month === 11){
|
if (month === 11){
|
||||||
month = 0;
|
month = 0;
|
||||||
year += 1;
|
year += 1;
|
||||||
@ -28176,15 +28255,19 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
if (!date){
|
if (!date){
|
||||||
this.dates.clear();
|
this.dates.clear();
|
||||||
}
|
}
|
||||||
if (this.o.multidate === 1 && ix === 0){
|
|
||||||
// single datepicker, don't remove selected date
|
if (ix !== -1){
|
||||||
}
|
if (this.o.multidate === true || this.o.multidate > 1 || this.o.toggleActive){
|
||||||
else if (ix !== -1){
|
|
||||||
this.dates.remove(ix);
|
this.dates.remove(ix);
|
||||||
}
|
}
|
||||||
|
} else if (this.o.multidate === false) {
|
||||||
|
this.dates.clear();
|
||||||
|
this.dates.push(date);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
this.dates.push(date);
|
this.dates.push(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.o.multidate === 'number')
|
if (typeof this.o.multidate === 'number')
|
||||||
while (this.dates.length > this.o.multidate)
|
while (this.dates.length > this.o.multidate)
|
||||||
this.dates.remove(0);
|
this.dates.remove(0);
|
||||||
@ -28198,7 +28281,9 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
|
|
||||||
this.fill();
|
this.fill();
|
||||||
this.setValue();
|
this.setValue();
|
||||||
|
if (!which || which !== 'view') {
|
||||||
this._trigger('changeDate');
|
this._trigger('changeDate');
|
||||||
|
}
|
||||||
var element;
|
var element;
|
||||||
if (this.isInput){
|
if (this.isInput){
|
||||||
element = this.element;
|
element = this.element;
|
||||||
@ -28273,7 +28358,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
},
|
},
|
||||||
|
|
||||||
keydown: function(e){
|
keydown: function(e){
|
||||||
if (this.picker.is(':not(:visible)')){
|
if (!this.picker.is(':visible')){
|
||||||
if (e.keyCode === 27) // allow escape to hide and re-show picker
|
if (e.keyCode === 27) // allow escape to hide and re-show picker
|
||||||
this.show();
|
this.show();
|
||||||
return;
|
return;
|
||||||
@ -28313,7 +28398,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
newViewDate = new Date(focusDate);
|
newViewDate = new Date(focusDate);
|
||||||
newViewDate.setUTCDate(focusDate.getUTCDate() + dir);
|
newViewDate.setUTCDate(focusDate.getUTCDate() + dir);
|
||||||
}
|
}
|
||||||
if (this.dateWithinRange(newDate)){
|
if (this.dateWithinRange(newViewDate)){
|
||||||
this.focusDate = this.viewDate = newViewDate;
|
this.focusDate = this.viewDate = newViewDate;
|
||||||
this.setValue();
|
this.setValue();
|
||||||
this.fill();
|
this.fill();
|
||||||
@ -28341,7 +28426,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
newViewDate = new Date(focusDate);
|
newViewDate = new Date(focusDate);
|
||||||
newViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7);
|
newViewDate.setUTCDate(focusDate.getUTCDate() + dir * 7);
|
||||||
}
|
}
|
||||||
if (this.dateWithinRange(newDate)){
|
if (this.dateWithinRange(newViewDate)){
|
||||||
this.focusDate = this.viewDate = newViewDate;
|
this.focusDate = this.viewDate = newViewDate;
|
||||||
this.setValue();
|
this.setValue();
|
||||||
this.fill();
|
this.fill();
|
||||||
@ -28364,6 +28449,11 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this.fill();
|
this.fill();
|
||||||
if (this.picker.is(':visible')){
|
if (this.picker.is(':visible')){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
if (typeof e.stopPropagation === 'function') {
|
||||||
|
e.stopPropagation(); // All modern browsers, IE9+
|
||||||
|
} else {
|
||||||
|
e.cancelBubble = true; // IE6,7,8 ignore "stopPropagation"
|
||||||
|
}
|
||||||
if (this.o.autoclose)
|
if (this.o.autoclose)
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
@ -28398,7 +28488,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir));
|
this.viewMode = Math.max(this.o.minViewMode, Math.min(2, this.viewMode + dir));
|
||||||
}
|
}
|
||||||
this.picker
|
this.picker
|
||||||
.find('>div')
|
.children('div')
|
||||||
.hide()
|
.hide()
|
||||||
.filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
|
.filter('.datepicker-' + DPGlobal.modes[this.viewMode].clsName)
|
||||||
.css('display', 'block');
|
.css('display', 'block');
|
||||||
@ -28413,8 +28503,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
});
|
});
|
||||||
delete options.inputs;
|
delete options.inputs;
|
||||||
|
|
||||||
$(this.inputs)
|
datepickerPlugin.call($(this.inputs), options)
|
||||||
.datepicker(options)
|
|
||||||
.bind('changeDate', $.proxy(this.dateUpdated, this));
|
.bind('changeDate', $.proxy(this.dateUpdated, this));
|
||||||
|
|
||||||
this.pickers = $.map(this.inputs, function(i){
|
this.pickers = $.map(this.inputs, function(i){
|
||||||
@ -28448,6 +28537,8 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
var dp = $(e.target).data('datepicker'),
|
var dp = $(e.target).data('datepicker'),
|
||||||
new_date = dp.getUTCDate(),
|
new_date = dp.getUTCDate(),
|
||||||
i = $.inArray(e.target, this.inputs),
|
i = $.inArray(e.target, this.inputs),
|
||||||
|
j = i - 1,
|
||||||
|
k = i + 1,
|
||||||
l = this.inputs.length;
|
l = this.inputs.length;
|
||||||
if (i === -1)
|
if (i === -1)
|
||||||
return;
|
return;
|
||||||
@ -28457,16 +28548,16 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
p.setUTCDate(new_date);
|
p.setUTCDate(new_date);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (new_date < this.dates[i]){
|
if (new_date < this.dates[j]){
|
||||||
// Date being moved earlier/left
|
// Date being moved earlier/left
|
||||||
while (i >= 0 && new_date < this.dates[i]){
|
while (j >= 0 && new_date < this.dates[j]){
|
||||||
this.pickers[i--].setUTCDate(new_date);
|
this.pickers[j--].setUTCDate(new_date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (new_date > this.dates[i]){
|
else if (new_date > this.dates[k]){
|
||||||
// Date being moved later/right
|
// Date being moved later/right
|
||||||
while (i < l && new_date > this.dates[i]){
|
while (k < l && new_date > this.dates[k]){
|
||||||
this.pickers[i++].setUTCDate(new_date);
|
this.pickers[k++].setUTCDate(new_date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.updateDates();
|
this.updateDates();
|
||||||
@ -28515,7 +28606,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
}
|
}
|
||||||
|
|
||||||
var old = $.fn.datepicker;
|
var old = $.fn.datepicker;
|
||||||
$.fn.datepicker = function(option){
|
var datepickerPlugin = function(option){
|
||||||
var args = Array.apply(null, arguments);
|
var args = Array.apply(null, arguments);
|
||||||
args.shift();
|
args.shift();
|
||||||
var internal_return;
|
var internal_return;
|
||||||
@ -28530,7 +28621,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
locopts = opts_from_locale(xopts.language),
|
locopts = opts_from_locale(xopts.language),
|
||||||
// Options priority: js args, data-attrs, locales, defaults
|
// Options priority: js args, data-attrs, locales, defaults
|
||||||
opts = $.extend({}, defaults, locopts, elopts, options);
|
opts = $.extend({}, defaults, locopts, elopts, options);
|
||||||
if ($this.is('.input-daterange') || opts.inputs){
|
if ($this.hasClass('input-daterange') || opts.inputs){
|
||||||
var ropts = {
|
var ropts = {
|
||||||
inputs: opts.inputs || $this.find('input').toArray()
|
inputs: opts.inputs || $this.find('input').toArray()
|
||||||
};
|
};
|
||||||
@ -28551,13 +28642,17 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
else
|
else
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
$.fn.datepicker = datepickerPlugin;
|
||||||
|
|
||||||
var defaults = $.fn.datepicker.defaults = {
|
var defaults = $.fn.datepicker.defaults = {
|
||||||
autoclose: false,
|
autoclose: false,
|
||||||
beforeShowDay: $.noop,
|
beforeShowDay: $.noop,
|
||||||
|
beforeShowMonth: $.noop,
|
||||||
calendarWeeks: false,
|
calendarWeeks: false,
|
||||||
clearBtn: false,
|
clearBtn: false,
|
||||||
|
toggleActive: false,
|
||||||
daysOfWeekDisabled: [],
|
daysOfWeekDisabled: [],
|
||||||
|
datesDisabled: [],
|
||||||
endDate: Infinity,
|
endDate: Infinity,
|
||||||
forceParse: true,
|
forceParse: true,
|
||||||
format: 'mm/dd/yyyy',
|
format: 'mm/dd/yyyy',
|
||||||
@ -28572,7 +28667,10 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
startView: 0,
|
startView: 0,
|
||||||
todayBtn: false,
|
todayBtn: false,
|
||||||
todayHighlight: false,
|
todayHighlight: false,
|
||||||
weekStart: 0
|
weekStart: 0,
|
||||||
|
disableTouchKeyboard: false,
|
||||||
|
enableOnReadonly: true,
|
||||||
|
container: 'body'
|
||||||
};
|
};
|
||||||
var locale_opts = $.fn.datepicker.locale_opts = [
|
var locale_opts = $.fn.datepicker.locale_opts = [
|
||||||
'format',
|
'format',
|
||||||
@ -28700,7 +28798,7 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
function match_part(){
|
function match_part(){
|
||||||
var m = this.slice(0, parts[i].length),
|
var m = this.slice(0, parts[i].length),
|
||||||
p = parts[i].slice(0, m.length);
|
p = parts[i].slice(0, m.length);
|
||||||
return m === p;
|
return m.toLowerCase() === p.toLowerCase();
|
||||||
}
|
}
|
||||||
if (parts.length === fparts.length){
|
if (parts.length === fparts.length){
|
||||||
var cnt;
|
var cnt;
|
||||||
@ -28762,9 +28860,9 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
},
|
},
|
||||||
headTemplate: '<thead>'+
|
headTemplate: '<thead>'+
|
||||||
'<tr>'+
|
'<tr>'+
|
||||||
'<th class="prev">«</th>'+
|
'<th class="prev">«</th>'+
|
||||||
'<th colspan="5" class="datepicker-switch"></th>'+
|
'<th colspan="5" class="datepicker-switch"></th>'+
|
||||||
'<th class="next">»</th>'+
|
'<th class="next">»</th>'+
|
||||||
'</tr>'+
|
'</tr>'+
|
||||||
'</thead>',
|
'</thead>',
|
||||||
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
|
contTemplate: '<tbody><tr><td colspan="7"></td></tr></tbody>',
|
||||||
@ -28812,6 +28910,9 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* DATEPICKER VERSION
|
||||||
|
* =================== */
|
||||||
|
$.fn.datepicker.version = "1.4.0";
|
||||||
|
|
||||||
/* DATEPICKER DATA-API
|
/* DATEPICKER DATA-API
|
||||||
* ================== */
|
* ================== */
|
||||||
@ -28825,11 +28926,11 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p
|
|||||||
return;
|
return;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// component click requires us to explicitly show it
|
// component click requires us to explicitly show it
|
||||||
$this.datepicker('show');
|
datepickerPlugin.call($this, 'show');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$(function(){
|
$(function(){
|
||||||
$('[data-provide="datepicker-inline"]').datepicker();
|
datepickerPlugin.call($('[data-provide="datepicker-inline"]'));
|
||||||
});
|
});
|
||||||
|
|
||||||
}(window.jQuery));
|
}(window.jQuery));
|
||||||
@ -32240,8 +32341,12 @@ function getInvoiceDetails(invoice) {
|
|||||||
{'due_date': invoice.due_date},
|
{'due_date': invoice.due_date},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) {
|
||||||
|
fields.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
|
||||||
|
}
|
||||||
|
|
||||||
if (NINJA.parseFloat(invoice.partial)) {
|
if (NINJA.parseFloat(invoice.partial)) {
|
||||||
fields.push({'total': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
fields.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.push({'balance_due': formatMoney(invoice.balance_amount, invoice.client.currency_id)})
|
fields.push({'balance_due': formatMoney(invoice.balance_amount, invoice.client.currency_id)})
|
||||||
@ -32297,12 +32402,16 @@ function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var paid = invoice.amount - invoice.balance;
|
var paid = invoice.amount - invoice.balance;
|
||||||
|
if (paid) {
|
||||||
|
data.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
|
||||||
|
}
|
||||||
|
|
||||||
if (invoice.account.hide_paid_to_date != '1' || paid) {
|
if (invoice.account.hide_paid_to_date != '1' || paid) {
|
||||||
data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)});
|
data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NINJA.parseFloat(invoice.partial) && invoice.total_amount != invoice.subtotal_amount) {
|
if (NINJA.parseFloat(invoice.partial) && invoice.total_amount != invoice.subtotal_amount) {
|
||||||
data.push({'total': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
data.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
|
32
public/js/pdfmake.min.js
vendored
32
public/js/pdfmake.min.js
vendored
File diff suppressed because one or more lines are too long
@ -705,8 +705,12 @@ function getInvoiceDetails(invoice) {
|
|||||||
{'due_date': invoice.due_date},
|
{'due_date': invoice.due_date},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (NINJA.parseFloat(invoice.balance) < NINJA.parseFloat(invoice.amount)) {
|
||||||
|
fields.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
|
||||||
|
}
|
||||||
|
|
||||||
if (NINJA.parseFloat(invoice.partial)) {
|
if (NINJA.parseFloat(invoice.partial)) {
|
||||||
fields.push({'total': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
fields.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
fields.push({'balance_due': formatMoney(invoice.balance_amount, invoice.client.currency_id)})
|
fields.push({'balance_due': formatMoney(invoice.balance_amount, invoice.client.currency_id)})
|
||||||
@ -762,12 +766,16 @@ function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX)
|
|||||||
}
|
}
|
||||||
|
|
||||||
var paid = invoice.amount - invoice.balance;
|
var paid = invoice.amount - invoice.balance;
|
||||||
|
if (paid) {
|
||||||
|
data.push({'total': formatMoney(invoice.amount, invoice.client.currency_id)});
|
||||||
|
}
|
||||||
|
|
||||||
if (invoice.account.hide_paid_to_date != '1' || paid) {
|
if (invoice.account.hide_paid_to_date != '1' || paid) {
|
||||||
data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)});
|
data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NINJA.parseFloat(invoice.partial) && invoice.total_amount != invoice.subtotal_amount) {
|
if (NINJA.parseFloat(invoice.partial) && invoice.total_amount != invoice.subtotal_amount) {
|
||||||
data.push({'total': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
data.push({'balance': formatMoney(invoice.total_amount, invoice.client.currency_id)});
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
|
@ -419,7 +419,7 @@ return array(
|
|||||||
'confirm_email_quote' => 'Bist du sicher, dass du dieses Angebot per E-Mail versenden möchtest',
|
'confirm_email_quote' => 'Bist du sicher, dass du dieses Angebot per E-Mail versenden möchtest',
|
||||||
'confirm_recurring_email_invoice' => 'Wiederkehrende Rechnung ist aktiv. Bis du sicher, dass du diese Rechnung weiterhin als E-Mail verschicken möchtest?',
|
'confirm_recurring_email_invoice' => 'Wiederkehrende Rechnung ist aktiv. Bis du sicher, dass du diese Rechnung weiterhin als E-Mail verschicken möchtest?',
|
||||||
|
|
||||||
'cancel_account' => 'Account Kündigen',
|
'cancel_account' => 'Konto Kündigen',
|
||||||
'cancel_account_message' => 'Warnung: Alle Daten werden unwiderruflich und vollständig gelöscht, es gibt kein zurück.',
|
'cancel_account_message' => 'Warnung: Alle Daten werden unwiderruflich und vollständig gelöscht, es gibt kein zurück.',
|
||||||
'go_back' => 'Zurück',
|
'go_back' => 'Zurück',
|
||||||
|
|
||||||
@ -562,7 +562,7 @@ return array(
|
|||||||
|
|
||||||
'api_tokens' => 'API Token',
|
'api_tokens' => 'API Token',
|
||||||
'users_and_tokens' => 'Benutzer & Token',
|
'users_and_tokens' => 'Benutzer & Token',
|
||||||
'account_login' => 'Account Login',
|
'account_login' => 'Konto Login',
|
||||||
'recover_password' => 'Passwort wiederherstellen',
|
'recover_password' => 'Passwort wiederherstellen',
|
||||||
'forgot_password' => 'Passwort vergessen?',
|
'forgot_password' => 'Passwort vergessen?',
|
||||||
'email_address' => 'E-Mail-Adresse',
|
'email_address' => 'E-Mail-Adresse',
|
||||||
@ -660,7 +660,7 @@ return array(
|
|||||||
'create_task' => 'Aufgabe erstellen',
|
'create_task' => 'Aufgabe erstellen',
|
||||||
'stopped_task' => 'Aufgabe erfolgreich angehalten',
|
'stopped_task' => 'Aufgabe erfolgreich angehalten',
|
||||||
'invoice_task' => 'Aufgabe in Rechnung stellen',
|
'invoice_task' => 'Aufgabe in Rechnung stellen',
|
||||||
'invoice_labels' => 'Rechnung Etiketten',
|
'invoice_labels' => 'Rechnung Spaltenüberschriften',
|
||||||
'prefix' => 'Präfix',
|
'prefix' => 'Präfix',
|
||||||
'counter' => 'Zähler',
|
'counter' => 'Zähler',
|
||||||
|
|
||||||
@ -670,32 +670,32 @@ return array(
|
|||||||
'more_actions' => 'More Actions',
|
'more_actions' => 'More Actions',
|
||||||
|
|
||||||
'pro_plan_title' => 'NINJA PRO',
|
'pro_plan_title' => 'NINJA PRO',
|
||||||
'pro_plan_call_to_action' => 'Upgrade Now!',
|
'pro_plan_call_to_action' => 'Jetzt Upgraden!',
|
||||||
'pro_plan_feature1' => 'Create Unlimited Clients',
|
'pro_plan_feature1' => 'Unlimitierte Anzahl Kunden erstellen',
|
||||||
'pro_plan_feature2' => 'Access to 10 Beautiful Invoice Designs',
|
'pro_plan_feature2' => 'Zugriff ui 10 schönen Rechnungsdesigns',
|
||||||
'pro_plan_feature3' => 'Custom URLs - "YourBrand.InvoiceNinja.com"',
|
'pro_plan_feature3' => 'Benutzerdefinierte URLs - "DeineFirma.InvoiceNinja.com"',
|
||||||
'pro_plan_feature4' => 'Remove "Created by Invoice Ninja"',
|
'pro_plan_feature4' => '"Created by Invoice Ninja" entfernen',
|
||||||
'pro_plan_feature5' => 'Multi-user Access & Activity Tracking',
|
'pro_plan_feature5' => 'Multi-Benutzer Zugriff & Aktivitätstracking',
|
||||||
'pro_plan_feature6' => 'Create Quotes & Pro-forma Invoices',
|
'pro_plan_feature6' => 'Angebote & pro-forma Rechnungen erstellen',
|
||||||
'pro_plan_feature7' => 'Customize Invoice Field Titles & Numbering',
|
'pro_plan_feature7' => 'Rechungstitelfelder und Nummerierung anpassen',
|
||||||
'pro_plan_feature8' => 'Option to Attach PDFs to Client Emails',
|
'pro_plan_feature8' => 'PDFs an E-Mails zu Kunden anhängen',
|
||||||
|
|
||||||
'resume' => 'Resume',
|
'resume' => 'Fortfahren',
|
||||||
'break_duration' => 'Break',
|
'break_duration' => 'Pause',
|
||||||
'edit_details' => 'Edit Details',
|
'edit_details' => 'Details bearbeiten',
|
||||||
'work' => 'Work',
|
'work' => 'Arbeiten',
|
||||||
'timezone_unset' => 'Please :link to set your timezone',
|
'timezone_unset' => 'Bitte :link um deine Zeitzone zu setzen',
|
||||||
'click_here' => 'click here',
|
'click_here' => 'hier klicken',
|
||||||
|
|
||||||
'email_receipt' => 'Email payment receipt to the client',
|
'email_receipt' => 'Zahlungsbestätigung an Kunden per E-Mail senden',
|
||||||
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
|
'created_payment_emailed_client' => 'Zahlung erfolgreich erstellt und Kunde per E-Mail benachrichtigt',
|
||||||
'add_account' => 'Add Account',
|
'add_account' => 'Konto hinzufügen',
|
||||||
'untitled' => 'Untitled',
|
'untitled' => 'Unbenannt',
|
||||||
'new_account' => 'New Account',
|
'new_account' => 'Neues Konto',
|
||||||
'associated_accounts' => 'Successfully linked accounts',
|
'associated_accounts' => 'Konten erfolgreich verlinkt',
|
||||||
'unlinked_account' => 'Successfully unlinked accounts',
|
'unlinked_account' => 'Konten erfolgreich getrennt',
|
||||||
'login' => 'Login',
|
'login' => 'Login',
|
||||||
'or' => 'or',
|
'or' => 'oder',
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
@ -704,4 +704,12 @@ return array(
|
|||||||
'login' => 'Login',
|
'login' => 'Login',
|
||||||
'or' => 'or',
|
'or' => 'or',
|
||||||
|
|
||||||
|
'email_error' => 'There was a problem sending the email',
|
||||||
|
'created_by_recurring' => 'Created by recurring invoice :invoice',
|
||||||
|
'confirm_recurring_timing' => 'Note: emails are sent at the start of the hour.',
|
||||||
|
'old_browser' => 'Please use a <a href="'.OUTDATE_BROWSER_URL.'" target="_blank">newer browser</a>',
|
||||||
|
'payment_terms_help' => 'Sets the default invoice due date',
|
||||||
|
'unlink_account' => 'Unlink Account',
|
||||||
|
'unlink' => 'Unlink',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
@ -14,7 +14,7 @@ return array(
|
|||||||
'state' => 'Région/Département',
|
'state' => 'Région/Département',
|
||||||
'postal_code' => 'Code postal',
|
'postal_code' => 'Code postal',
|
||||||
'country_id' => 'Pays',
|
'country_id' => 'Pays',
|
||||||
'contacts' => 'Informations de contact', //if you speak about contact details
|
'contacts' => 'Informations de contact',
|
||||||
'first_name' => 'Prénom',
|
'first_name' => 'Prénom',
|
||||||
'last_name' => 'Nom',
|
'last_name' => 'Nom',
|
||||||
'phone' => 'Téléphone',
|
'phone' => 'Téléphone',
|
||||||
@ -23,7 +23,7 @@ return array(
|
|||||||
'payment_terms' => 'Conditions de paiement',
|
'payment_terms' => 'Conditions de paiement',
|
||||||
'currency_id' => 'Devise',
|
'currency_id' => 'Devise',
|
||||||
'size_id' => 'Taille',
|
'size_id' => 'Taille',
|
||||||
'industry_id' => 'Secteur', // literal translation : Industrie
|
'industry_id' => 'Secteur',
|
||||||
'private_notes' => 'Note personnelle',
|
'private_notes' => 'Note personnelle',
|
||||||
|
|
||||||
// invoice
|
// invoice
|
||||||
@ -45,11 +45,11 @@ return array(
|
|||||||
'quantity' => 'Quantité',
|
'quantity' => 'Quantité',
|
||||||
'line_total' => 'Total',
|
'line_total' => 'Total',
|
||||||
'subtotal' => 'Total',
|
'subtotal' => 'Total',
|
||||||
'paid_to_date' => 'Versé à ce jour',//this one is not very used in France
|
'paid_to_date' => 'Versé à ce jour',
|
||||||
'balance_due' => 'Montant total',//can be "Montant à verser" or "Somme totale"
|
'balance_due' => 'Montant total',
|
||||||
'invoice_design_id' => 'Design', //if you speak about invoice's design -> "Modèle"
|
'invoice_design_id' => 'Design',
|
||||||
'terms' => 'Conditions',
|
'terms' => 'Conditions',
|
||||||
'your_invoice' => 'Votre Facture',
|
'your_invoice' => 'Votre facture',
|
||||||
|
|
||||||
'remove_contact' => 'Supprimer un contact',
|
'remove_contact' => 'Supprimer un contact',
|
||||||
'add_contact' => 'Ajouter un contact',
|
'add_contact' => 'Ajouter un contact',
|
||||||
@ -211,8 +211,8 @@ return array(
|
|||||||
|
|
||||||
// application messages
|
// application messages
|
||||||
'created_client' => 'Client créé avec succès',
|
'created_client' => 'Client créé avec succès',
|
||||||
'created_clients' => ':count clients créés avec csuccès',
|
'created_clients' => ':count clients créés avec succès',
|
||||||
'updated_settings' => 'paramètres mis à jour avec succès',
|
'updated_settings' => 'Paramètres mis à jour avec succès',
|
||||||
'removed_logo' => 'Logo supprimé avec succès',
|
'removed_logo' => 'Logo supprimé avec succès',
|
||||||
'sent_message' => 'Message envoyé avec succès',
|
'sent_message' => 'Message envoyé avec succès',
|
||||||
'invoice_error' => 'Veuillez vous assurer de sélectionner un client et de corriger les erreurs',
|
'invoice_error' => 'Veuillez vous assurer de sélectionner un client et de corriger les erreurs',
|
||||||
@ -293,7 +293,7 @@ return array(
|
|||||||
|
|
||||||
// Pro Plan
|
// Pro Plan
|
||||||
'pro_plan' => [
|
'pro_plan' => [
|
||||||
'remove_logo' => ':link pour supprimer le logo Invoice Ninja en souscrivant au plan Pro',
|
'remove_logo' => ':link pour supprimer le logo Invoice Ninja en souscrivant au Plan Pro',
|
||||||
'remove_logo_link' => 'Cliquez ici',
|
'remove_logo_link' => 'Cliquez ici',
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -456,10 +456,10 @@ return array(
|
|||||||
'sent' => 'envoyé',
|
'sent' => 'envoyé',
|
||||||
'timesheets' => 'Feuilles de temps',
|
'timesheets' => 'Feuilles de temps',
|
||||||
|
|
||||||
'payment_title' => 'Enter Your Billing Address and Credit Card information',
|
'payment_title' => 'Entrez votre adresse de facturation et vos informations bancaires',
|
||||||
'payment_cvv' => '*This is the 3-4 digit number onthe back of your card',
|
'payment_cvv' => '*Numéro à 3 ou 4 chiffres au dos de votre carte',
|
||||||
'payment_footer1' => '*Billing address must match address associated with credit card.',
|
'payment_footer1' => '*L\'adresse de facturation doit correspondre à celle enregistrée avec votre carte bancaire',
|
||||||
'payment_footer2' => '*Please click "PAY NOW" only once - transaction may take up to 1 minute to process.',
|
'payment_footer2' => '*Merci de cliquer sur "Payer maintenant" une seule fois. Le processus peut prendre jusqu\'à 1 minute.',
|
||||||
'vat_number' => 'Numéro de TVA',
|
'vat_number' => 'Numéro de TVA',
|
||||||
|
|
||||||
'id_number' => 'Numéro ID',
|
'id_number' => 'Numéro ID',
|
||||||
@ -492,18 +492,18 @@ return array(
|
|||||||
'select_versiony' => 'Choix de la verison',
|
'select_versiony' => 'Choix de la verison',
|
||||||
'view_history' => 'Consulter l\'historique',
|
'view_history' => 'Consulter l\'historique',
|
||||||
|
|
||||||
'edit_payment' => 'Edit Payment',
|
'edit_payment' => 'Editer le paiement',
|
||||||
'updated_payment' => 'Successfully updated payment',
|
'updated_payment' => 'Paiement édité avec succès',
|
||||||
'deleted' => 'Deleted',
|
'deleted' => 'Supprimé',
|
||||||
'restore_user' => 'Restore User',
|
'restore_user' => 'Restaurer l\'utilisateur',
|
||||||
'restored_user' => 'Successfully restored user',
|
'restored_user' => 'Restaurer la commande',
|
||||||
'show_deleted_users' => 'Show deleted users',
|
'show_deleted_users' => 'Voir les utilisateurs supprimés',
|
||||||
'email_templates' => 'Email Templates',
|
'email_templates' => 'Templates de mail',
|
||||||
'invoice_email' => 'Invoice Email',
|
'invoice_email' => 'Templates de facture',
|
||||||
'payment_email' => 'Payment Email',
|
'payment_email' => 'Email de paiement',
|
||||||
'quote_email' => 'Quote Email',
|
'quote_email' => 'Email de déclaration',
|
||||||
'reset_all' => 'Reset All',
|
'reset_all' => 'Réinitialiser',
|
||||||
'approve' => 'Approve',
|
'approve' => 'Accepter',
|
||||||
|
|
||||||
'token_billing_type_id' => 'Token Billing',
|
'token_billing_type_id' => 'Token Billing',
|
||||||
'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.',
|
'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.',
|
||||||
@ -519,18 +519,18 @@ return array(
|
|||||||
'token_billing_secure' => 'The data is stored securely by :stripe_link',
|
'token_billing_secure' => 'The data is stored securely by :stripe_link',
|
||||||
|
|
||||||
'support' => 'Support',
|
'support' => 'Support',
|
||||||
'contact_information' => 'Contact information',
|
'contact_information' => 'Information de contact',
|
||||||
'256_encryption' => '256-Bit Encryption',
|
'256_encryption' => '256-Bit Encryption',
|
||||||
'amount_due' => 'Amount due',
|
'amount_due' => 'Montant dû',
|
||||||
'billing_address' => 'Billing address',
|
'billing_address' => 'Billing address',
|
||||||
'billing_method' => 'Billing method',
|
'billing_method' => 'Billing method',
|
||||||
'order_overview' => 'Order overview',
|
'order_overview' => 'Order overview',
|
||||||
'match_address' => '*Address must match address associated with credit card.',
|
'match_address' => '*Address must match address associated with credit card.',
|
||||||
'click_once' => '*Please click "PAY NOW" only once - transaction may take up to 1 minute to process.',
|
'click_once' => '*Please click "PAY NOW" only once - transaction may take up to 1 minute to process.',
|
||||||
|
|
||||||
'default_invoice_footer' => 'Set default invoice footer',
|
'default_invoice_footer' => 'Définir par défaut',
|
||||||
'invoice_footer' => 'Invoice footer',
|
'invoice_footer' => 'Pied de facture',
|
||||||
'save_as_default_footer' => 'Save as default footer',
|
'save_as_default_footer' => 'Définir comme pied de facture par défatu',
|
||||||
|
|
||||||
'token_management' => 'Token Management',
|
'token_management' => 'Token Management',
|
||||||
'tokens' => 'Tokens',
|
'tokens' => 'Tokens',
|
||||||
@ -543,12 +543,12 @@ return array(
|
|||||||
'delete_token' => 'Delete Token',
|
'delete_token' => 'Delete Token',
|
||||||
'token' => 'Token',
|
'token' => 'Token',
|
||||||
|
|
||||||
'add_gateway' => 'Add Gateway',
|
'add_gateway' => 'Ajouter passerelle',
|
||||||
'delete_gateway' => 'Delete Gateway',
|
'delete_gateway' => 'Supprimer passerelle',
|
||||||
'edit_gateway' => 'Edit Gateway',
|
'edit_gateway' => 'Editer passerelle',
|
||||||
'updated_gateway' => 'Successfully updated gateway',
|
'updated_gateway' => 'Passerelle mise à jour avec succès',
|
||||||
'created_gateway' => 'Successfully created gateway',
|
'created_gateway' => 'Passerelle crée avec succès',
|
||||||
'deleted_gateway' => 'Successfully deleted gateway',
|
'deleted_gateway' => 'Passerelle supprimée avec succès',
|
||||||
'pay_with_paypal' => 'PayPal',
|
'pay_with_paypal' => 'PayPal',
|
||||||
'pay_with_card' => 'Carte bancaire',
|
'pay_with_card' => 'Carte bancaire',
|
||||||
|
|
||||||
@ -579,44 +579,44 @@ return array(
|
|||||||
'confirmation_resent' => 'The confirmation email was resent',
|
'confirmation_resent' => 'The confirmation email was resent',
|
||||||
|
|
||||||
'gateway_help_42' => ':link to sign up for BitPay.<br/>Note: use a Legacy API Key, not an API token.',
|
'gateway_help_42' => ':link to sign up for BitPay.<br/>Note: use a Legacy API Key, not an API token.',
|
||||||
'payment_type_credit_card' => 'Credit card',
|
'payment_type_credit_card' => 'Carte de crédit',
|
||||||
'payment_type_paypal' => 'PayPal',
|
'payment_type_paypal' => 'PayPal',
|
||||||
'payment_type_bitcoin' => 'Bitcoin',
|
'payment_type_bitcoin' => 'Bitcoin',
|
||||||
'knowledge_base' => 'Knowledge Base',
|
'knowledge_base' => 'Base de connaissances',
|
||||||
'partial' => 'Partial',
|
'partial' => 'Partiel',
|
||||||
'partial_remaining' => ':partial of :balance',
|
'partial_remaining' => ':partial de :balance',
|
||||||
|
|
||||||
'more_fields' => 'More Fields',
|
'more_fields' => 'Plus de champs',
|
||||||
'less_fields' => 'Less Fields',
|
'less_fields' => 'Moins de champs',
|
||||||
'client_name' => 'Client Name',
|
'client_name' => 'Nom du client',
|
||||||
'pdf_settings' => 'PDF Settings',
|
'pdf_settings' => 'Réglages PDF',
|
||||||
'utf8_invoices' => 'Cyrillic Support <sup>Beta</sup>',
|
'utf8_invoices' => 'Cyrillic Support <sup>Beta</sup>',
|
||||||
'product_settings' => 'Product Settings',
|
'product_settings' => 'Réglages du produit',
|
||||||
'auto_wrap' => 'Auto Line Wrap',
|
'auto_wrap' => 'Auto Line Wrap',
|
||||||
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',
|
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',
|
||||||
'view_documentation' => 'View Documentation',
|
'view_documentation' => 'Voir documentation',
|
||||||
'app_title' => 'Free Open-Source Online Invoicing',
|
'app_title' => 'Free Open-Source Online Invoicing',
|
||||||
'app_description' => 'Invoice Ninja is a free, open-source solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
|
'app_description' => 'Invoice Ninja is a free, open-source solution for invoicing and billing customers. With Invoice Ninja, you can easily build and send beautiful invoices from any device that has access to the web. Your clients can print your invoices, download them as pdf files, and even pay you online from within the system.',
|
||||||
|
|
||||||
'rows' => 'rows',
|
'rows' => 'lignes',
|
||||||
'www' => 'www',
|
'www' => 'www',
|
||||||
'logo' => 'Logo',
|
'logo' => 'Logo',
|
||||||
'subdomain' => 'Subdomain',
|
'subdomain' => 'Sous domaine',
|
||||||
'provide_name_or_email' => 'Please provide a contact name or email',
|
'provide_name_or_email' => 'Merci d\'indiquer un nom ou une adresse email',
|
||||||
'charts_and_reports' => 'Charts & Reports',
|
'charts_and_reports' => 'Charts & Reports',
|
||||||
'chart' => 'Chart',
|
'chart' => 'Chart',
|
||||||
'report' => 'Report',
|
'report' => 'Report',
|
||||||
'group_by' => 'Group by',
|
'group_by' => 'Grouper par',
|
||||||
'paid' => 'Paid',
|
'paid' => 'Payé',
|
||||||
'enable_report' => 'Report',
|
'enable_report' => 'Report',
|
||||||
'enable_chart' => 'Chart',
|
'enable_chart' => 'Chart',
|
||||||
'totals' => 'Totals',
|
'totals' => 'Totals',
|
||||||
'run' => 'Run',
|
'run' => 'Run',
|
||||||
'export' => 'Export',
|
'export' => 'Exporter',
|
||||||
'documentation' => 'Documentation',
|
'documentation' => 'Documentation',
|
||||||
'zapier' => 'Zapier <sup>Beta</sup>',
|
'zapier' => 'Zapier <sup>Beta</sup>',
|
||||||
'recurring' => 'Recurring',
|
'recurring' => 'Récurrent',
|
||||||
'last_invoice_sent' => 'Last invoice sent :date',
|
'last_invoice_sent' => 'Dernière facture envoyée le :date',
|
||||||
|
|
||||||
'processed_updates' => 'Mise à jour effectuée avec succès',
|
'processed_updates' => 'Mise à jour effectuée avec succès',
|
||||||
'tasks' => 'Tâches',
|
'tasks' => 'Tâches',
|
||||||
@ -641,7 +641,7 @@ return array(
|
|||||||
'minute' => 'minute',
|
'minute' => 'minute',
|
||||||
'minutes' => 'minutes',
|
'minutes' => 'minutes',
|
||||||
'hour' => 'heure',
|
'hour' => 'heure',
|
||||||
'hours' => 'houres',
|
'hours' => 'heures',
|
||||||
'task_details' => 'Détails tâche',
|
'task_details' => 'Détails tâche',
|
||||||
'duration' => 'Durée',
|
'duration' => 'Durée',
|
||||||
'end_time' => 'Heure de fin',
|
'end_time' => 'Heure de fin',
|
||||||
@ -655,8 +655,8 @@ return array(
|
|||||||
'restored_task' => 'Tâche restaurée avec succès',
|
'restored_task' => 'Tâche restaurée avec succès',
|
||||||
'archived_task' => 'Tâche archivée avec succès',
|
'archived_task' => 'Tâche archivée avec succès',
|
||||||
'archived_tasks' => ':count tâches archivées avec succès',
|
'archived_tasks' => ':count tâches archivées avec succès',
|
||||||
'deleted_task' => 'Tâche supprimée avec succès,'
|
'deleted_task' => 'Tâche supprimée avec succès',
|
||||||
'deleted_tasks' => ':count tâches supprimées avec syccès',
|
'deleted_tasks' => ':count tâches supprimées avec succès',
|
||||||
'create_task' => 'Créer tâche',
|
'create_task' => 'Créer tâche',
|
||||||
'stopped_task' => 'Tâche stoppée avec succès',
|
'stopped_task' => 'Tâche stoppée avec succès',
|
||||||
'invoice_task' => 'Tâche facturation',
|
'invoice_task' => 'Tâche facturation',
|
||||||
@ -682,20 +682,20 @@ return array(
|
|||||||
|
|
||||||
'resume' => 'Resume',
|
'resume' => 'Resume',
|
||||||
'break_duration' => 'Break',
|
'break_duration' => 'Break',
|
||||||
'edit_details' => 'Edit Details',
|
'edit_details' => 'Editer détails',
|
||||||
'work' => 'Work',
|
'work' => 'Travail',
|
||||||
'timezone_unset' => 'Please :link to set your timezone',
|
'timezone_unset' => 'Please :link to set your timezone',
|
||||||
'click_here' => 'click here',
|
'click_here' => 'cliquer ici',
|
||||||
|
|
||||||
'email_receipt' => 'Email payment receipt to the client',
|
'email_receipt' => 'Email payment receipt to the client',
|
||||||
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
|
'created_payment_emailed_client' => 'Paiement crée avec succès et envoyé au client',
|
||||||
'add_account' => 'Add Account',
|
'add_account' => 'Ajouter compte',
|
||||||
'untitled' => 'Untitled',
|
'untitled' => 'Sans titre',
|
||||||
'new_account' => 'New Account',
|
'new_account' => 'Nouveau compte',
|
||||||
'associated_accounts' => 'Successfully linked accounts',
|
'associated_accounts' => 'Successfully linked accounts',
|
||||||
'unlinked_account' => 'Successfully unlinked accounts',
|
'unlinked_account' => 'Successfully unlinked accounts',
|
||||||
'login' => 'Login',
|
'login' => 'Connexion',
|
||||||
'or' => 'or',
|
'or' => 'ou',
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -79,11 +79,11 @@
|
|||||||
{!! Former::hidden('remember')->raw() !!}
|
{!! Former::hidden('remember')->raw() !!}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>{!! Button::success(trans(Utils::allowNewAccounts() ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}</p>
|
<p>{!! Button::success(trans(Input::get('new_account') && Utils::allowNewAccounts() ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}</p>
|
||||||
|
|
||||||
@if (Utils::allowNewAccounts())
|
@if (Input::get('new_account') && Utils::allowNewAccounts())
|
||||||
<center><p>- {{ trans('texts.or') }} -</p></center>
|
<center><p>- {{ trans('texts.or') }} -</p></center>
|
||||||
<p>{!! Button::primary(trans('texts.new_account'))->asLinkTo(URL::to('/invoice_now?logout=true'))->large()->submit()->block() !!}</p>
|
<p>{!! Button::primary(trans('texts.new_account'))->asLinkTo(URL::to('/invoice_now?new_account=true'))->large()->submit()->block() !!}</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
@ -110,12 +110,9 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (Session::has('error'))
|
@if (Session::has('error'))
|
||||||
<div class="alert alert-danger">{{ Session::get('error') }}</div>
|
<div class="alert alert-danger"><li>{{ Session::get('error') }}</li></div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!! Former::close() !!}
|
{!! Former::close() !!}
|
||||||
|
@ -8,7 +8,11 @@
|
|||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
{!! Former::open($url)->addClass('col-md-12 warn-on-exit')->method($method) !!}
|
{!! Former::open($url)
|
||||||
|
->rules(
|
||||||
|
['email' => 'email']
|
||||||
|
)->addClass('col-md-12 warn-on-exit')
|
||||||
|
->method($method) !!}
|
||||||
|
|
||||||
@if ($client)
|
@if ($client)
|
||||||
{!! Former::populate($client) !!}
|
{!! Former::populate($client) !!}
|
||||||
@ -100,7 +104,8 @@
|
|||||||
{!! Former::select('currency_id')->addOption('','')
|
{!! Former::select('currency_id')->addOption('','')
|
||||||
->fromQuery($currencies, 'name', 'id') !!}
|
->fromQuery($currencies, 'name', 'id') !!}
|
||||||
{!! Former::select('payment_terms')->addOption('','')
|
{!! Former::select('payment_terms')->addOption('','')
|
||||||
->fromQuery($paymentTerms, 'name', 'num_days') !!}
|
->fromQuery($paymentTerms, 'name', 'num_days')
|
||||||
|
->help(trans('texts.payment_terms_help')) !!}
|
||||||
{!! Former::select('size_id')->addOption('','')
|
{!! Former::select('size_id')->addOption('','')
|
||||||
->fromQuery($sizes, 'name', 'id') !!}
|
->fromQuery($sizes, 'name', 'id') !!}
|
||||||
{!! Former::select('industry_id')->addOption('','')
|
{!! Former::select('industry_id')->addOption('','')
|
||||||
|
@ -112,7 +112,7 @@
|
|||||||
<i class="fa fa-envelope" style="width: 20px"></i>{!! HTML::mailto($contact->email, $contact->email) !!}<br/>
|
<i class="fa fa-envelope" style="width: 20px"></i>{!! HTML::mailto($contact->email, $contact->email) !!}<br/>
|
||||||
@endif
|
@endif
|
||||||
@if ($contact->phone)
|
@if ($contact->phone)
|
||||||
<i class="fa fa-phone" style="width: 20px"></i>{!! Utils::formatPhoneNumber($contact->phone) !!}
|
<i class="fa fa-phone" style="width: 20px"></i>{!! Utils::formatPhoneNumber($contact->phone) !!}<br/>
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
@ -186,13 +186,19 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function unlinkAccount(userAccountId, userId) {
|
function showUnlink(userAccountId, userId) {
|
||||||
if (confirm('{!! trans("texts.are_you_sure") !!}')) {
|
NINJA.unlink = {
|
||||||
window.location = '{{ URL::to('/unlink_account') }}' + '/' + userAccountId + '/' + userId;
|
'userAccountId': userAccountId,
|
||||||
}
|
'userId': userId
|
||||||
|
};
|
||||||
|
$('#unlinkModal').modal('show');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function unlinkAccount() {
|
||||||
|
window.location = '{{ URL::to('/unlink_account') }}' + '/' + NINJA.unlink.userAccountId + '/' + NINJA.unlink.userId;
|
||||||
|
}
|
||||||
|
|
||||||
function wordWrapText(value, width)
|
function wordWrapText(value, width)
|
||||||
{
|
{
|
||||||
@if (Auth::user()->account->auto_wrap)
|
@if (Auth::user()->account->auto_wrap)
|
||||||
@ -242,7 +248,14 @@
|
|||||||
$(".alert-hide").fadeOut(500);
|
$(".alert-hide").fadeOut(500);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
|
$('#search').blur(function(){
|
||||||
|
$('#search').css('width', '150px');
|
||||||
|
$('ul.navbar-right').show();
|
||||||
|
});
|
||||||
|
|
||||||
$('#search').focus(function(){
|
$('#search').focus(function(){
|
||||||
|
$('#search').css('width', '256px');
|
||||||
|
$('ul.navbar-right').hide();
|
||||||
if (!window.hasOwnProperty('searchData')) {
|
if (!window.hasOwnProperty('searchData')) {
|
||||||
$.get('{{ URL::route('getSearchData') }}', function(data) {
|
$.get('{{ URL::route('getSearchData') }}', function(data) {
|
||||||
window.searchData = true;
|
window.searchData = true;
|
||||||
@ -316,7 +329,7 @@
|
|||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a href="{{ URL::to(NINJA_WEB_URL) }}" class='navbar-brand'>
|
<a href="{{ URL::to(NINJA_WEB_URL) }}" class='navbar-brand' target="_blank">
|
||||||
<img src="{{ asset('images/invoiceninja-logo.png') }}" style="height:18px;width:auto"/>
|
<img src="{{ asset('images/invoiceninja-logo.png') }}" style="height:18px;width:auto"/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -353,29 +366,42 @@
|
|||||||
<ul class="dropdown-menu user-accounts" role="menu">
|
<ul class="dropdown-menu user-accounts" role="menu">
|
||||||
@if (session(SESSION_USER_ACCOUNTS))
|
@if (session(SESSION_USER_ACCOUNTS))
|
||||||
@foreach (session(SESSION_USER_ACCOUNTS) as $item)
|
@foreach (session(SESSION_USER_ACCOUNTS) as $item)
|
||||||
<li><a href='{{ URL::to("/switch_account/{$item->user_id}") }}'>
|
|
||||||
@if ($item->user_id == Auth::user()->id)
|
@if ($item->user_id == Auth::user()->id)
|
||||||
<b>
|
@include('user_account', [
|
||||||
|
'user_account_id' => $item->id,
|
||||||
|
'user_id' => $item->user_id,
|
||||||
|
'account_name' => $item->account_name,
|
||||||
|
'user_name' => $item->user_name,
|
||||||
|
'account_key' => $item->account_key,
|
||||||
|
'selected' => true,
|
||||||
|
'show_remove' => count(session(SESSION_USER_ACCOUNTS)) > 1,
|
||||||
|
])
|
||||||
@endif
|
@endif
|
||||||
@if (count(session(SESSION_USER_ACCOUNTS)) > 1)
|
@endforeach
|
||||||
<div class="pull-right glyphicon glyphicon-remove remove" onclick="return unlinkAccount({{ $item->id }}, {{ $item->user_id }})"></div>
|
@foreach (session(SESSION_USER_ACCOUNTS) as $item)
|
||||||
|
@if ($item->user_id != Auth::user()->id)
|
||||||
|
@include('user_account', [
|
||||||
|
'user_account_id' => $item->id,
|
||||||
|
'user_id' => $item->user_id,
|
||||||
|
'account_name' => $item->account_name,
|
||||||
|
'user_name' => $item->user_name,
|
||||||
|
'account_key' => $item->account_key,
|
||||||
|
'selected' => false,
|
||||||
|
'show_remove' => count(session(SESSION_USER_ACCOUNTS)) > 1,
|
||||||
|
])
|
||||||
@endif
|
@endif
|
||||||
<div class="account" style="padding-right:28px">{{ $item->account_name }}</div>
|
|
||||||
<div class="user">{{ $item->user_name }}</div>
|
|
||||||
@if ($item->user_id == Auth::user()->id)
|
|
||||||
</b>
|
|
||||||
@endif
|
|
||||||
</a></li>
|
|
||||||
@endforeach
|
@endforeach
|
||||||
@else
|
@else
|
||||||
<li><a href='#'><b>
|
@include('user_account', [
|
||||||
<div class="account">{{ Auth::user()->account->name ?: trans('texts.untitled') }}</div>
|
'account_name' => Auth::user()->account->name ?: trans('texts.untitled'),
|
||||||
<div class="user">{{ Auth::user()->getDisplayName() }}</div>
|
'user_name' => Auth::user()->getDisplayName(),
|
||||||
</b></a></li>
|
'account_key' => Auth::user()->account->account_key,
|
||||||
|
'selected' => true,
|
||||||
|
])
|
||||||
@endif
|
@endif
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
@if (Auth::user()->isPro() && (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5))
|
@if (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5)
|
||||||
<li>{!! link_to('/login', trans('texts.add_account')) !!}</li>
|
<li>{!! link_to('/login?new_account=true', trans('texts.add_account')) !!}</li>
|
||||||
@endif
|
@endif
|
||||||
<li>{!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}</li>
|
<li>{!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -419,7 +445,7 @@
|
|||||||
|
|
||||||
<form class="navbar-form navbar-right" role="search">
|
<form class="navbar-form navbar-right" role="search">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" id="search" style="width: {{ Session::get(SESSION_LOCALE) == 'en' ? 180 : 140 }}px"
|
<input type="text" id="search" style="width: 150px"
|
||||||
class="form-control" placeholder="{{ trans('texts.search') }}">
|
class="form-control" placeholder="{{ trans('texts.search') }}">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -454,7 +480,7 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (Session::has('error'))
|
@if (Session::has('error'))
|
||||||
<div class="alert alert-danger">{{ Session::get('error') }}</div>
|
<div class="alert alert-danger">{!! Session::get('error') !!}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@if (!isset($showBreadcrumbs) || $showBreadcrumbs)
|
@if (!isset($showBreadcrumbs) || $showBreadcrumbs)
|
||||||
@ -549,6 +575,28 @@
|
|||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@if (Auth::check() && session(SESSION_USER_ACCOUNTS) && count(session(SESSION_USER_ACCOUNTS)))
|
||||||
|
<div class="modal fade" id="unlinkModal" tabindex="-1" role="dialog" aria-labelledby="unlinkModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title" id="myModalLabel">{{ trans('texts.unlink_account') }}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h3>{{ trans('texts.are_you_sure') }}</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer" id="signUpFooter">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('texts.cancel') }}</button>
|
||||||
|
<button type="button" class="btn btn-primary" onclick="unlinkAccount()">{{ trans('texts.unlink') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
@if (Auth::check() && !Auth::user()->isPro())
|
@if (Auth::check() && !Auth::user()->isPro())
|
||||||
<div class="modal fade" id="proPlanModal" tabindex="-1" role="dialog" aria-labelledby="proPlanModalLabel" aria-hidden="true">
|
<div class="modal fade" id="proPlanModal" tabindex="-1" role="dialog" aria-labelledby="proPlanModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog large-dialog">
|
<div class="modal-dialog large-dialog">
|
||||||
@ -588,7 +636,7 @@
|
|||||||
|
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
{{-- Per our license, please do not remove or modify this link. --}}
|
{{-- Per our license, please do not remove or modify this section. --}}
|
||||||
@if (!Utils::isNinja())
|
@if (!Utils::isNinja())
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a> |
|
{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a> |
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
@if ($invoice && $invoice->recurring_invoice_id)
|
@if ($invoice && $invoice->recurring_invoice_id)
|
||||||
<div class="pull-right" style="padding-top: 6px">
|
<div class="pull-right" style="padding-top: 6px">
|
||||||
Created by a {!! link_to('/invoices/'.$invoice->recurring_invoice_id, 'recurring invoice') !!}
|
{!! trans('texts.created_by_recurring', ['invoice' => link_to('/invoices/'.$invoice->recurring_invoice->public_id, $invoice->recurring_invoice->invoice_number)]) !!}
|
||||||
</div>
|
</div>
|
||||||
@else
|
@else
|
||||||
<div data-bind="visible: invoice_status_id() === 0">
|
<div data-bind="visible: invoice_status_id() === 0">
|
||||||
@ -438,7 +438,8 @@
|
|||||||
|
|
||||||
<span data-bind="visible: $root.showMore">
|
<span data-bind="visible: $root.showMore">
|
||||||
{!! Former::select('payment_terms')->addOption('','')->data_bind('value: payment_terms')
|
{!! Former::select('payment_terms')->addOption('','')->data_bind('value: payment_terms')
|
||||||
->fromQuery($paymentTerms, 'name', 'num_days') !!}
|
->fromQuery($paymentTerms, 'name', 'num_days')
|
||||||
|
->help(trans('texts.payment_terms_help')) !!}
|
||||||
{!! Former::select('size_id')->addOption('','')->data_bind('value: size_id')
|
{!! Former::select('size_id')->addOption('','')->data_bind('value: size_id')
|
||||||
->fromQuery($sizes, 'name', 'id') !!}
|
->fromQuery($sizes, 'name', 'id') !!}
|
||||||
{!! Former::select('industry_id')->addOption('','')->data_bind('value: industry_id')
|
{!! Former::select('industry_id')->addOption('','')->data_bind('value: industry_id')
|
||||||
@ -738,14 +739,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onEmailClick() {
|
function onEmailClick() {
|
||||||
if (confirm('{!! trans("texts.confirm_email_$entityType") !!}')) {
|
if (!NINJA.isRegistered) {
|
||||||
|
alert("{{ trans('texts.registration_required') }}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirm('{!! trans("texts.confirm_email_$entityType") !!}' + '\n\n' + getSendToEmails())) {
|
||||||
preparePdfData('email');
|
preparePdfData('email');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSaveClick() {
|
function onSaveClick() {
|
||||||
if (model.invoice().is_recurring()) {
|
if (model.invoice().is_recurring()) {
|
||||||
if (confirm('{!! trans("texts.confirm_recurring_email_$entityType") !!}')) {
|
if (!NINJA.isRegistered) {
|
||||||
|
alert("{{ trans('texts.registration_required') }}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (confirm('{!! trans("texts.confirm_recurring_email_$entityType") !!}' + '\n\n' + getSendToEmails() + '\n' + '{!! trans("texts.confirm_recurring_timing") !!}')) {
|
||||||
submitAction('');
|
submitAction('');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -753,6 +764,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSendToEmails() {
|
||||||
|
var client = model.invoice().client();
|
||||||
|
var parts = [];
|
||||||
|
|
||||||
|
for (var i=0; i<client.contacts().length; i++) {
|
||||||
|
var contact = client.contacts()[i];
|
||||||
|
if (contact.send_invoice()) {
|
||||||
|
parts.push(contact.displayName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
function preparePdfData(action) {
|
function preparePdfData(action) {
|
||||||
var invoice = createInvoiceModel();
|
var invoice = createInvoiceModel();
|
||||||
var design = getDesignJavascript();
|
var design = getDesignJavascript();
|
||||||
@ -1430,6 +1455,22 @@
|
|||||||
self.send_invoice = ko.observable(false);
|
self.send_invoice = ko.observable(false);
|
||||||
self.invitation_link = ko.observable('');
|
self.invitation_link = ko.observable('');
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
ko.mapping.fromJS(data, {}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.displayName = ko.computed(function() {
|
||||||
|
var str = '';
|
||||||
|
if (self.first_name() || self.last_name()) {
|
||||||
|
str += self.first_name() + ' ' + self.last_name() + '\n';
|
||||||
|
}
|
||||||
|
if (self.email()) {
|
||||||
|
str += self.email() + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
});
|
||||||
|
|
||||||
self.email.display = ko.computed(function() {
|
self.email.display = ko.computed(function() {
|
||||||
var str = '';
|
var str = '';
|
||||||
if (self.first_name() || self.last_name()) {
|
if (self.first_name() || self.last_name()) {
|
||||||
@ -1447,10 +1488,6 @@
|
|||||||
|
|
||||||
return str;
|
return str;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data) {
|
|
||||||
ko.mapping.fromJS(data, {}, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function TaxRateModel(data) {
|
function TaxRateModel(data) {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<iframe id="theFrame" style="display:none" frameborder="1" width="100%" height="{{ isset($pdfHeight) ? $pdfHeight : 1180 }}px"></iframe>
|
<iframe id="theFrame" style="display:none" frameborder="1" width="100%" height="{{ isset($pdfHeight) ? $pdfHeight : 1180 }}px"></iframe>
|
||||||
<canvas id="theCanvas" style="display:none;width:100%;border:solid 1px #CCCCCC;"></canvas>
|
<canvas id="theCanvas" style="display:none;width:100%;border:solid 1px #CCCCCC;"></canvas>
|
||||||
|
|
||||||
|
@if (!Utils::isNinja() || !Utils::isPro())
|
||||||
<div class="modal fade" id="moreDesignsModal" tabindex="-1" role="dialog" aria-labelledby="moreDesignsModalLabel" aria-hidden="true">
|
<div class="modal fade" id="moreDesignsModal" tabindex="-1" role="dialog" aria-labelledby="moreDesignsModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
@ -43,7 +44,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
@if (count($paymentTypes) > 1)
|
@if (count($paymentTypes) > 1)
|
||||||
{!! DropdownButton::success(trans('texts.pay_now'))->withContents($paymentTypes)->large() !!}
|
{!! DropdownButton::success(trans('texts.pay_now'))->withContents($paymentTypes)->large() !!}
|
||||||
@else
|
@else
|
||||||
{!! Button::success(trans('texts.pay_now'))->asLinkTo(URL::to('/payment/' . $invitation->invitation_key))->large() !!}
|
{!! Button::success(trans('texts.pay_now'))->asLinkTo(URL::to($paymentURL))->large() !!}
|
||||||
@endif
|
@endif
|
||||||
@else
|
@else
|
||||||
{!! Button::normal('Download PDF')->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}
|
{!! Button::normal('Download PDF')->withAttributes(['onclick' => 'onDownloadClick()'])->large() !!}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="{{App::getLocale()}}">
|
<html lang="{{App::getLocale()}}">
|
||||||
<head>
|
<head>
|
||||||
<title>Invoice Ninja | {{ isset($title) ? $title : ' ' . trans('texts.app_title') }}</title>
|
<title>{{ isset($title) ? ($title . ' | Invoice Ninja') : ('Invoice Ninja | ' . trans('texts.app_title')) }} | </title>
|
||||||
<meta name="description" content="{{ isset($description) ? $description : trans('texts.app_description') }}" />
|
<meta name="description" content="{{ isset($description) ? $description : trans('texts.app_description') }}" />
|
||||||
|
|
||||||
<!-- Source: https://github.com/hillelcoren/invoice-ninja -->
|
<!-- Source: https://github.com/hillelcoren/invoice-ninja -->
|
||||||
|
@ -181,7 +181,7 @@ table.table thead .sorting_desc_disabled:after { content: '' !important }
|
|||||||
</button>
|
</button>
|
||||||
@if (!isset($hideLogo) || !$hideLogo)
|
@if (!isset($hideLogo) || !$hideLogo)
|
||||||
{{-- Per our license, please do not remove or modify this link. --}}
|
{{-- Per our license, please do not remove or modify this link. --}}
|
||||||
<a class="navbar-brand" href="https://www.invoiceninja.com/"><img src="{{ asset('images/invoiceninja-logo.png') }}"></a>
|
<a class="navbar-brand" href="{{ URL::to(NINJA_WEB_URL) }}" target="_blank"><img src="{{ asset('images/invoiceninja-logo.png') }}"></a>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div id="navbar" class="collapse navbar-collapse">
|
<div id="navbar" class="collapse navbar-collapse">
|
||||||
|
@ -77,7 +77,11 @@ header h3 em {
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7">
|
<div class="col-md-7">
|
||||||
<header>
|
<header>
|
||||||
|
@if (isset($redirectTo))
|
||||||
|
<h2>Payment Complete</h2>
|
||||||
|
@else
|
||||||
<h2>License Key<br/><small>{{ $message }}</small></h2>
|
<h2>License Key<br/><small>{{ $message }}</small></h2>
|
||||||
|
@endif
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -87,9 +91,16 @@ header h3 em {
|
|||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<h2 style="text-align:center">{{ $license }}</h2>
|
<h2 style="text-align:center">
|
||||||
|
@if (isset($redirectTo))
|
||||||
|
{{ $message }}
|
||||||
|
@else
|
||||||
|
{{ $license }}
|
||||||
|
@endif
|
||||||
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -102,6 +113,13 @@ header h3 em {
|
|||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
trackEvent('/license', '/product_{{ $productId }}');
|
trackEvent('/license', '/product_{{ $productId }}');
|
||||||
|
|
||||||
|
@if (isset($redirectTo))
|
||||||
|
setTimeout(function() {
|
||||||
|
location.href = "{!! $redirectTo !!}";
|
||||||
|
}, 3000);
|
||||||
|
@endif
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -6,10 +6,11 @@
|
|||||||
<meta name="csrf-token" content="<?= csrf_token() ?>">
|
<meta name="csrf-token" content="<?= csrf_token() ?>">
|
||||||
<script src="{{ asset('js/built.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
|
<script src="{{ asset('js/built.js') }}?no_cache={{ NINJA_VERSION }}" type="text/javascript"></script>
|
||||||
<link href="{{ asset('css/built.public.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
|
<link href="{{ asset('css/built.public.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
<link href="{{ asset('css/built.css') }}?no_cache={{ NINJA_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
background-color: #f8f8f8;
|
background-color: #FEFEFE;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -35,7 +36,7 @@
|
|||||||
<pre>sudo chown yourname:www-data /path/to/ninja</pre>
|
<pre>sudo chown yourname:www-data /path/to/ninja</pre>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
If you need help you can either post to our <a href="https://groups.google.com/forum/#!forum/invoiceninja" target="_blank">Google Group</a>
|
If you need help you can either post to our <a href="https://www.invoiceninja.com/forums/forum/support/" target="_blank">support forum</a>
|
||||||
or email us at <a href="mailto:contact@invoiceninja.com" target="_blank">contact@invoiceninja.com</a>.
|
or email us at <a href="mailto:contact@invoiceninja.com" target="_blank">contact@invoiceninja.com</a>.
|
||||||
<p>
|
<p>
|
||||||
<pre>-- Commands to create a MySQL database and user
|
<pre>-- Commands to create a MySQL database and user
|
||||||
@ -64,7 +65,7 @@ FLUSH PRIVILEGES;</pre>
|
|||||||
<h3 class="panel-title">Application Settings</h3>
|
<h3 class="panel-title">Application Settings</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{!! Former::text('app[url]')->label('URL')->value(Request::root()) !!}
|
{!! Former::text('app[url]')->label('URL')->value(isset($_ENV['APP_URL']) ? $_ENV['APP_URL'] : Request::root()) !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -73,12 +74,17 @@ FLUSH PRIVILEGES;</pre>
|
|||||||
<h3 class="panel-title">Database Connection</h3>
|
<h3 class="panel-title">Database Connection</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{!! Former::select('database[default]')->label('Driver')->options(['mysql' => 'MySQL', 'pgsql' => 'PostgreSQL', 'sqlite' => 'SQLite']) !!}
|
{!! Former::select('database[default]')->label('Driver')->options(['mysql' => 'MySQL', 'pgsql' => 'PostgreSQL', 'sqlite' => 'SQLite'])
|
||||||
{!! Former::text('database[type][host]')->label('Host')->value('localhost') !!}
|
->value(isset($_ENV['DB_TYPE']) ? $_ENV['DB_TYPE'] : 'mysql') !!}
|
||||||
{!! Former::text('database[type][database]')->label('Database')->value('ninja') !!}
|
{!! Former::text('database[type][host]')->label('Host')->value('localhost')
|
||||||
{!! Former::text('database[type][username]')->label('Username')->value('ninja') !!}
|
->value(isset($_ENV['DB_HOST']) ? $_ENV['DB_HOST'] : '') !!}
|
||||||
{!! Former::password('database[type][password]')->label('Password')->value('ninja') !!}
|
{!! Former::text('database[type][database]')->label('Database')->value('ninja')
|
||||||
{!! Former::actions( Button::normal('Test connection')->withAttributes(['onclick' => 'testDatabase()']), ' <span id="dbTestResult"/>' ) !!}
|
->value(isset($_ENV['DB_DATABASE']) ? $_ENV['DB_DATABASE'] : '') !!}
|
||||||
|
{!! Former::text('database[type][username]')->label('Username')->value('ninja')
|
||||||
|
->value(isset($_ENV['DB_USERNAME']) ? $_ENV['DB_USERNAME'] : '') !!}
|
||||||
|
{!! Former::password('database[type][password]')->label('Password')->value('ninja')
|
||||||
|
->value(isset($_ENV['DB_PASSWORD']) ? $_ENV['DB_PASSWORD'] : '') !!}
|
||||||
|
{!! Former::actions( Button::primary('Test connection')->small()->withAttributes(['onclick' => 'testDatabase()']), ' <span id="dbTestResult"/>' ) !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -88,14 +94,21 @@ FLUSH PRIVILEGES;</pre>
|
|||||||
<h3 class="panel-title">Email Settings</h3>
|
<h3 class="panel-title">Email Settings</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
{!! Former::select('mail[driver]')->label('Driver')->options(['smtp' => 'SMTP', 'mail' => 'Mail', 'sendmail' => 'Sendmail']) !!}
|
{!! Former::select('mail[driver]')->label('Driver')->options(['smtp' => 'SMTP', 'mail' => 'Mail', 'sendmail' => 'Sendmail'])
|
||||||
{!! Former::text('mail[host]')->label('Host')->value('localhost') !!}
|
->value(isset($_ENV['MAIL_DRIVER']) ? $_ENV['MAIL_DRIVER'] : 'smtp') !!}
|
||||||
{!! Former::text('mail[port]')->label('Port')->value('587') !!}
|
{!! Former::text('mail[host]')->label('Host')
|
||||||
{!! Former::select('mail[encryption]')->label('Encryption')->options(['tls' => 'TLS', 'ssl' => 'SSL']) !!}
|
->value(isset($_ENV['MAIL_HOST']) ? $_ENV['MAIL_HOST'] : '') !!}
|
||||||
{!! Former::text('mail[from][name]')->label('From Name') !!}
|
{!! Former::text('mail[port]')->label('Port')
|
||||||
{!! Former::text('mail[username]')->label('Email') !!}
|
->value(isset($_ENV['MAIL_PORT']) ? $_ENV['MAIL_PORT'] : '587') !!}
|
||||||
{!! Former::password('mail[password]')->label('Password') !!}
|
{!! Former::select('mail[encryption]')->label('Encryption')->options(['tls' => 'TLS', 'ssl' => 'SSL'])
|
||||||
{!! Former::actions( Button::normal('Send test email')->withAttributes(['onclick' => 'testMail()']), ' <span id="mailTestResult"/>' ) !!}
|
->value(isset($_ENV['MAIL_ENCRYPTION']) ? $_ENV['MAIL_ENCRYPTION'] : 'tls') !!}
|
||||||
|
{!! Former::text('mail[from][name]')->label('From Name')
|
||||||
|
->value(isset($_ENV['MAIL_FROM_NAME']) ? $_ENV['MAIL_FROM_NAME'] : '') !!}
|
||||||
|
{!! Former::text('mail[username]')->label('Email')
|
||||||
|
->value(isset($_ENV['MAIL_USERNAME']) ? $_ENV['MAIL_USERNAME'] : '') !!}
|
||||||
|
{!! Former::password('mail[password]')->label('Password')
|
||||||
|
->value(isset($_ENV['MAIL_PASSWORD']) ? $_ENV['MAIL_PASSWORD'] : '') !!}
|
||||||
|
{!! Former::actions( Button::primary('Send test email')->small()->withAttributes(['onclick' => 'testMail()']), ' <span id="mailTestResult"/>' ) !!}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -112,8 +125,9 @@ FLUSH PRIVILEGES;</pre>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{!! Former::checkbox('terms_checkbox')->label(' ')->text(trans('texts.agree_to_terms', ['terms' => '<a href="'.NINJA_APP_URL.'/terms" target="_blank">'.trans('texts.terms_of_service').'</a>'])) !!}
|
{!! Former::checkbox('terms_checkbox')->label(' ')->text(trans('texts.agree_to_terms', ['terms' => '<a href="'.NINJA_APP_URL.'/terms" target="_blank">'.trans('texts.terms_of_service').'</a>'])) !!}
|
||||||
{!! Former::actions( Button::primary('Submit')->submit() ) !!}
|
{!! Former::actions( Button::primary('Submit')->large()->submit() ) !!}
|
||||||
{!! Former::close() !!}
|
{!! Former::close() !!}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
31
resources/views/user_account.blade.php
Normal file
31
resources/views/user_account.blade.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<li style="margin-top: 4px; margin-bottom: 4px; min-width: 220px; cursor: pointer">
|
||||||
|
@if (isset($user_id) && $show_remove)
|
||||||
|
<a href='{{ URL::to("/switch_account/{$user_id}") }}'>
|
||||||
|
@else
|
||||||
|
<a href='#' onclick="return false;">
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (isset($show_remove) && $show_remove)
|
||||||
|
<div class="pull-right glyphicon glyphicon-remove remove" onclick="return showUnlink({{ $user_account_id }}, {{ $user_id }})"></div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (file_exists('logo/'.$account_key.'.jpg'))
|
||||||
|
<img class="pull-left" style="width: 40px; min-height: 40px; margin-right: 16px" src="{{ asset('logo/'.$account_key.'.jpg') }}"/>
|
||||||
|
@else
|
||||||
|
<div class="pull-left" style="width: 40px; min-height: 40px; margin-right: 16px"> </div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (isset($selected) && $selected)
|
||||||
|
<b>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="account" style="padding-right:90px">{{ $account_name }}</div>
|
||||||
|
<div class="user" style="padding-right:90px">{{ $user_name }}</div>
|
||||||
|
|
||||||
|
@if (isset($selected) && $selected)
|
||||||
|
</b>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</li>
|
Loading…
x
Reference in New Issue
Block a user