1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-08 20:22:42 +01:00

Improved settings navigation

This commit is contained in:
Hillel Coren 2015-10-14 17:15:39 +03:00
parent d3550903f4
commit 831c81a4b9
59 changed files with 2312 additions and 1986 deletions

View File

@ -37,11 +37,11 @@ class SendRecurringInvoices extends Command
$this->info(count($invoices).' recurring invoice(s) found');
foreach ($invoices as $recurInvoice) {
$recurInvoice->account->loadLocalizationSettings($recurInvoice->client);
$this->info('Processing Invoice '.$recurInvoice->id.' - Should send '.($recurInvoice->shouldSendToday() ? 'YES' : 'NO'));
$invoice = $this->invoiceRepo->createRecurringInvoice($recurInvoice);
if ($invoice && !$invoice->isPaid()) {
$recurInvoice->account->loadLocalizationSettings($invoice->client);
$this->mailer->sendInvoice($invoice);
}
}

View File

@ -15,7 +15,6 @@ use Cache;
use Response;
use parseCSV;
use Request;
use App\Models\Affiliate;
use App\Models\License;
use App\Models\User;
@ -129,9 +128,9 @@ class AccountController extends BaseController
Session::put("show_trash:{$entityType}", $visible == 'true');
if ($entityType == 'user') {
return Redirect::to('company/'.ACCOUNT_ADVANCED_SETTINGS.'/'.ACCOUNT_USER_MANAGEMENT);
return Redirect::to('settings/'.ACCOUNT_USER_MANAGEMENT);
} elseif ($entityType == 'token') {
return Redirect::to('company/'.ACCOUNT_ADVANCED_SETTINGS.'/'.ACCOUNT_TOKEN_MANAGEMENT);
return Redirect::to('settings/'.ACCOUNT_API_TOKENS);
} else {
return Redirect::to("{$entityType}s");
}
@ -143,10 +142,53 @@ class AccountController extends BaseController
return Response::json($data);
}
public function showSection($section = ACCOUNT_DETAILS, $subSection = false)
public function showSection($section = false)
{
if ($section == ACCOUNT_DETAILS) {
if (!$section) {
return Redirect::to('/settings/' . ACCOUNT_COMPANY_DETAILS, 301);
}
if ($section == ACCOUNT_COMPANY_DETAILS) {
return self::showCompanyDetails();
} elseif ($section == ACCOUNT_USER_DETAILS) {
return self::showUserDetails();
} elseif ($section == ACCOUNT_LOCALIZATION) {
return self::showLocalization();
} elseif ($section == ACCOUNT_PAYMENTS) {
return self::showOnlinePayments();
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
return View::make('accounts.import_export', ['title' => trans('texts.import_export')]);
} elseif ($section == ACCOUNT_INVOICE_DESIGN || $section == ACCOUNT_CUSTOMIZE_DESIGN) {
return self::showInvoiceDesign($section);
} elseif ($section === ACCOUNT_TEMPLATES_AND_REMINDERS) {
return self::showTemplates();
} elseif ($section === ACCOUNT_PRODUCTS) {
return self::showProducts();
} else {
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'title' => trans("texts.{$section}"),
'section' => $section
];
return View::make("accounts.{$section}", $data);
}
}
private function showCompanyDetails()
{
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'countries' => Cache::get('countries'),
'sizes' => Cache::get('sizes'),
'industries' => Cache::get('industries'),
'title' => trans('texts.company_details'),
];
return View::make('accounts.details', $data);
}
private function showUserDetails()
{
$oauthLoginUrls = [];
foreach (AuthService::$providers as $provider) {
$oauthLoginUrls[] = ['label' => $provider, 'url' => '/auth/' . strtolower($provider)];
@ -154,23 +196,32 @@ class AccountController extends BaseController
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'countries' => Cache::get('countries'),
'sizes' => Cache::get('sizes'),
'industries' => Cache::get('industries'),
'timezones' => Cache::get('timezones'),
'dateFormats' => Cache::get('dateFormats'),
'datetimeFormats' => Cache::get('datetimeFormats'),
'currencies' => Cache::get('currencies'),
'languages' => Cache::get('languages'),
'title' => trans('texts.company_details'),
'title' => trans('texts.user_details'),
'user' => Auth::user(),
'oauthProviderName' => AuthService::getProviderName(Auth::user()->oauth_provider_id),
'oauthLoginUrls' => $oauthLoginUrls,
];
return View::make('accounts.details', $data);
} elseif ($section == ACCOUNT_PAYMENTS) {
return View::make('accounts.user_details', $data);
}
private function showLocalization()
{
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'timezones' => Cache::get('timezones'),
'dateFormats' => Cache::get('dateFormats'),
'datetimeFormats' => Cache::get('datetimeFormats'),
'currencies' => Cache::get('currencies'),
'languages' => Cache::get('languages'),
'title' => trans('texts.localization'),
];
return View::make('accounts.localization', $data);
}
private function showOnlinePayments()
{
$account = Auth::user()->account;
$account->load('account_gateways');
$count = count($account->account_gateways);
@ -183,25 +234,21 @@ class AccountController extends BaseController
'title' => trans('texts.online_payments')
]);
}
} elseif ($section == ACCOUNT_NOTIFICATIONS) {
}
private function showProducts()
{
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'title' => trans('texts.notifications'),
'account' => Auth::user()->account,
'title' => trans('texts.product_library'),
];
return View::make('accounts.notifications', $data);
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
return View::make('accounts.import_export', ['title' => trans('texts.import_export')]);
} elseif ($section == ACCOUNT_ADVANCED_SETTINGS) {
return View::make('accounts.products', $data);
}
private function showInvoiceDesign($section)
{
$account = Auth::user()->account->load('country');
$data = [
'account' => $account,
'feature' => $subSection,
'title' => trans('texts.invoice_settings'),
];
if ($subSection == ACCOUNT_INVOICE_DESIGN
|| $subSection == ACCOUNT_CUSTOMIZE_DESIGN) {
$invoice = new stdClass();
$client = new stdClass();
$contact = new stdClass();
@ -239,6 +286,7 @@ class AccountController extends BaseController
$data['invoiceLabels'] = json_decode($account->invoice_labels) ?: [];
$data['title'] = trans('texts.invoice_design');
$data['invoiceDesigns'] = InvoiceDesign::getDesigns();
$data['section'] = $section;
$design = false;
foreach ($data['invoiceDesigns'] as $item) {
@ -248,10 +296,16 @@ class AccountController extends BaseController
}
}
if ($subSection == ACCOUNT_CUSTOMIZE_DESIGN) {
if ($section == ACCOUNT_CUSTOMIZE_DESIGN) {
$data['customDesign'] = ($account->custom_design && !$design) ? $account->custom_design : $design;
}
} else if ($subSection == ACCOUNT_TEMPLATES_AND_REMINDERS) {
return View::make("accounts.{$section}", $data);
}
private function showTemplates()
{
$account = Auth::user()->account->load('country');
$data['account'] = $account;
$data['templates'] = [];
$data['defaultTemplates'] = [];
foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type) {
@ -266,44 +320,34 @@ class AccountController extends BaseController
}
$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.templates_and_reminders', $data);
}
return View::make("accounts.{$subSection}", $data);
} elseif ($section == ACCOUNT_PRODUCTS) {
$data = [
'account' => Auth::user()->account,
'title' => trans('texts.product_library'),
];
return View::make('accounts.products', $data);
}
}
public function doSection($section = ACCOUNT_DETAILS, $subSection = false)
public function doSection($section = ACCOUNT_COMPANY_DETAILS)
{
if ($section == ACCOUNT_DETAILS) {
if ($section === ACCOUNT_COMPANY_DETAILS) {
return AccountController::saveDetails();
} elseif ($section == ACCOUNT_IMPORT_EXPORT) {
} elseif ($section === ACCOUNT_USER_DETAILS) {
return AccountController::saveUserDetails();
} elseif ($section === ACCOUNT_LOCALIZATION) {
return AccountController::saveLocalization();
} elseif ($section === ACCOUNT_IMPORT_EXPORT) {
return AccountController::importFile();
} elseif ($section == ACCOUNT_MAP) {
} elseif ($section === ACCOUNT_MAP) {
return AccountController::mapFile();
} elseif ($section == ACCOUNT_NOTIFICATIONS) {
} elseif ($section === ACCOUNT_NOTIFICATIONS) {
return AccountController::saveNotifications();
} elseif ($section == ACCOUNT_EXPORT) {
} elseif ($section === ACCOUNT_EXPORT) {
return AccountController::export();
} elseif ($section == ACCOUNT_ADVANCED_SETTINGS) {
if ($subSection == ACCOUNT_INVOICE_SETTINGS) {
} elseif ($section === ACCOUNT_INVOICE_SETTINGS) {
return AccountController::saveInvoiceSettings();
} elseif ($subSection == ACCOUNT_INVOICE_DESIGN) {
} elseif ($section === ACCOUNT_INVOICE_DESIGN) {
return AccountController::saveInvoiceDesign();
} elseif ($subSection == ACCOUNT_CUSTOMIZE_DESIGN) {
} elseif ($section === ACCOUNT_CUSTOMIZE_DESIGN) {
return AccountController::saveCustomizeDesign();
} elseif ($subSection == ACCOUNT_TEMPLATES_AND_REMINDERS) {
} elseif ($section === ACCOUNT_TEMPLATES_AND_REMINDERS) {
return AccountController::saveEmailTemplates();
}
} elseif ($section == ACCOUNT_PRODUCTS) {
} elseif ($section === ACCOUNT_PRODUCTS) {
return AccountController::saveProducts();
}
}
@ -318,7 +362,7 @@ class AccountController extends BaseController
Session::flash('message', trans('texts.updated_settings'));
}
return Redirect::to('company/advanced_settings/customize_design');
return Redirect::to('settings/' . ACCOUNT_CUSTOMIZE_DESIGN);
}
private function saveEmailTemplates()
@ -351,7 +395,7 @@ class AccountController extends BaseController
Session::flash('message', trans('texts.updated_settings'));
}
return Redirect::to('company/advanced_settings/templates_and_reminders');
return Redirect::to('settings/' . ACCOUNT_TEMPLATES_AND_REMINDERS);
}
private function saveProducts()
@ -363,7 +407,7 @@ class AccountController extends BaseController
$account->save();
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('company/products');
return Redirect::to('settings/' . ACCOUNT_PRODUCTS);
}
private function saveInvoiceSettings()
@ -386,7 +430,7 @@ class AccountController extends BaseController
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to('company/details')
return Redirect::to('settings/' . ACCOUNT_INVOICE_SETTINGS)
->withErrors($validator)
->withInput();
} else {
@ -420,8 +464,7 @@ class AccountController extends BaseController
if (!$account->share_counter && $account->invoice_number_prefix == $account->quote_number_prefix) {
Session::flash('error', trans('texts.invalid_counter'));
return Redirect::to('company/advanced_settings/invoice_settings')->withInput();
return Redirect::to('settings/' . ACCOUNT_INVOICE_SETTINGS)->withInput();
} else {
$account->save();
Session::flash('message', trans('texts.updated_settings'));
@ -429,7 +472,7 @@ class AccountController extends BaseController
}
}
return Redirect::to('company/advanced_settings/invoice_settings');
return Redirect::to('settings/' . ACCOUNT_INVOICE_SETTINGS);
}
private function saveInvoiceDesign()
@ -457,7 +500,7 @@ class AccountController extends BaseController
Session::flash('message', trans('texts.updated_settings'));
}
return Redirect::to('company/advanced_settings/invoice_design');
return Redirect::to('settings/' . ACCOUNT_INVOICE_DESIGN);
}
private function export()
@ -568,7 +611,7 @@ class AccountController extends BaseController
if ($file == null) {
Session::flash('error', trans('texts.select_file'));
return Redirect::to('company/import_export');
return Redirect::to('settings/' . ACCOUNT_IMPORT_EXPORT);
}
$name = $file->getRealPath();
@ -582,7 +625,7 @@ class AccountController extends BaseController
$message = trans('texts.limit_clients', ['count' => Auth::user()->getMaxNumClients()]);
Session::flash('error', $message);
return Redirect::to('company/import_export');
return Redirect::to('settings/' . ACCOUNT_IMPORT_EXPORT);
}
Session::put('data', $csv->data);
@ -680,7 +723,7 @@ class AccountController extends BaseController
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('company/notifications');
return Redirect::to('settings/' . ACCOUNT_NOTIFICATIONS);
}
private function saveDetails()
@ -690,16 +733,10 @@ class AccountController extends BaseController
'logo' => 'sometimes|max:1024|mimes:jpeg,gif,png',
);
$user = Auth::user()->account->users()->orderBy('id')->first();
if (Auth::user()->id === $user->id) {
$rules['email'] = 'email|required|unique:users,email,'.$user->id.',id';
}
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to('company/details')
return Redirect::to('settings/' . ACCOUNT_COMPANY_DETAILS)
->withErrors($validator)
->withInput();
} else {
@ -717,30 +754,8 @@ class AccountController extends BaseController
$account->country_id = Input::get('country_id') ? Input::get('country_id') : null;
$account->size_id = Input::get('size_id') ? Input::get('size_id') : null;
$account->industry_id = Input::get('industry_id') ? Input::get('industry_id') : null;
$account->timezone_id = Input::get('timezone_id') ? Input::get('timezone_id') : null;
$account->date_format_id = Input::get('date_format_id') ? Input::get('date_format_id') : null;
$account->datetime_format_id = Input::get('datetime_format_id') ? Input::get('datetime_format_id') : null;
$account->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1; // US Dollar
$account->language_id = Input::get('language_id') ? Input::get('language_id') : 1; // English
$account->military_time = Input::get('military_time') ? true : false;
$account->save();
$user = Auth::user();
$user->first_name = trim(Input::get('first_name'));
$user->last_name = trim(Input::get('last_name'));
$user->username = trim(Input::get('email'));
$user->email = trim(strtolower(Input::get('email')));
$user->phone = trim(Input::get('phone'));
if (Utils::isNinja()) {
if (Input::get('referral_code') && !$user->referral_code) {
$user->referral_code = $this->accountRepo->getReferralCode();
}
}
if (Utils::isNinjaDev()) {
$user->dark_mode = Input::get('dark_mode') ? true : false;
}
$user->save();
/* Logo image file */
if ($file = Input::file('logo')) {
$path = Input::file('logo')->getRealPath();
@ -770,10 +785,61 @@ class AccountController extends BaseController
Event::fire(new UserSettingsChanged());
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('company/details');
return Redirect::to('settings/' . ACCOUNT_COMPANY_DETAILS);
}
}
private function saveUserDetails()
{
$user = Auth::user();
$rules = ['email' => 'email|required|unique:users,email,'.$user->id.',id'];
$validator = Validator::make(Input::all(), $rules);
if ($validator->fails()) {
return Redirect::to('settings/' . ACCOUNT_USER_DETAILS)
->withErrors($validator)
->withInput();
} else {
$user->first_name = trim(Input::get('first_name'));
$user->last_name = trim(Input::get('last_name'));
$user->username = trim(Input::get('email'));
$user->email = trim(strtolower(Input::get('email')));
$user->phone = trim(Input::get('phone'));
if (Utils::isNinja()) {
if (Input::get('referral_code') && !$user->referral_code) {
$user->referral_code = $this->accountRepo->getReferralCode();
}
}
if (Utils::isNinjaDev()) {
$user->dark_mode = Input::get('dark_mode') ? true : false;
}
$user->save();
Event::fire(new UserSettingsChanged());
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('settings/' . ACCOUNT_USER_DETAILS);
}
}
private function saveLocalization()
{
$account = Auth::user()->account;
$account->timezone_id = Input::get('timezone_id') ? Input::get('timezone_id') : null;
$account->date_format_id = Input::get('date_format_id') ? Input::get('date_format_id') : null;
$account->datetime_format_id = Input::get('datetime_format_id') ? Input::get('datetime_format_id') : null;
$account->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1; // US Dollar
$account->language_id = Input::get('language_id') ? Input::get('language_id') : 1; // English
$account->military_time = Input::get('military_time') ? true : false;
$account->save();
Event::fire(new UserSettingsChanged());
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('settings/' . ACCOUNT_LOCALIZATION);
}
public function removeLogo()
{
File::delete('logo/'.Auth::user()->account->account_key.'.jpg');
@ -781,7 +847,7 @@ class AccountController extends BaseController
Session::flash('message', trans('texts.removed_logo'));
return Redirect::to('company/details');
return Redirect::to('settings/' . ACCOUNT_COMPANY_DETAILS);
}
public function checkEmail()
@ -879,6 +945,26 @@ class AccountController extends BaseController
$user = Auth::user();
$this->userMailer->sendConfirmation($user);
return Redirect::to('/company/details')->with('message', trans('texts.confirmation_resent'));
return Redirect::to('/settings/' . ACCOUNT_COMPANY_DETAILS)->with('message', trans('texts.confirmation_resent'));
}
public function redirectLegacy($section, $subSection = false)
{
if ($section === 'details') {
$section = ACCOUNT_COMPANY_DETAILS;
} elseif ($section === 'payments') {
$section = ACCOUNT_PAYMENTS;
} elseif ($section === 'advanced_settings') {
$section = $subSection;
if ($section === 'token_management') {
$section = ACCOUNT_API_TOKENS;
}
}
if (!in_array($section, array_merge(Account::$basicSettings, Account::$advancedSettings))) {
$section = ACCOUNT_COMPANY_DETAILS;
}
return Redirect::to("/settings/$section/", 301);
}
}

View File

@ -159,7 +159,6 @@ class AccountGatewayController extends BaseController
'gateways' => $gateways,
'creditCardTypes' => $creditCards,
'tokenBillingOptions' => $tokenBillingOptions,
'showBreadcrumbs' => false,
'countGateways' => count($currentGateways)
];
}
@ -173,7 +172,7 @@ class AccountGatewayController extends BaseController
Session::flash('message', trans('texts.deleted_gateway'));
return Redirect::to('company/payments');
return Redirect::to('settings/' . ACCOUNT_PAYMENTS);
}
/**

View File

@ -61,7 +61,7 @@ class AuthController extends Controller {
$this->accountRepo->unlinkUserFromOauth(Auth::user());
Session::flash('message', trans('texts.updated_settings'));
return redirect()->to('/company/details');
return redirect()->to('/settings/' . ACCOUNT_COMPANY_DETAILS);
}
public function getLoginWrapper()

View File

@ -45,7 +45,6 @@ class ProductController extends BaseController
public function edit($publicId)
{
$data = [
'showBreadcrumbs' => false,
'product' => Product::scope($publicId)->firstOrFail(),
'method' => 'PUT',
'url' => 'products/'.$publicId,
@ -58,7 +57,6 @@ class ProductController extends BaseController
public function create()
{
$data = [
'showBreadcrumbs' => false,
'product' => null,
'method' => 'POST',
'url' => 'products',
@ -94,7 +92,7 @@ class ProductController extends BaseController
$message = $productPublicId ? trans('texts.updated_product') : trans('texts.created_product');
Session::flash('message', $message);
return Redirect::to('company/products');
return Redirect::to('settings/' . ACCOUNT_PRODUCTS);
}
public function archive($publicId)
@ -104,6 +102,6 @@ class ProductController extends BaseController
Session::flash('message', trans('texts.archived_product'));
return Redirect::to('company/products');
return Redirect::to('settings/' . ACCOUNT_PRODUCTS);
}
}

View File

@ -33,7 +33,6 @@ class ReportController extends BaseController
}
$data = [
'feature' => ACCOUNT_DATA_VISUALIZATIONS,
'clients' => $clients,
'message' => $message,
];
@ -276,7 +275,6 @@ class ReportController extends BaseController
'startDate' => $startDate->format(Session::get(SESSION_DATE_FORMAT)),
'endDate' => $endDate->format(Session::get(SESSION_DATE_FORMAT)),
'groupBy' => $groupBy,
'feature' => ACCOUNT_CHART_BUILDER,
'displayData' => $displayData,
'columns' => $columns,
'reportTotals' => $reportTotals,

View File

@ -67,7 +67,6 @@ class TokenController extends BaseController
->where('public_id', '=', $publicId)->firstOrFail();
$data = [
'showBreadcrumbs' => false,
'token' => $token,
'method' => 'PUT',
'url' => 'tokens/'.$publicId,
@ -94,12 +93,10 @@ class TokenController extends BaseController
public function create()
{
$data = [
'showBreadcrumbs' => false,
'token' => null,
'method' => 'POST',
'url' => 'tokens',
'title' => trans('texts.add_token'),
'feature' => 'tokens',
];
return View::make('accounts.token', $data);
@ -115,7 +112,7 @@ class TokenController extends BaseController
Session::flash('message', trans('texts.deleted_token'));
return Redirect::to('company/advanced_settings/token_management');
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
}
/**
@ -163,7 +160,7 @@ class TokenController extends BaseController
Session::flash('message', $message);
}
return Redirect::to('company/advanced_settings/token_management');
return Redirect::to('settings/' . ACCOUNT_API_TOKENS);
}
}

View File

@ -106,7 +106,6 @@ class UserController extends BaseController
->where('public_id', '=', $publicId)->firstOrFail();
$data = [
'showBreadcrumbs' => false,
'user' => $user,
'method' => 'PUT',
'url' => 'users/'.$publicId,
@ -134,24 +133,22 @@ class UserController extends BaseController
{
if (!Auth::user()->registered) {
Session::flash('error', trans('texts.register_to_add_user'));
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
if (!Auth::user()->confirmed) {
Session::flash('error', trans('texts.confirmation_required'));
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
if (Utils::isNinja()) {
$count = User::where('account_id', '=', Auth::user()->account_id)->count();
if ($count >= MAX_NUM_USERS) {
Session::flash('error', trans('texts.limit_users'));
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
}
$data = [
'showBreadcrumbs' => false,
'user' => null,
'method' => 'POST',
'url' => 'users',
@ -171,7 +168,7 @@ class UserController extends BaseController
Session::flash('message', trans('texts.deleted_user'));
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
public function restoreUser($userPublicId)
@ -184,7 +181,7 @@ class UserController extends BaseController
Session::flash('message', trans('texts.restored_user'));
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
/**
@ -247,7 +244,7 @@ class UserController extends BaseController
Session::flash('message', $message);
}
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}
public function sendConfirmation($userPublicId)
@ -258,7 +255,7 @@ class UserController extends BaseController
$this->userMailer->sendConfirmation($user, Auth::user());
Session::flash('message', trans('texts.sent_invite'));
return Redirect::to('company/advanced_settings/user_management');
return Redirect::to('settings/' . ACCOUNT_USER_MANAGEMENT);
}

View File

@ -121,14 +121,16 @@ Route::group(['middleware' => 'auth'], function() {
Route::resource('products', 'ProductController');
Route::get('products/{product_id}/archive', 'ProductController@archive');
Route::get('company/advanced_settings/data_visualizations', 'ReportController@d3');
Route::get('company/advanced_settings/charts_and_reports', 'ReportController@showReports');
Route::post('company/advanced_settings/charts_and_reports', 'ReportController@showReports');
Route::get('company/{section}/{subSection?}', 'AccountController@redirectLegacy');
Route::get('settings/data_visualizations', 'ReportController@d3');
Route::get('settings/charts_and_reports', 'ReportController@showReports');
Route::post('settings/charts_and_reports', 'ReportController@showReports');
Route::post('settings/cancel_account', 'AccountController@cancelAccount');
Route::get('settings/{section?}', 'AccountController@showSection');
Route::post('settings/{section?}', 'AccountController@doSection');
Route::post('company/cancel_account', 'AccountController@cancelAccount');
Route::get('account/getSearchData', array('as' => 'getSearchData', 'uses' => 'AccountController@getSearchData'));
Route::get('company/{section?}/{sub_section?}', 'AccountController@showSection');
Route::post('company/{section?}/{sub_section?}', 'AccountController@doSection');
Route::post('user/setTheme', 'UserController@setTheme');
Route::post('remove_logo', 'AccountController@removeLogo');
Route::post('account/go_pro', 'AccountController@enableProPlan');
@ -183,7 +185,6 @@ Route::group(['middleware' => 'auth'], function() {
Route::post('credits/bulk', 'CreditController@bulk');
get('/resend_confirmation', 'AccountController@resendConfirmation');
//Route::resource('timesheets', 'TimesheetController');
});
// Route group for API
@ -253,21 +254,26 @@ if (!defined('CONTACT_EMAIL')) {
define('PERSON_CONTACT', 'contact');
define('PERSON_USER', 'user');
define('ACCOUNT_DETAILS', 'details');
define('BASIC_SETTINGS', 'basic_settings');
define('ADVANCED_SETTINGS', 'advanced_settings');
define('ACCOUNT_COMPANY_DETAILS', 'company_details');
define('ACCOUNT_USER_DETAILS', 'user_details');
define('ACCOUNT_LOCALIZATION', 'localization');
define('ACCOUNT_NOTIFICATIONS', 'notifications');
define('ACCOUNT_IMPORT_EXPORT', 'import_export');
define('ACCOUNT_PAYMENTS', 'payments');
define('ACCOUNT_PAYMENTS', 'online_payments');
define('ACCOUNT_MAP', 'import_map');
define('ACCOUNT_EXPORT', 'export');
define('ACCOUNT_PRODUCTS', 'products');
define('ACCOUNT_ADVANCED_SETTINGS', 'advanced_settings');
define('ACCOUNT_INVOICE_SETTINGS', 'invoice_settings');
define('ACCOUNT_INVOICE_DESIGN', 'invoice_design');
define('ACCOUNT_CHART_BUILDER', 'chart_builder');
define('ACCOUNT_CHARTS_AND_REPORTS', 'charts_and_reports');
define('ACCOUNT_USER_MANAGEMENT', 'user_management');
define('ACCOUNT_DATA_VISUALIZATIONS', 'data_visualizations');
define('ACCOUNT_TEMPLATES_AND_REMINDERS', 'templates_and_reminders');
define('ACCOUNT_TOKEN_MANAGEMENT', 'token_management');
define('ACCOUNT_API_TOKENS', 'api_tokens');
define('ACCOUNT_CUSTOMIZE_DESIGN', 'customize_design');

View File

@ -15,6 +15,26 @@ class Account extends Eloquent
protected $dates = ['deleted_at'];
protected $hidden = ['ip'];
public static $basicSettings = [
ACCOUNT_COMPANY_DETAILS,
ACCOUNT_USER_DETAILS,
ACCOUNT_LOCALIZATION,
ACCOUNT_PAYMENTS,
ACCOUNT_PRODUCTS,
ACCOUNT_NOTIFICATIONS,
ACCOUNT_IMPORT_EXPORT,
];
public static $advancedSettings = [
ACCOUNT_INVOICE_DESIGN,
ACCOUNT_INVOICE_SETTINGS,
ACCOUNT_TEMPLATES_AND_REMINDERS,
ACCOUNT_CHARTS_AND_REPORTS,
ACCOUNT_DATA_VISUALIZATIONS,
ACCOUNT_USER_MANAGEMENT,
ACCOUNT_API_TOKENS,
];
/*
protected $casts = [
'invoice_settings' => 'object',

View File

@ -145,7 +145,6 @@ class ContactMailer extends Mailer
$subject = $this->processVariables($emailSubject, $variables);
$data['invoice_id'] = $payment->invoice->id;
$invoice->updateCachedPDF();
if ($user->email && $contact->email) {
$this->sendTo($contact->email, $user->email, $accountName, $subject, $view, $data);

View File

@ -49,7 +49,7 @@ class AuthService
Session::flash('warning', trans('texts.success_message'));
} else {
Session::flash('message', trans('texts.updated_settings'));
return redirect()->to('/company/details');
return redirect()->to('/settings/' . ACCOUNT_COMPANY_DETAILS);
}
} else {
Session::flash('error', $result);

10
public/css/built.css vendored
View File

@ -3341,3 +3341,13 @@ ul.user-accounts a:hover div.remove {
text-align:left;
width: 350px;
}
.list-group-item.selected:before {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 2px;
content: "";
background-color: #e37329;
}

View File

@ -866,11 +866,11 @@ body {
}
/* Hide bootstrap sort header icons */
table.data-table thead .sorting:after { content: '' !important }
table.data-table thead .sorting_asc:after { content: '' !important }
table.data-table thead .sorting_desc:after { content: '' !important}
table.data-table thead .sorting_asc_disabled:after { content: '' !important }
table.data-table thead .sorting_desc_disabled:after { content: '' !important }
table.table thead .sorting:after { content: '' !important }
table.table thead .sorting_asc:after { content: '' !important }
table.table thead .sorting_desc:after { content: '' !important }
table.table thead .sorting_asc_disabled:after { content: '' !important }
table.table thead .sorting_desc_disabled:after { content: '' !important }
.dataTables_length {
padding-left: 20px;

11
public/css/style.css vendored
View File

@ -991,3 +991,14 @@ ul.user-accounts a:hover div.remove {
text-align:left;
width: 350px;
}
/* Show selected section in settings nav */
.list-group-item.selected:before {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 2px;
content: "";
background-color: #e37329;
}

View File

@ -262,7 +262,7 @@
'email_salutation' => 'Kære :name,',
'email_signature' => 'Med venlig hilsen,',
'email_from' => 'Invoice Ninja Teamet',
'user_email_footer' => 'For at justere varslings indstillingene besøg venligst'.SITE_URL.'/company/notifications',
'user_email_footer' => 'For at justere varslings indstillingene besøg venligst'.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Hvis du vil se din klient faktura klik på linket under:',
'notification_invoice_paid_subject' => 'Faktura :invoice betalt af :client',
'notification_invoice_sent_subject' => 'Faktura :invoice sendt til :client',
@ -271,15 +271,14 @@
'notification_invoice_sent' => 'En e-mail er blevet sendt til :client med faktura :invoice pålydende :amount.',
'notification_invoice_viewed' => ':client har set faktura :invoice pålydende :amount.',
'reset_password' => 'Du kan nulstille din adgangskode ved at besøge følgende link:',
'reset_password_footer' => 'Hvis du ikke bad om at få nulstillet din adgangskode kontakt venligst kundeservice: ' . CONTACT_EMAIL,
'reset_password_footer' => 'Hvis du ikke bad om at få nulstillet din adgangskode kontakt venligst kundeservice: '.CONTACT_EMAIL,
// Payment page
'secure_payment' => 'Sikker betaling',
'card_number' => 'Kortnummer',
'expiration_month' => 'Udløbsdato',
'expiration_year' => 'Udløbsår',
'cvv' =>'Kontrolcifre',
'cvv' => 'Kontrolcifre',
// Security alerts
'security' => [
@ -300,7 +299,7 @@
'logout' => 'Log ud',
'sign_up_to_save' => 'Registrer dig for at gemme dit arbejde',
'agree_to_terms' =>'Jeg accepterer Invoice Ninja :terms',
'agree_to_terms' => 'Jeg accepterer Invoice Ninja :terms',
'terms_of_service' => 'Vilkår for brug',
'email_taken' => 'E-mailadressen er allerede registreret',
'working' => 'Arbejder',
@ -420,7 +419,7 @@
'active' => 'Aktiv',
'pending' => 'Afventer',
'deleted_user' => 'Bruger slettet',
'limit_users' => 'Desværre, dette vil overstige grænsen på ' . MAX_NUM_USERS . ' brugere',
'limit_users' => 'Desværre, dette vil overstige grænsen på '.MAX_NUM_USERS.' brugere',
'confirm_email_invoice' => 'Er du sikker på at du vil sende en e-mail med denne faktura?',
'confirm_email_quote' => 'Er du sikker på du ville sende en e-mail med dette tilbud?',
@ -818,6 +817,9 @@
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Sehr geehrte/r :name,',
'email_signature' => 'Mit freundlichen Grüßen,',
'email_from' => 'Das InvoiceNinja Team',
'user_email_footer' => 'Um deine E-Mail-Benachrichtigungen anzupassen besuche bitte '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Um deine E-Mail-Benachrichtigungen anzupassen besuche bitte '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Um deine Kundenrechnung anzuschauen, klicke auf den folgenden Link:',
'notification_invoice_paid_subject' => 'Die Rechnung :invoice wurde von :client bezahlt.',
'notification_invoice_sent_subject' => 'Die Rechnung :invoice wurde an :client versendet.',
@ -817,6 +817,10 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Dear :name,',
'email_signature' => 'Regards,',
'email_from' => 'The Invoice Ninja Team',
'user_email_footer' => 'To adjust your email notification settings please visit '.SITE_URL.'/company/notifications',
'user_email_footer' => 'To adjust your email notification settings please visit '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'To view your client invoice click the link below:',
'notification_invoice_paid_subject' => 'Invoice :invoice was paid by :client',
'notification_invoice_sent_subject' => 'Invoice :invoice was sent to :client',
@ -557,7 +557,7 @@ return array(
'created_gateway' => 'Successfully created gateway',
'deleted_gateway' => 'Successfully deleted gateway',
'pay_with_paypal' => 'PayPal',
'pay_with_card' => 'Credit card',
'pay_with_card' => 'Credit Card',
'change_password' => 'Change password',
'current_password' => 'Current password',
@ -587,7 +587,7 @@ return array(
'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.',
'payment_type_credit_card' => 'Credit card',
'payment_type_credit_card' => 'Credit Card',
'payment_type_paypal' => 'PayPal',
'payment_type_bitcoin' => 'Bitcoin',
'knowledge_base' => 'Knowledge Base',
@ -818,6 +818,9 @@ return array(
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -256,7 +256,7 @@ return array(
'email_salutation' => 'Estimado :name,',
'email_signature' => 'Un saludo cordial,',
'email_from' => 'El equipo de Invoice Ninja ',
'user_email_footer' => 'Para ajustar la configuración de las notificaciones de tu correo, visita '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Para ajustar la configuración de las notificaciones de tu correo, visita '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Para visualizar la factura de cliente, haz clic en el enlace abajo:',
'notification_invoice_paid_subject' => 'La factura :invoice ha sido pagada por el cliente :client',
'notification_invoice_sent_subject' => 'La factura :invoice ha sido enviada a el cliente :client',
@ -795,6 +795,10 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -1,4 +1,4 @@
<?php
<?php
return array(
@ -271,7 +271,7 @@ return array(
'email_salutation' => 'Estimado :name,',
'email_signature' => 'Un cordial saludo,',
'email_from' => 'El equipo de Invoice Ninja ',
'user_email_footer' => 'Para ajustar la configuración de las notificaciones de tu email, visita '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Para ajustar la configuración de las notificaciones de tu email, visita '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Para visualizar la factura de cliente, haz clic en el enlace de abajo:',
'notification_invoice_paid_subject' => 'La factura :invoice ha sido pagada por el cliente :client',
'notification_invoice_sent_subject' => 'La factura :invoice ha sido enviada a el cliente :client',
@ -280,7 +280,7 @@ return array(
'notification_invoice_sent' => 'La factura :invoice por importe de :amount fue enviada al cliente :cliente.',
'notification_invoice_viewed' => 'La factura :invoice por importe de :amount fue visualizada por el cliente :client.',
'reset_password' => 'Puedes reconfigurar la contraseña de tu cuenta haciendo clic en el siguiente enlace:',
'reset_password_footer' => 'Si no has solicitado un cambio de contraseña, por favor contactate con nosostros: ' . CONTACT_EMAIL,
'reset_password_footer' => 'Si no has solicitado un cambio de contraseña, por favor contactate con nosostros: '.CONTACT_EMAIL,
// Payment page
'secure_payment' => 'Pago seguro',
@ -307,7 +307,7 @@ return array(
],
'logout' => 'Cerrar sesión',
'sign_up_to_save' => 'Registrate para guardar tu trabajo',
'agree_to_terms' =>'Estoy de acuerdo con los términos de Invoice Ninja :terms',
'agree_to_terms' => 'Estoy de acuerdo con los términos de Invoice Ninja :terms',
'terms_of_service' => 'Términos de servicio',
'email_taken' => 'Esta dirección de correo electrónico ya se ha registrado',
'working' => 'Procesando',
@ -414,7 +414,7 @@ return array(
'active' => 'Activo',
'pending' => 'Pendiente',
'deleted_user' => 'Usario eliminado con éxito',
'limit_users' => 'Lo sentimos, esta acción excederá el límite de ' . MAX_NUM_USERS . ' usarios',
'limit_users' => 'Lo sentimos, esta acción excederá el límite de '.MAX_NUM_USERS.' usarios',
'confirm_email_invoice' => '¿Estás seguro que quieres enviar esta factura?',
'confirm_email_quote' => '¿Estás seguro que quieres enviar este presupuesto?',
'confirm_recurring_email_invoice' => 'Se ha marcado esta factura como recurrente, estás seguro que quieres enviar esta factura?',
@ -435,7 +435,6 @@ return array(
'invalid_counter' => 'Para evitar posibles conflictos, por favor crea un prefijo de facturación y de presupuesto.',
'mark_sent' => 'Marcar como enviado',
'gateway_help_1' => ':link para registrarse en Authorize.net.',
'gateway_help_2' => ':link para registrarse en Authorize.net.',
'gateway_help_17' => ':link para obtener su firma API de PayPal.',
@ -817,6 +816,9 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Cher :name,',
'email_signature' => 'Cordialement,',
'email_from' => 'L\'équipe Invoice Ninja',
'user_email_footer' => 'Pour modifier vos paramètres de notification par courriel, veuillez visiter '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Pour modifier vos paramètres de notification par courriel, veuillez visiter '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Pour voir la facture de votre client cliquez sur le lien ci-après :',
'notification_invoice_paid_subject' => 'La facture :invoice a été payée par le client :client',
'notification_invoice_sent_subject' => 'La facture :invoice a été envoyée au client :client',
@ -809,6 +809,10 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Cher :name,',
'email_signature' => 'Cordialement,',
'email_from' => 'L\'équipe InvoiceNinja',
'user_email_footer' => 'Pour modifier vos paramètres de notification par courriel, veuillez visiter '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Pour modifier vos paramètres de notification par courriel, veuillez visiter '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Pour voir la facture de votre client cliquez sur le lien ci-après :',
'notification_invoice_paid_subject' => 'La facture :invoice a été payée par le client :client',
'notification_invoice_sent_subject' => 'La facture :invoice a été envoyée au client :client',
@ -810,6 +810,10 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Caro :name,',
'email_signature' => 'Distinti saluti,',
'email_from' => 'Il Team di InvoiceNinja',
'user_email_footer' => 'Per modificare le impostazioni di notifiche via email per favore accedi a: '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Per modificare le impostazioni di notifiche via email per favore accedi a: '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Per visualizzare la tua fattura del cliente clicca sul link qui sotto:',
'notification_invoice_paid_subject' => 'La fattura :invoice è stata pagata da :client',
'notification_invoice_sent_subject' => 'La fattura :invoice è stata inviata a :client',
@ -812,5 +812,9 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Dear :name,',
'email_signature' => 'Regards,',
'email_from' => 'The Invoice Ninja Team',
'user_email_footer' => 'To adjust your email notification settings please visit '.SITE_URL.'/company/notifications',
'user_email_footer' => 'To adjust your email notification settings please visit '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'To view your client invoice click the link below:',
'notification_invoice_paid_subject' => 'Invoice :invoice was paid by :client',
'notification_invoice_sent_subject' => 'Invoice :invoice was sent to :client',
@ -819,6 +819,10 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Kj&#230;re :name,',
'email_signature' => 'Med vennlig hilsen,',
'email_from' => 'The Invoice Ninja Team',
'user_email_footer' => 'For &#229; justere varslingsinnstillingene vennligst bes&#248;k '.SITE_URL.'/company/notifications',
'user_email_footer' => 'For &#229; justere varslingsinnstillingene vennligst bes&#248;k '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Hvis du vil se din klientfaktura klikk p&#229; linken under:',
'notification_invoice_paid_subject' => 'Faktura :invoice betalt av :client',
'notification_invoice_sent_subject' => 'Faktura :invoice sendt til :client',
@ -817,5 +817,9 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -260,7 +260,7 @@ return array(
'email_salutation' => 'Beste :name,',
'email_signature' => 'Met vriendelijke groeten,',
'email_from' => 'Het InvoiceNinja Team',
'user_email_footer' => 'Ga alstublieft naar '.SITE_URL.'/company/notifications om je e-mail notificatie instellingen aan te passen ',
'user_email_footer' => 'Ga alstublieft naar '.SITE_URL.'/settings/notifications om je e-mail notificatie instellingen aan te passen ',
'invoice_link_message' => 'Klik op volgende link om de Factuur van je klant te bekijken:',
'notification_invoice_paid_subject' => 'Factuur :invoice is betaald door :client',
'notification_invoice_sent_subject' => 'Factuur :invoice is gezonden door :client',
@ -812,5 +812,9 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -258,7 +258,7 @@ return array(
'email_salutation' => 'Caro :name,',
'email_signature' => 'Até mais,',
'email_from' => 'Equipe InvoiceNinja',
'user_email_footer' => 'Para ajustar suas configurações de notificações de email acesse '.SITE_URL.'/company/notifications',
'user_email_footer' => 'Para ajustar suas configurações de notificações de email acesse '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'Para visualizar a fatura do seu cliente clique no link abaixo:',
'notification_invoice_paid_subject' => 'Fatura :invoice foi pago por :client',
'notification_invoice_sent_subject' => 'Fatura :invoice foi enviado por :client',
@ -812,5 +812,9 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -262,7 +262,7 @@ return array(
'email_salutation' => 'Hej :name,',
'email_signature' => 'Vänliga hälsningar,',
'email_from' => 'Invoice Ninja teamet',
'user_email_footer' => 'För att anpassa dina e-post notifieringar gå till '.SITE_URL.'/company/notifications',
'user_email_footer' => 'För att anpassa dina e-post notifieringar gå till '.SITE_URL.'/settings/notifications',
'invoice_link_message' => 'För att se din kundfaktura klicka på länken nedan:',
'notification_invoice_paid_subject' => 'Faktura :invoice är betald av :client',
'notification_invoice_sent_subject' => 'Faktura :invoice är skickad till :client',
@ -815,5 +815,9 @@ return array(
'custom_invoice_link' => 'Custom Invoice Link',
'total_invoiced' => 'Total Invoiced',
'open_balance' => 'Open Balance',
'verify_email' => 'Please visit the link in the account confirmation email to verify your email address.',
'basic_settings' => 'Basic Settings',
'pro' => 'Pro',
'gateways' => 'Payment Gateways',
);

View File

@ -1,9 +1,11 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
{!! Former::open($url)->method($method)->rule()->addClass('col-md-8 col-md-offset-2 warn-on-exit') !!}
@include('accounts.nav', ['selected' => ACCOUNT_PAYMENTS])
{!! Former::open($url)->method($method)->rule()->addClass('warn-on-exit') !!}
{!! Former::populate($account) !!}
@ -106,7 +108,7 @@
<p/>&nbsp;<p/>
{!! Former::actions(
$countGateways > 0 ? Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/company/payments'))->appendIcon(Icon::create('remove-circle')) : false,
$countGateways > 0 ? Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/online_payments'))->appendIcon(Icon::create('remove-circle')) : false,
Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))) !!}
{!! Former::close() !!}

View File

@ -0,0 +1,72 @@
@extends('header')
@section('content')
@parent
@include('accounts.nav', ['selected' => ACCOUNT_API_TOKENS, 'advanced' => true])
{!! Former::open('tokens/delete')->addClass('user-form') !!}
<div style="display:none">
{!! Former::text('tokenPublicId') !!}
</div>
{!! Former::close() !!}
<div class="pull-right">
{!! Button::normal(trans('texts.documentation'))->asLinkTo(NINJA_WEB_URL.'/knowledgebase/api-documentation/')->withAttributes(['target' => '_blank'])->appendIcon(Icon::create('info-sign')) !!}
@if (Utils::isNinja())
{!! Button::normal(trans('texts.zapier'))->asLinkTo(ZAPIER_URL)->withAttributes(['target' => '_blank']) !!}
@endif
@if (Utils::isPro())
{!! Button::primary(trans('texts.add_token'))->asLinkTo(URL::to('/tokens/create'))->appendIcon(Icon::create('plus-sign')) !!}
@endif
</div>
<!--
<label for="trashed" style="font-weight:normal; margin-left: 10px;">
<input id="trashed" type="checkbox" onclick="setTrashVisible()"
{!! Session::get('show_trash:token') ? 'checked' : ''!!}/> {!! trans('texts.show_deleted_tokens')!!}
</label>
-->
{!! Datatable::table()
->addColumn(
trans('texts.name'),
trans('texts.token'),
trans('texts.action'))
->setUrl(url('api/tokens/'))
->setOptions('sPaginationType', 'bootstrap')
->setOptions('bFilter', false)
->setOptions('bAutoWidth', false)
->setOptions('aoColumns', [[ "sWidth"=> "40%" ], [ "sWidth"=> "40%" ], ["sWidth"=> "20%"]])
->setOptions('aoColumnDefs', [['bSortable'=>false, 'aTargets'=>[2]]])
->render('datatable') !!}
<script>
window.onDatatableReady = function() {
$('tbody tr').mouseover(function() {
$(this).closest('tr').find('.tr-action').css('visibility','visible');
}).mouseout(function() {
$dropdown = $(this).closest('tr').find('.tr-action');
if (!$dropdown.hasClass('open')) {
$dropdown.css('visibility','hidden');
}
});
}
function setTrashVisible() {
var checked = $('#trashed').is(':checked');
window.location = '{!! URL::to('view_archive/token') !!}' + (checked ? '/true' : '/false');
}
function deleteToken(id) {
if (!confirm("{!! trans('texts.are_you_sure') !!}")) {
return;
}
$('#tokenPublicId').val(id);
$('form.user-form').submit();
}
</script>
@stop

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('head')
@parent
@ -28,8 +28,7 @@
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_INVOICE_DESIGN, 'advanced' => true])
<script>
@ -155,7 +154,7 @@
{!! Former::select('invoice_design_id')->style('display:inline;width:120px')->fromQuery($invoiceDesigns, 'name', 'id')->onchange('onSelectChange()')->raw() !!}
<div class="pull-right">
{!! Button::normal(trans('texts.help'))->withAttributes(['onclick' => 'showHelp()'])->appendIcon(Icon::create('question-sign')) !!}
{!! Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/company/advanced_settings/invoice_design'))->appendIcon(Icon::create('remove-circle')) !!}
{!! Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/invoice_design'))->appendIcon(Icon::create('remove-circle')) !!}
@if (Auth::user()->isPro())
{!! Button::success(trans('texts.save'))->withAttributes(['onclick' => 'submitForm()'])->appendIcon(Icon::create('floppy-disk')) !!}
@endif

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@ -13,21 +13,14 @@
{!! Former::open_for_files()->addClass('warn-on-exit')->rules(array(
'name' => 'required',
'email' => 'email|required'
)) !!}
{{ Former::populate($account) }}
{{ Former::populateField('military_time', intval($account->military_time)) }}
{{ Former::populateField('first_name', $user->first_name) }}
{{ Former::populateField('last_name', $user->last_name) }}
{{ Former::populateField('email', $user->email) }}
{{ Former::populateField('phone', $user->phone) }}
@if (Utils::isNinjaDev())
{{ Former::populateField('dark_mode', intval($user->dark_mode)) }}
@endif
@include('accounts.nav', ['selected' => ACCOUNT_COMPANY_DETAILS])
<div class="row">
<div class="col-md-6">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
@ -72,133 +65,13 @@
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.user_details') !!}</h3>
</div>
<div class="panel-body">
{!! Former::text('first_name') !!}
{!! Former::text('last_name') !!}
{!! Former::text('email') !!}
{!! Former::text('phone') !!}
@if (Utils::isNinja())
{!! Former::plaintext('oneclick_login')->value(
$user->oauth_provider_id ?
$oauthProviderName . ' - ' . link_to('#', trans('texts.disable'), ['onclick' => 'disableSocialLogin()']) :
DropdownButton::primary(trans('texts.enable'))->withContents($oauthLoginUrls)->small()
) !!}
@endif
@if (Utils::isNinja() && $user->confirmed)
@if ($user->referral_code)
{!! Former::plaintext('referral_code')
->value($user->referral_code . ' <a href="'.REFERRAL_PROGRAM_URL.'" target="_blank" title="'.trans('texts.learn_more').'">' . Icon::create('question-sign') . '</a>') !!}
@else
{!! Former::checkbox('referral_code')
->text(trans('texts.enable') . ' <a href="'.REFERRAL_PROGRAM_URL.'" target="_blank" title="'.trans('texts.learn_more').'">' . Icon::create('question-sign') . '</a>') !!}
@endif
@endif
@if (false && Utils::isNinjaDev())
{!! Former::checkbox('dark_mode')->text(trans('texts.dark_mode_help')) !!}
@endif
@if (Utils::isNinja())
<br/>
@if (Auth::user()->confirmed)
{!! Former::actions( Button::primary(trans('texts.change_password'))->small()->withAttributes(['onclick'=>'showChangePassword()'])) !!}
@elseif (Auth::user()->registered)
{!! Former::actions( Button::primary(trans('texts.resend_confirmation'))->asLinkTo(URL::to('/resend_confirmation'))->small() ) !!}
@endif
@endif
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.localization') !!}</h3>
</div>
<div class="panel-body">
{!! Former::select('currency_id')->addOption('','')
->fromQuery($currencies, 'name', 'id') !!}
{!! Former::select('language_id')->addOption('','')
->fromQuery($languages, 'name', 'id') !!}
{!! Former::select('timezone_id')->addOption('','')
->fromQuery($timezones, 'location', 'id') !!}
{!! Former::select('date_format_id')->addOption('','')
->fromQuery($dateFormats, 'label', 'id') !!}
{!! Former::select('datetime_format_id')->addOption('','')
->fromQuery($datetimeFormats, 'label', 'id') !!}
{!! Former::checkbox('military_time')->text(trans('texts.enable')) !!}
</div>
</div>
</div>
</div>
<center>
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
</center>
<div class="modal fade" id="passwordModal" tabindex="-1" role="dialog" aria-labelledby="passwordModalLabel" 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">&times;</button>
<h4 class="modal-title" id="passwordModalLabel">{{ trans('texts.change_password') }}</h4>
</div>
<div style="background-color: #fff" id="changePasswordDiv" onkeyup="validateChangePassword()" onclick="validateChangePassword()" onkeydown="checkForEnter(event)">
&nbsp;
{!! Former::password('current_password')->style('width:300px') !!}
{!! Former::password('newer_password')->style('width:300px')->label(trans('texts.new_password')) !!}
{!! Former::password('confirm_password')->style('width:300px') !!}
&nbsp;
<br/>
<center>
<div id="changePasswordError"></div>
</center>
<br/>
</div>
<div style="padding-left:40px;padding-right:40px;display:none;min-height:130px" id="working">
<h3>{{ trans('texts.working') }}...</h3>
<div class="progress progress-striped active">
<div class="progress-bar" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
</div>
</div>
<div style="background-color: #fff; padding-right:20px;padding-left:20px; display:none" id="successDiv">
<br/>
<h3>{{ trans('texts.success') }}</h3>
{{ trans('texts.updated_password') }}
<br/>
&nbsp;
<br/>
</div>
<div class="modal-footer" style="margin-top: 0px" id="changePasswordFooter">
<button type="button" class="btn btn-default" id="cancelChangePasswordButton" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-success" onclick="submitChangePassword()" id="changePasswordButton" disabled>
{{ trans('texts.save') }}
<i class="glyphicon glyphicon-floppy-disk"></i>
</button>
</div>
</div>
</div>
</div>
{!! Former::close() !!}
{!! Form::open(['url' => 'remove_logo', 'class' => 'removeLogoForm']) !!}
@ -209,21 +82,6 @@
$(function() {
$('#country_id').combobox();
$('#passwordModal').on('hidden.bs.modal', function () {
$(['current_password', 'newer_password', 'confirm_password']).each(function(i, field) {
var $input = $('form #'+field);
$input.val('');
$input.closest('div.form-group').removeClass('has-success');
});
$('#changePasswordButton').prop('disabled', true);
})
$('#passwordModal').on('shown.bs.modal', function () {
$('#current_password').focus();
})
localStorage.setItem('auth_provider', '{{ strtolower($oauthProviderName) }}');
});
function deleteLogo() {
@ -232,84 +90,6 @@
}
}
function showChangePassword() {
$('#passwordModal').modal('show');
}
function checkForEnter(event)
{
if (event.keyCode === 13){
event.preventDefault();
return false;
}
}
function validateChangePassword(showError)
{
var isFormValid = true;
$(['current_password', 'newer_password', 'confirm_password']).each(function(i, field) {
var $input = $('form #'+field),
val = $.trim($input.val());
var isValid = val && val.length >= 6;
if (isValid && field == 'confirm_password') {
isValid = val == $.trim($('#newer_password').val());
}
if (isValid) {
$input.closest('div.form-group').removeClass('has-error').addClass('has-success');
} else {
isFormValid = false;
$input.closest('div.form-group').removeClass('has-success');
if (showError) {
$input.closest('div.form-group').addClass('has-error');
}
}
});
$('#changePasswordButton').prop('disabled', !isFormValid);
return isFormValid;
}
function submitChangePassword()
{
if (!validateChangePassword(true)) {
return;
}
$('#changePasswordDiv, #changePasswordFooter').hide();
$('#working').show();
$.ajax({
type: 'POST',
url: '{{ URL::to('/users/change_password') }}',
data: 'current_password=' + encodeURIComponent($('form #current_password').val()) +
'&new_password=' + encodeURIComponent($('form #newer_password').val()) +
'&confirm_password=' + encodeURIComponent($('form #confirm_password').val()),
success: function(result) {
if (result == 'success') {
NINJA.formIsChanged = false;
$('#changePasswordButton').hide();
$('#successDiv').show();
$('#cancelChangePasswordButton').html('{{ trans('texts.close') }}');
} else {
$('#changePasswordError').html(result);
$('#changePasswordDiv').show();
}
$('#changePasswordFooter').show();
$('#working').hide();
}
});
}
function disableSocialLogin() {
if (!confirm("{!! trans('texts.are_you_sure') !!}")) {
return;
}
window.location = '{{ URL::to('/auth_unlink') }}';
}
</script>
@stop

View File

@ -1,7 +1,8 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav', ['selected' => ACCOUNT_IMPORT_EXPORT])
{{ Former::open()->addClass('col-md-9 col-md-offset-1') }}
{{ Former::legend('Export Client Data') }}

View File

@ -1,9 +1,11 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
{!! Former::open_for_files('company/import_map')->addClass('col-md-8 col-md-offset-2') !!}
@include('accounts.nav', ['selected' => ACCOUNT_IMPORT_EXPORT])
{!! Former::open_for_files('settings/' . ACCOUNT_MAP) !!}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.import_clients') !!}</h3>
@ -16,7 +18,7 @@
{!! Former::close() !!}
{!! Former::open('company/export')->addClass('col-md-8 col-md-offset-2') !!}
{!! Former::open('settings/' . ACCOUNT_EXPORT) !!}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.export_clients') !!}</h3>
@ -28,7 +30,7 @@
{!! Former::close() !!}
{!! Former::open('company/cancel_account')->addClass('col-md-8 col-md-offset-2 cancel-account') !!}
{!! Former::open('settings/cancel_account')->addClass('cancel-account') !!}
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.cancel_account') !!}</h3>

View File

@ -1,9 +1,11 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
{!! Former::open('company/import_export')->addClass('col-md-8 col-md-offset-2 warn-on-exit') !!}
@include('accounts.nav', ['selected' => ACCOUNT_IMPORT_EXPORT])
{!! Former::open('settings/' . ACCOUNT_IMPORT_EXPORT)->addClass('warn-on-exit') !!}
<div class="panel panel-default">
<div class="panel-heading">
@ -46,7 +48,7 @@
{!! Former::actions(
Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/company/import_export'))->appendIcon(Icon::create('remove-circle')),
Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/import_export'))->appendIcon(Icon::create('remove-circle')),
Button::success(trans('texts.import'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))) !!}
{!! Former::close() !!}

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('head')
@parent
@ -12,7 +12,7 @@
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_INVOICE_DESIGN, 'advanced' => true])
<script>
var invoiceDesigns = {!! $invoiceDesigns !!};
@ -105,7 +105,7 @@
{!! Former::text('secondary_color') !!}
{!! Former::actions(
Button::primary(trans('texts.customize_design'))->small()->asLinkTo(URL::to('/company/advanced_settings/customize_design'))
Button::primary(trans('texts.customize_design'))->small()->asLinkTo(URL::to('/settings/customize_design'))
) !!}
</div>

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('head')
@parent
@ -18,9 +18,9 @@
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_INVOICE_SETTINGS, 'advanced' => true])
{!! Former::open()->addClass('col-md-8 col-md-offset-2 warn-on-exit') !!}
{!! Former::open()->addClass('warn-on-exit') !!}
{{ Former::populate($account) }}
{{ Former::populateField('custom_invoice_taxes1', intval($account->custom_invoice_taxes1)) }}
{{ Former::populateField('custom_invoice_taxes2', intval($account->custom_invoice_taxes2)) }}

View File

@ -0,0 +1,45 @@
@extends('header')
@section('content')
@parent
{!! Former::open_for_files()->addClass('warn-on-exit') !!}
{{ Former::populate($account) }}
@include('accounts.nav', ['selected' => ACCOUNT_LOCALIZATION])
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.localization') !!}</h3>
</div>
<div class="panel-body">
{!! Former::select('currency_id')->addOption('','')
->fromQuery($currencies, 'name', 'id') !!}
{!! Former::select('language_id')->addOption('','')
->fromQuery($languages, 'name', 'id') !!}
{!! Former::select('timezone_id')->addOption('','')
->fromQuery($timezones, 'location', 'id') !!}
{!! Former::select('date_format_id')->addOption('','')
->fromQuery($dateFormats, 'label', 'id') !!}
{!! Former::select('datetime_format_id')->addOption('','')
->fromQuery($datetimeFormats, 'label', 'id') !!}
{!! Former::checkbox('military_time')->text(trans('texts.enable')) !!}
</div>
</div>
</div>
<center>
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
</center>
{!! Former::close() !!}
@stop
@section('onReady')
$('#currency_id').focus();
@stop

View File

@ -1,16 +1,33 @@
@extends('header')
@if (!Utils::isPro() && isset($advanced) && $advanced)
<div class="alert alert-warning" style="font-size:larger;">
<center>
{!! trans('texts.pro_plan_advanced_settings', ['link'=>'<a href="#" onclick="showProPlan(\''.$selected.'\')">'.trans('texts.pro_plan.remove_logo_link').'</a>']) !!}
</center>
</div>
@endif
@section('content')
<div class="row">
<ul class="nav nav-tabs nav nav-justified">
{!! HTML::nav_link('company/details', 'company_details') !!}
{!! HTML::nav_link('company/payments', 'online_payments', 'gateways') !!}
{!! HTML::nav_link('company/products', 'product_library') !!}
{!! HTML::nav_link('company/notifications', 'notifications') !!}
{!! HTML::nav_link('company/import_export', 'import_export', 'company/import_map') !!}
{!! HTML::nav_link('company/advanced_settings/invoice_design', 'advanced_settings', '*/advanced_settings/*') !!}
</ul>
<div class="col-md-3">
@foreach([
BASIC_SETTINGS => \App\Models\Account::$basicSettings,
ADVANCED_SETTINGS => \App\Models\Account::$advancedSettings,
] as $type => $settings)
<div class="panel panel-default">
<div class="panel-heading" style="color:white">
{{ trans("texts.{$type}") }}
@if ($type == ADVANCED_SETTINGS && !Utils::isPro())
<sup>{{ strtoupper(trans('texts.pro')) }}</sup>
@endif
</div>
<div class="list-group">
@foreach ($settings as $section)
<a href="{{ URL::to("settings/{$section}") }}" class="list-group-item {{ $selected === $section ? 'selected' : '' }}"
style="width:100%;text-align:left">{{ trans("texts.{$section}") }}</a>
@endforeach
</div>
</div>
@endforeach
</div>
<br/>
@stop
<div class="col-md-9">

View File

@ -1,9 +1,11 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
{!! Former::open()->addClass('col-md-8 col-md-offset-2 warn-on-exit') !!}
@include('accounts.nav', ['selected' => ACCOUNT_NOTIFICATIONS])
{!! Former::open()->addClass('warn-on-exit') !!}
{{ Former::populate($account) }}
{{ Former::populateField('notify_sent', intval(Auth::user()->notify_sent)) }}
{{ Former::populateField('notify_viewed', intval(Auth::user()->notify_viewed)) }}

View File

@ -1,7 +1,8 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav', ['selected' => ACCOUNT_PAYMENTS])
{!! Former::open('gateways/delete')->addClass('user-form') !!}

View File

@ -1,11 +1,13 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav', ['selected' => ACCOUNT_PRODUCTS])
{!! Former::open($url)->method($method)
->rules(['product_key' => 'required|max:255'])
->addClass('col-md-8 col-md-offset-2 warn-on-exit') !!}
->addClass('warn-on-exit') !!}
<div class="panel panel-default">
@ -27,7 +29,7 @@
</div>
{!! Former::actions(
Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/company/products'))->appendIcon(Icon::create('remove-circle')),
Button::normal(trans('texts.cancel'))->large()->asLinkTo(URL::to('/settings/products'))->appendIcon(Icon::create('remove-circle')),
Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))
) !!}

View File

@ -1,8 +1,10 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav', ['selected' => ACCOUNT_PRODUCTS])
{!! Former::open()->addClass('warn-on-exit') !!}
{{ Former::populateField('fill_products', intval($account->fill_products)) }}
{{ Former::populateField('update_products', intval($account->update_products)) }}

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('head')
@parent
@ -13,9 +13,9 @@
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_TEMPLATES_AND_REMINDERS, 'advanced' => true])
{!! Former::vertical_open()->addClass('col-md-10 col-md-offset-1 warn-on-exit') !!}
{!! Former::vertical_open()->addClass('warn-on-exit') !!}
{!! Former::populate($account) !!}
@foreach ([ENTITY_INVOICE, ENTITY_QUOTE, ENTITY_PAYMENT, REMINDER1, REMINDER2, REMINDER3] as $type)

View File

@ -1,10 +1,10 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_API_TOKENS])
{!! Former::open($url)->method($method)->addClass('col-md-8 col-md-offset-2 warn-on-exit')->rules(array(
{!! Former::open($url)->method($method)->addClass('warn-on-exit')->rules(array(
'name' => 'required',
)); !!}
@ -25,7 +25,7 @@
@if (Auth::user()->isPro())
{!! Former::actions(
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/company/advanced_settings/token_management'))->appendIcon(Icon::create('remove-circle'))->large(),
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/token_management'))->appendIcon(Icon::create('remove-circle'))->large(),
Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk'))
) !!}
@else

View File

@ -1,8 +1,8 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_API_TOKENS, 'advanced' => true])
{!! Former::open('tokens/delete')->addClass('user-form') !!}

View File

@ -0,0 +1,223 @@
@extends('header')
@section('content')
@parent
{!! Former::open_for_files()->addClass('warn-on-exit')->rules(array(
'email' => 'email|required'
)) !!}
{{ Former::populate($account) }}
{{ Former::populateField('military_time', intval($account->military_time)) }}
{{ Former::populateField('first_name', $user->first_name) }}
{{ Former::populateField('last_name', $user->last_name) }}
{{ Former::populateField('email', $user->email) }}
{{ Former::populateField('phone', $user->phone) }}
@if (Utils::isNinjaDev())
{{ Former::populateField('dark_mode', intval($user->dark_mode)) }}
@endif
@include('accounts.nav', ['selected' => ACCOUNT_USER_DETAILS])
<div class="row">
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.user_details') !!}</h3>
</div>
<div class="panel-body">
{!! Former::text('first_name') !!}
{!! Former::text('last_name') !!}
{!! Former::text('email') !!}
{!! Former::text('phone') !!}
@if (Utils::isNinja())
{!! Former::plaintext('oneclick_login')->value(
$user->oauth_provider_id ?
$oauthProviderName . ' - ' . link_to('#', trans('texts.disable'), ['onclick' => 'disableSocialLogin()']) :
DropdownButton::primary(trans('texts.enable'))->withContents($oauthLoginUrls)->small()
) !!}
@endif
@if (Utils::isNinja() && $user->confirmed)
@if ($user->referral_code)
{!! Former::plaintext('referral_code')
->value($user->referral_code . ' <a href="'.REFERRAL_PROGRAM_URL.'" target="_blank" title="'.trans('texts.learn_more').'">' . Icon::create('question-sign') . '</a>') !!}
@else
{!! Former::checkbox('referral_code')
->text(trans('texts.enable') . ' <a href="'.REFERRAL_PROGRAM_URL.'" target="_blank" title="'.trans('texts.learn_more').'">' . Icon::create('question-sign') . '</a>') !!}
@endif
@endif
@if (false && Utils::isNinjaDev())
{!! Former::checkbox('dark_mode')->text(trans('texts.dark_mode_help')) !!}
@endif
@if (Utils::isNinja())
<br/>
@if (Auth::user()->confirmed)
{!! Former::actions( Button::primary(trans('texts.change_password'))->small()->withAttributes(['onclick'=>'showChangePassword()'])) !!}
@elseif (Auth::user()->registered)
{!! Former::actions( Button::primary(trans('texts.resend_confirmation'))->asLinkTo(URL::to('/resend_confirmation'))->small() ) !!}
@endif
@endif
</div>
</div>
</div>
<center>
{!! Button::success(trans('texts.save'))->submit()->large()->appendIcon(Icon::create('floppy-disk')) !!}
</center>
</div>
<div class="modal fade" id="passwordModal" tabindex="-1" role="dialog" aria-labelledby="passwordModalLabel" 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">&times;</button>
<h4 class="modal-title" id="passwordModalLabel">{{ trans('texts.change_password') }}</h4>
</div>
<div style="background-color: #fff" id="changePasswordDiv" onkeyup="validateChangePassword()" onclick="validateChangePassword()" onkeydown="checkForEnter(event)">
&nbsp;
{!! Former::password('current_password')->style('width:300px') !!}
{!! Former::password('newer_password')->style('width:300px')->label(trans('texts.new_password')) !!}
{!! Former::password('confirm_password')->style('width:300px') !!}
&nbsp;
<br/>
<center>
<div id="changePasswordError"></div>
</center>
<br/>
</div>
<div style="padding-left:40px;padding-right:40px;display:none;min-height:130px" id="working">
<h3>{{ trans('texts.working') }}...</h3>
<div class="progress progress-striped active">
<div class="progress-bar" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
</div>
</div>
<div style="background-color: #fff; padding-right:20px;padding-left:20px; display:none" id="successDiv">
<br/>
<h3>{{ trans('texts.success') }}</h3>
{{ trans('texts.updated_password') }}
<br/>
&nbsp;
<br/>
</div>
<div class="modal-footer" style="margin-top: 0px" id="changePasswordFooter">
<button type="button" class="btn btn-default" id="cancelChangePasswordButton" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-success" onclick="submitChangePassword()" id="changePasswordButton" disabled>
{{ trans('texts.save') }}
<i class="glyphicon glyphicon-floppy-disk"></i>
</button>
</div>
</div>
</div>
</div>
{!! Former::close() !!}
<script type="text/javascript">
$(function() {
$('#passwordModal').on('hidden.bs.modal', function () {
$(['current_password', 'newer_password', 'confirm_password']).each(function(i, field) {
var $input = $('form #'+field);
$input.val('');
$input.closest('div.form-group').removeClass('has-success');
});
$('#changePasswordButton').prop('disabled', true);
})
$('#passwordModal').on('shown.bs.modal', function () {
$('#current_password').focus();
})
localStorage.setItem('auth_provider', '{{ strtolower($oauthProviderName) }}');
});
function showChangePassword() {
$('#passwordModal').modal('show');
}
function validateChangePassword(showError)
{
var isFormValid = true;
$(['current_password', 'newer_password', 'confirm_password']).each(function(i, field) {
var $input = $('form #'+field),
val = $.trim($input.val());
var isValid = val && val.length >= 6;
if (isValid && field == 'confirm_password') {
isValid = val == $.trim($('#newer_password').val());
}
if (isValid) {
$input.closest('div.form-group').removeClass('has-error').addClass('has-success');
} else {
isFormValid = false;
$input.closest('div.form-group').removeClass('has-success');
if (showError) {
$input.closest('div.form-group').addClass('has-error');
}
}
});
$('#changePasswordButton').prop('disabled', !isFormValid);
return isFormValid;
}
function submitChangePassword()
{
if (!validateChangePassword(true)) {
return;
}
$('#changePasswordDiv, #changePasswordFooter').hide();
$('#working').show();
$.ajax({
type: 'POST',
url: '{{ URL::to('/users/change_password') }}',
data: 'current_password=' + encodeURIComponent($('form #current_password').val()) +
'&new_password=' + encodeURIComponent($('form #newer_password').val()) +
'&confirm_password=' + encodeURIComponent($('form #confirm_password').val()),
success: function(result) {
if (result == 'success') {
NINJA.formIsChanged = false;
$('#changePasswordButton').hide();
$('#successDiv').show();
$('#cancelChangePasswordButton').html('{{ trans('texts.close') }}');
} else {
$('#changePasswordError').html(result);
$('#changePasswordDiv').show();
}
$('#changePasswordFooter').show();
$('#working').hide();
}
});
}
function disableSocialLogin() {
if (!confirm("{!! trans('texts.are_you_sure') !!}")) {
return;
}
window.location = '{{ URL::to('/auth_unlink') }}';
}
</script>
@stop
@section('onReady')
$('#first_name').focus();
@stop

View File

@ -1,8 +1,8 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_USER_MANAGEMENT, 'advanced' => true])
{!! Former::open('users/delete')->addClass('user-form') !!}
@ -13,7 +13,6 @@
<div class="pull-right">
{!! Button::normal(trans('texts.api_tokens'))->asLinkTo(URL::to('/company/advanced_settings/token_management'))->appendIcon(Icon::create('cloud')) !!}
@if (Utils::isPro())
{!! Button::primary(trans('texts.add_user'))->asLinkTo(URL::to('/users/create'))->appendIcon(Icon::create('plus-sign')) !!}
@endif

View File

@ -438,12 +438,10 @@
<span class="glyphicon glyphicon-cog" title="{{ trans('texts.settings') }}"/>
</a>
<ul class="dropdown-menu">
<li>{!! link_to('company/details', uctrans('texts.company_details')) !!}</li>
<li>{!! link_to('company/payments', uctrans('texts.online_payments')) !!}</li>
<li>{!! link_to('company/products', uctrans('texts.product_library')) !!}</li>
<li>{!! link_to('company/notifications', uctrans('texts.notifications')) !!}</li>
<li>{!! link_to('company/import_export', uctrans('texts.import_export')) !!}</li>
<li><a href="{{ url('company/advanced_settings/invoice_design') }}">{!! uctrans('texts.advanced_settings') . Utils::getProLabel(ACCOUNT_ADVANCED_SETTINGS) !!}</a></li>
@foreach (\App\Models\Account::$basicSettings as $setting)
<li>{!! link_to('settings/' . $setting, uctrans("texts.{$setting}")) !!}</li>
@endforeach
<li><a href="{{ url('settings/' . ACCOUNT_INVOICE_DESIGN) }}">{!! uctrans('texts.advanced_settings') . Utils::getProLabel(ACCOUNT_ADVANCED_SETTINGS) !!}</a></li>
</ul>
</li>
</ul>
@ -667,6 +665,7 @@
{{-- Per our license, please do not remove or modify this section. --}}
@if (!Utils::isNinjaProd())
</div>
<p>&nbsp;</p>
<div class="container">
{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a> -

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('head')
@parent
@ -8,24 +8,7 @@
@section('content')
@parent
@include('accounts.nav_advanced')
{!! Button::primary(trans('texts.data_visualizations'))
->asLinkTo(URL::to('/company/advanced_settings/data_visualizations'))
->withAttributes(['class' => 'pull-right'])
->appendIcon(Icon::create('globe')) !!}
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="row">
<div class="col-lg-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.settings') !!}</h3>
</div>
<div class="panel-body">
@include('accounts.nav', ['selected' => ACCOUNT_CHARTS_AND_REPORTS, 'advanced' => true])
{!! Former::open()->rules(['start_date' => 'required', 'end_date' => 'required'])->addClass('warn-on-exit') !!}
@ -39,6 +22,16 @@
{!! Former::populateField('enable_report', intval($enableReport)) !!}
{!! Former::populateField('enable_chart', intval($enableChart)) !!}
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">{!! trans('texts.settings') !!}</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="col-md-6">
{!! Former::text('start_date')->data_date_format(Session::get(SESSION_DATE_PICKER_FORMAT))
->addGroupClass('start_date')
->append('<i class="glyphicon glyphicon-calendar" onclick="toggleDatePicker(\'start_date\')"></i>') !!}
@ -47,36 +40,36 @@
->append('<i class="glyphicon glyphicon-calendar" onclick="toggleDatePicker(\'end_date\')"></i>') !!}
<p>&nbsp;</p>
{!! Former::actions(
Button::primary(trans('texts.export'))->withAttributes(array('onclick' => 'onExportClick()'))->appendIcon(Icon::create('export')),
Button::success(trans('texts.run'))->withAttributes(array('id' => 'submitButton'))->submit()->appendIcon(Icon::create('play'))
) !!}
@if (!Auth::user()->isPro())
<script>
$(function() {
$('form.warn-on-exit').find('input, select, button').prop('disabled', true);
});
</script>
@endif
</div>
<div class="col-md-6">
{!! Former::checkbox('enable_report')->text(trans('texts.enable')) !!}
{!! Former::select('report_type')->options($reportTypes, $reportType)->label(trans('texts.group_by')) !!}
<p>&nbsp;</p>
{!! Former::checkbox('enable_chart')->text(trans('texts.enable')) !!}
{!! Former::select('group_by')->options($dateTypes, $groupBy) !!}
{!! Former::select('chart_type')->options($chartTypes, $chartType) !!}
<p>&nbsp;</p>
@if (Auth::user()->isPro())
{!! Former::actions(
Button::primary(trans('texts.export'))->withAttributes(array('onclick' => 'onExportClick()'))->appendIcon(Icon::create('export')),
Button::success(trans('texts.run'))->withAttributes(array('id' => 'submitButton'))->submit()->appendIcon(Icon::create('play'))
) !!}
@else
<script>
$(function() {
$('form.warn-on-exit').find('input, select').prop('disabled', true);
});
</script>
@endif
{!! Former::close() !!}
</div>
</div>
</div>
<div class="col-lg-8">
</div>
@if ($enableReport)
<div class="panel panel-default">
<div class="panel-body">
@ -155,8 +148,6 @@
</div>
</div>
<script type="text/javascript">
function onExportClick() {

View File

@ -1,4 +1,4 @@
@extends('accounts.nav')
@extends('header')
@section('head')
@parent
@ -30,7 +30,7 @@
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_DATA_VISUALIZATIONS, 'advanced' => true])
<div id="tooltip" class="hidden">
<p>
@ -121,22 +121,10 @@
product.displayAge = product.values.age;
});
/*
_.each(clients, function(client) {
_.each(client.invoices, function(invoice) {
_.each(invoice.invoice_items, function(invoice_item) {
delete invoice_item.invoice;
});
});
});
*/
//console.log(JSON.stringify(clients));
//console.log(JSON.stringify(invoices));
//console.log(JSON.stringify(products));
var arc = d3.svg.arc()
.innerRadius(function(d) { return d.r - 2 })
.outerRadius(function(d) { return d.r - 8 })
@ -149,7 +137,7 @@
.endAngle(2 * Math.PI);
var diameter = 1050,
var diameter = 900,
format = d3.format(",d");
//color = d3.scale.category10();
@ -164,14 +152,14 @@
.padding(12);
var svg = d3.select(".svg-div").append("svg")
.attr("width", "1142px")
.attr("width", "100%")
.attr("height", "1142px")
.attr("class", "bubble");
svg.append("rect")
.attr("stroke-width", "1")
.attr("stroke", "rgb(150,150,150)")
.attr("width", "100%")
.attr("width", "99%")
.attr("height", "100%")
.attr("fill", "white");
@ -187,7 +175,6 @@
var selection = svg.selectAll(".node")
.data(data, function(d) { return d.displayName; });
//.data(data);
var node = selection.enter().append("g")
.attr("class", "node")
@ -198,9 +185,10 @@
if (!visibleTooltip || visibleTooltip != d.displayName) {
d3.select("#tooltip")
.classed("hidden", false)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px");
.style("left", (d3.event.offsetX + 40) + "px")
.style("top", (d3.event.offsetY + 40) + "px");
visibleTooltip = d.displayName;
//console.log(d3.event);
}
d3.select("#tooltipTitle").text(truncate(d.displayName, 18));

View File

@ -45,7 +45,7 @@
@if (Auth::user()->account->timezone_id)
{{ $timezone }}
@else
{!! link_to('/company/details?focus=timezone_id', $timezone, ['target' => '_blank']) !!}
{!! link_to('/settings/company_details?focus=timezone_id', $timezone, ['target' => '_blank']) !!}
@endif
<p/>

View File

@ -2,7 +2,7 @@
@if (isset($user_id) && $user_id != Auth::user()->id)
<a href="{{ URL::to("/switch_account/{$user_id}") }}">
@else
<a href="{{ URL::to("/company/details") }}">
<a href="{{ URL::to("/settings/company_details") }}">
@endif
@if (file_exists($logo_path))

View File

@ -1,10 +1,10 @@
@extends('accounts.nav')
@extends('header')
@section('content')
@parent
@include('accounts.nav_advanced')
@include('accounts.nav', ['selected' => ACCOUNT_USER_MANAGEMENT])
{!! Former::open($url)->method($method)->addClass('col-md-8 col-md-offset-2 warn-on-exit')->rules(array(
{!! Former::open($url)->method($method)->addClass('warn-on-exit')->rules(array(
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required|email',
@ -28,7 +28,7 @@
</div>
{!! Former::actions(
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/company/advanced_settings/user_management'))->appendIcon(Icon::create('remove-circle'))->large(),
Button::normal(trans('texts.cancel'))->asLinkTo(URL::to('/settings/user_management'))->appendIcon(Icon::create('remove-circle'))->large(),
Button::success(trans($user && $user->confirmed ? 'texts.save' : 'texts.send_invite'))->submit()->large()->appendIcon(Icon::create($user && $user->confirmed ? 'floppy-disk' : 'send'))
)!!}

View File

@ -52,31 +52,31 @@ $I->see('Payments', 'li');
$I->see('Create');
// Settings pages
$I->amOnPage('/company/details');
$I->amOnPage('/settings/company_details');
$I->see('Details');
$I->amOnPage('/gateways/create');
$I->see('Add Gateway');
$I->amOnPage('/company/products');
$I->amOnPage('/settings/products');
$I->see('Product Settings');
$I->amOnPage('/company/import_export');
$I->amOnPage('/settings/import_export');
$I->see('Import');
$I->amOnPage('/company/advanced_settings/invoice_settings');
$I->amOnPage('/settings/invoice_settings');
$I->see('Invoice Fields');
$I->amOnPage('/company/advanced_settings/invoice_design');
$I->amOnPage('/settings/invoice_design');
$I->see('Invoice Design');
$I->amOnPage('/company/advanced_settings/templates_and_reminders');
$I->amOnPage('/settings/templates_and_reminders');
$I->see('Invoice Email');
$I->amOnPage('/company/advanced_settings/charts_and_reports');
$I->amOnPage('/settings/charts_and_reports');
$I->see('Data Visualizations');
$I->amOnPage('/company/advanced_settings/user_management');
$I->amOnPage('/settings/user_management');
$I->see('Add User');
//try to logout

View File

@ -24,7 +24,7 @@ class InvoiceDesignCest
{
$I->wantTo('Design my invoice');
$I->amOnPage('/company/advanced_settings/invoice_design');
$I->amOnPage('/settings/invoice_design');
$I->click('select#invoice_design_id');
$I->click('select#invoice_design_id option:nth-child(2)');

View File

@ -24,7 +24,7 @@ class OnlinePaymentCest
// set gateway info
$I->wantTo('create a gateway');
$I->amOnPage('/company/payments');
$I->amOnPage('/settings/online_payments');
if (strpos($I->grabFromCurrentUrl(), 'create') !== false) {
$I->fillField(['name' =>'23_apiKey'], Fixtures::get('gateway_key'));

View File

@ -14,10 +14,11 @@ class SettingsCest
$this->faker = Factory::create();
}
/*
public function companyDetails(FunctionalTester $I)
{
$I->wantTo('update the company details');
$I->amOnPage('/company/details');
$I->amOnPage('/settings/company_details');
$name = $this->faker->company;
@ -29,20 +30,50 @@ class SettingsCest
$I->fillField(['name' => 'city'], $this->faker->city);
$I->fillField(['name' => 'state'], $this->faker->state);
$I->fillField(['name' => 'postal_code'], $this->faker->postcode);
$I->fillField(['name' => 'first_name'], $this->faker->firstName);
$I->fillField(['name' => 'last_name'], $this->faker->lastName);
$I->fillField(['name' => 'phone'], $this->faker->phoneNumber);
$I->click('Save');
$I->seeResponseCodeIs(200);
$I->seeRecord('accounts', array('name' => $name));
}
*/
public function userDetails(FunctionalTester $I)
{
$I->wantTo('update the user details');
$I->amOnPage('/settings/user_details');
$firstName = $this->faker->firstName;
$I->fillField(['name' => 'first_name'], $firstName);
$I->fillField(['name' => 'last_name'], $this->faker->lastName);
$I->fillField(['name' => 'phone'], $this->faker->phoneNumber);
$I->click('Save');
$I->seeResponseCodeIs(200);
$I->seeRecord('users', array('first_name' => $firstName));
}
/*
public function localization(FunctionalTester $I)
{
$I->wantTo('update the localization');
$I->amOnPage('/settings/localization');
$name = $this->faker->company;
$I->fillField(['name' => 'name'], $name);
$I->click('Save');
$I->seeResponseCodeIs(200);
$I->seeRecord('accounts', array('name' => $name));
}
*/
public function productSettings(FunctionalTester $I)
{
$I->wantTo('update the product settings');
$I->amOnPage('/company/products');
$I->amOnPage('/settings/products');
$I->click('Save');
@ -84,7 +115,7 @@ class SettingsCest
public function updateNotifications(FunctionalTester $I)
{
$I->wantTo('update notification settings');
$I->amOnPage('/company/notifications');
$I->amOnPage('/settings/notifications');
$terms = $this->faker->text(80);
@ -99,7 +130,7 @@ class SettingsCest
public function updateInvoiceDesign(FunctionalTester $I)
{
$I->wantTo('update invoice design');
$I->amOnPage('/company/advanced_settings/invoice_design');
$I->amOnPage('/settings/invoice_design');
$color = $this->faker->hexcolor;
@ -114,7 +145,7 @@ class SettingsCest
public function updateInvoiceSettings(FunctionalTester $I)
{
$I->wantTo('update invoice settings');
$I->amOnPage('/company/advanced_settings/invoice_settings');
$I->amOnPage('/settings/invoice_settings');
$label = $this->faker->text(10);
@ -131,7 +162,7 @@ class SettingsCest
public function updateEmailTemplates(FunctionalTester $I)
{
$I->wantTo('update email templates');
$I->amOnPage('/company/advanced_settings/templates_and_reminders');
$I->amOnPage('/settings/templates_and_reminders');
$string = $this->faker->text(100);
@ -145,7 +176,7 @@ class SettingsCest
public function runReport(FunctionalTester $I)
{
$I->wantTo('run the report');
$I->amOnPage('/company/advanced_settings/charts_and_reports');
$I->amOnPage('/settings/charts_and_reports');
$I->click('Run');
$I->seeResponseCodeIs(200);