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

Added multi-company support

This commit is contained in:
Hillel Coren 2015-06-16 22:35:35 +03:00
parent ef08b3c5fe
commit 67dff394b4
33 changed files with 576 additions and 64 deletions

View File

@ -19,3 +19,5 @@ MAIL_USERNAME
MAIL_FROM_ADDRESS
MAIL_FROM_NAME
MAIL_PASSWORD
ALLOW_NEW_ACCOUNTS

View File

@ -1,8 +1,10 @@
<?php namespace App\Exceptions;
use Redirect;
use Utils;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Database\Eloquent\ModelNotFoundException;
class Handler extends ExceptionHandler {
@ -39,7 +41,12 @@ class Handler extends ExceptionHandler {
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
{
if ($e instanceof ModelNotFoundException) {
return Redirect::to('/');
}
if (Utils::isNinjaProd()) {
$data = [
'error' => get_class($e),

View File

@ -77,10 +77,12 @@ class AccountController extends BaseController
{
if (Auth::check()) {
return Redirect::to('invoices/create');
} elseif (!Utils::isNinja() && Account::count() > 0) {
return Redirect::to('/login');
}
if (!Utils::isNinja() && !Utils::allowNewAccounts() && Account::count() > 0) {
return Redirect::to('/login');
}
$user = false;
$guestKey = Input::get('guest_key');
@ -728,7 +730,7 @@ class AccountController extends BaseController
$email = trim(Input::get('email'));
if (!$email || $email == 'user@example.com') {
return RESULT_SUCCESS;
return '';
}
$license = new License();
@ -742,7 +744,7 @@ class AccountController extends BaseController
$license->is_claimed = 1;
$license->save();
return RESULT_SUCCESS;
return '';
}
public function cancelAccount()
@ -762,6 +764,7 @@ class AccountController extends BaseController
$account->forceDelete();
Auth::logout();
Session::flush();
return Redirect::to('/')->with('clearGuestKey', true);
}

View File

@ -3,10 +3,12 @@
use Auth;
use Event;
use Utils;
use Session;
use Illuminate\Http\Request;
use App\Models\User;
use App\Events\UserLoggedIn;
use App\Http\Controllers\Controller;
use App\Ninja\Repositories\AccountRepository;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\Registrar;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
@ -28,6 +30,7 @@ class AuthController extends Controller {
protected $loginPath = '/login';
protected $redirectTo = '/dashboard';
protected $accountRepo;
/**
* Create a new authentication controller instance.
@ -36,12 +39,13 @@ class AuthController extends Controller {
* @param \Illuminate\Contracts\Auth\Registrar $registrar
* @return void
*/
public function __construct(Guard $auth, Registrar $registrar)
public function __construct(Guard $auth, Registrar $registrar, AccountRepository $repo)
{
$this->auth = $auth;
$this->registrar = $registrar;
$this->accountRepo = $repo;
$this->middleware('guest', ['except' => 'getLogout']);
//$this->middleware('guest', ['except' => 'getLogout']);
}
public function getLoginWrapper()
@ -55,13 +59,36 @@ class AuthController extends Controller {
public function postLoginWrapper(Request $request)
{
$userId = Auth::check() ? Auth::user()->id : null;
$response = self::postLogin($request);
if (Auth::check()) {
Event::fire(new UserLoggedIn());
if (Utils::isPro()) {
$users = false;
// we're linking a new account
if ($userId && Auth::user()->id != $userId) {
$users = $this->accountRepo->associateAccounts($userId, Auth::user()->id);
Session::flash('message', trans('texts.associated_accounts'));
// check if other accounts are linked
} else {
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
}
Session::put(SESSION_USER_ACCOUNTS, $users);
}
}
return $response;
}
public function getLogoutWrapper()
{
$response = self::getLogout();
Session::flush();
return $response;
}
}

View File

@ -45,6 +45,11 @@ class HomeController extends BaseController
public function invoiceNow()
{
if (Auth::check() && Input::get('logout')) {
Auth::user()->clearSession();
Auth::logout();
}
if (Auth::check()) {
return Redirect::to('invoices/create')->with('sign_up', Input::get('sign_up'));
} else {

View File

@ -630,8 +630,9 @@ class PaymentController extends BaseController
$invoice = $invitation->invoice;
$accountGateway = $invoice->client->account->getGatewayByType(Session::get('payment_type'));
if ($invoice->account->account_key == NINJA_ACCOUNT_KEY) {
$account = Account::find($invoice->client->public_id);
if ($invoice->account->account_key == NINJA_ACCOUNT_KEY
&& $invoice->amount == PRO_PLAN_PRICE) {
$account = Account::with('users')->find($invoice->client->public_id);
if ($account->pro_plan_paid && $account->pro_plan_paid != '0000-00-00') {
$date = DateTime::createFromFormat('Y-m-d', $account->pro_plan_paid);
$account->pro_plan_paid = $date->modify('+1 year')->format('Y-m-d');
@ -639,6 +640,9 @@ class PaymentController extends BaseController
$account->pro_plan_paid = date_create()->format('Y-m-d');
}
$account->save();
$user = $account->users()->first();
$this->accountRepo->syncAccounts($user->id, $account->pro_plan_paid);
}
$payment = Payment::createNew($invitation);

View File

@ -7,6 +7,7 @@ use DB;
use Event;
use Input;
use View;
use Request;
use Redirect;
use Session;
use URL;
@ -309,10 +310,8 @@ class UserController extends BaseController
}
}
Session::forget('news_feed_id');
Session::forget('news_feed_message');
Auth::logout();
Session::flush();
return Redirect::to('/')->with('clearGuestKey', true);
}
@ -342,4 +341,32 @@ class UserController extends BaseController
return RESULT_SUCCESS;
}
public function switchAccount($newUserId)
{
$oldUserId = Auth::user()->id;
$referer = Request::header('referer');
$account = $this->accountRepo->findUserAccounts($newUserId, $oldUserId);
if ($account) {
if ($account->hasUserId($newUserId) && $account->hasUserId($oldUserId)) {
Auth::loginUsingId($newUserId);
Auth::user()->account->loadLocalizationSettings();
}
}
return Redirect::to($referer);
}
public function unlinkAccount($userAccountId, $userId)
{
$this->accountRepo->unlinkAccount($userAccountId, $userId);
$referer = Request::header('referer');
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
Session::put(SESSION_USER_ACCOUNTS, $users);
Session::flash('message', trans('texts.unlinked_account'));
return Redirect::to($referer);
}
}

View File

@ -67,8 +67,7 @@ get('/signup', array('as' => 'signup', 'uses' => 'Auth\AuthController@getRegiste
post('/signup', array('as' => 'signup', 'uses' => 'Auth\AuthController@postRegister'));
get('/login', array('as' => 'login', 'uses' => 'Auth\AuthController@getLoginWrapper'));
post('/login', array('as' => 'login', 'uses' => 'Auth\AuthController@postLoginWrapper'));
//get('/logout', array('as' => 'logout', 'uses' => 'Auth\AuthController@getLogoutWrapper'));
get('/logout', array('as' => 'logout', 'uses' => 'Auth\AuthController@getLogout'));
get('/logout', array('as' => 'logout', 'uses' => 'Auth\AuthController@getLogoutWrapper'));
get('/forgot', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@getEmail'));
post('/forgot', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@postEmail'));
get('/password/reset/{token}', array('as' => 'forgot', 'uses' => 'Auth\PasswordController@getReset'));
@ -95,6 +94,7 @@ Route::group(['middleware' => 'auth'], function() {
Route::get('restore_user/{user_id}', 'UserController@restoreUser');
Route::post('users/change_password', 'UserController@changePassword');
Route::get('/switch_account/{user_id}', 'UserController@switchAccount');
Route::get('/unlink_account/{user_account_id}/{user_id}', 'UserController@unlinkAccount');
Route::get('api/tokens', array('as'=>'api.tokens', 'uses'=>'TokenController@getDatatable'));
Route::resource('tokens', 'TokenController');

View File

@ -51,12 +51,17 @@ class Utils
public static function isNinjaProd()
{
return isset($_ENV['NINJA_PROD']) && $_ENV['NINJA_PROD'];
return isset($_ENV['NINJA_PROD']) && $_ENV['NINJA_PROD'] == 'true';
}
public static function isNinjaDev()
{
return isset($_ENV['NINJA_DEV']) && $_ENV['NINJA_DEV'];
return isset($_ENV['NINJA_DEV']) && $_ENV['NINJA_DEV'] == 'true';
}
public static function allowNewAccounts()
{
return isset($_ENV['ALLOW_NEW_ACCOUNTS']) && $_ENV['ALLOW_NEW_ACCOUNTS'] == 'true';
}
public static function isPro()

View File

@ -1,9 +1,9 @@
<?php namespace App\Listeners;
use Auth;
use Session;
use App\Events\UserSettingsChanged;
use App\Ninja\Repositories\AccountRepository;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;
@ -14,9 +14,9 @@ class HandleUserSettingsChanged {
*
* @return void
*/
public function __construct()
public function __construct(AccountRepository $accountRepo)
{
//
$this->accountRepo = $accountRepo;
}
/**
@ -29,6 +29,9 @@ class HandleUserSettingsChanged {
{
$account = Auth::user()->account;
$account->loadLocalizationSettings();
$users = $this->accountRepo->loadAccounts(Auth::user()->id);
Session::put(SESSION_USER_ACCOUNTS, $users);
}
}

View File

@ -128,6 +128,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return Session::get(SESSION_COUNTER, 0);
}
/*
public function getPopOverText()
{
if (!Utils::isNinja() || !Auth::check() || Session::has('error')) {
@ -146,7 +147,8 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return false;
}
*/
public function afterSave($success = true, $forced = false)
{
if ($this->email) {
@ -176,4 +178,22 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return 'remember_token';
}
public function clearSession()
{
$keys = [
RECENTLY_VIEWED,
SESSION_USER_ACCOUNTS,
SESSION_TIMEZONE,
SESSION_DATE_FORMAT,
SESSION_DATE_PICKER_FORMAT,
SESSION_DATETIME_FORMAT,
SESSION_CURRENCY,
SESSION_LOCALE,
];
foreach ($keys as $key) {
Session::forget($key);
}
}
}

View File

@ -0,0 +1,52 @@
<?php namespace App\Models;
use Eloquent;
class UserAccount extends Eloquent
{
public $timestamps = false;
public function hasUserId($userId)
{
if (!$userId) {
return false;
}
for ($i=1; $i<=5; $i++) {
$field = "user_id{$i}";
if ($this->$field && $this->$field == $userId) {
return true;
}
}
return false;
}
public function setUserId($userId)
{
if (self::hasUserId($userId)) {
return;
}
for ($i=1; $i<=5; $i++) {
$field = "user_id{$i}";
if (!$this->$field) {
$this->$field = $userId;
break;
}
}
}
public function removeUserId($userId)
{
if (!$userId || !self::hasUserId($userId)) {
return;
}
for ($i=1; $i<=5; $i++) {
$field = "user_id{$i}";
if ($this->$field && $this->$field == $userId) {
$this->$field = null;
}
}
}
}

View File

@ -4,6 +4,8 @@ use Auth;
use Request;
use Session;
use Utils;
use DB;
use stdClass;
use App\Models\AccountGateway;
use App\Models\Invitation;
@ -14,6 +16,7 @@ use App\Models\Language;
use App\Models\Contact;
use App\Models\Account;
use App\Models\User;
use App\Models\UserAccount;
class AccountRepository
{
@ -244,4 +247,129 @@ class AccountRepository
curl_exec($ch);
curl_close($ch);
}
public function findUserAccounts($userId1, $userId2 = false)
{
$query = UserAccount::where('user_id1', '=', $userId1)
->orWhere('user_id2', '=', $userId1)
->orWhere('user_id3', '=', $userId1)
->orWhere('user_id4', '=', $userId1)
->orWhere('user_id5', '=', $userId1);
if ($userId2) {
$query->orWhere('user_id1', '=', $userId2)
->orWhere('user_id2', '=', $userId2)
->orWhere('user_id3', '=', $userId2)
->orWhere('user_id4', '=', $userId2)
->orWhere('user_id5', '=', $userId2);
}
return $query->first(['id', 'user_id1', 'user_id2', 'user_id3', 'user_id4', 'user_id5']);
}
public function prepareUsersData($record) {
if (!$record) {
return false;
}
$userIds = [];
for ($i=1; $i<=5; $i++) {
$field = "user_id$i";
if ($record->$field) {
$userIds[] = $record->$field;
}
}
$users = User::with('account')
->whereIn('id', $userIds)
->get();
$data = [];
foreach ($users as $user) {
$item = new stdClass();
$item->id = $record->id;
$item->user_id = $user->id;
$item->user_name = $user->getDisplayName();
$item->account_id = $user->account->id;
$item->account_name = $user->account->getDisplayName();
$item->pro_plan_paid = $user->account->pro_plan_paid;
$data[] = $item;
}
return $data;
}
public function loadAccounts($userId) {
$record = self::findUserAccounts($userId);
return self::prepareUsersData($record);
}
public function syncAccounts($userId, $proPlanPaid) {
$users = self::loadAccounts($userId);
self::syncUserAccounts($users, $proPlanPaid);
}
public function syncUserAccounts($users, $proPlanPaid = false) {
if (!$proPlanPaid) {
foreach ($users as $user) {
if ($user->pro_plan_paid && $user->pro_plan_paid != '0000-00-00') {
$proPlanPaid = $user->pro_plan_paid;
break;
}
}
}
if (!$proPlanPaid) {
return;
}
$accountIds = [];
foreach ($users as $user) {
if ($user->pro_plan_paid != $proPlanPaid) {
$accountIds[] = $user->account_id;
}
}
if (count($accountIds)) {
DB::table('accounts')
->whereIn('id', $accountIds)
->update(['pro_plan_paid' => $proPlanPaid]);
}
}
public function associateAccounts($userId1, $userId2) {
$record = self::findUserAccounts($userId1, $userId2);
if ($record) {
foreach ([$userId1, $userId2] as $userId) {
if (!$record->hasUserId($userId)) {
$record->setUserId($userId);
}
}
} else {
$record = new UserAccount();
$record->user_id1 = $userId1;
$record->user_id2 = $userId2;
}
$record->save();
$users = self::prepareUsersData($record);
self::syncUserAccounts($users);
return $users;
}
public function unlinkAccount($userAccountId, $userId) {
$userAccount = UserAccount::whereId($userAccountId)->first();
if ($userAccount->hasUserId(Auth::user()->id)) {
$userAccount->removeUserId($userId);
$userAccount->save();
}
}
}

View File

@ -44,6 +44,10 @@ class AppServiceProvider extends ServiceProvider {
$str .= '<li class="divider"></li>
<li><a href="'.URL::to('quotes').'">'.trans("texts.quotes").'</a></li>
<li><a href="'.URL::to('quotes/create').'">'.trans("texts.new_quote").'</a></li>';
} else if ($type == ENTITY_CLIENT) {
$str .= '<li class="divider"></li>
<li><a href="'.URL::to('credits').'">'.trans("texts.credits").'</a></li>
<li><a href="'.URL::to('credits/create').'">'.trans("texts.new_credit").'</a></li>';
}
$str .= '</ul>

View File

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MultiCompanySupport extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_accounts', function($table)
{
$table->increments('id');
$table->unsignedInteger('user_id1')->nullable();
$table->unsignedInteger('user_id2')->nullable();
$table->unsignedInteger('user_id3')->nullable();
$table->unsignedInteger('user_id4')->nullable();
$table->unsignedInteger('user_id5')->nullable();
$table->foreign('user_id1')->references('id')->on('users');
$table->foreign('user_id2')->references('id')->on('users');
$table->foreign('user_id3')->references('id')->on('users');
$table->foreign('user_id4')->references('id')->on('users');
$table->foreign('user_id5')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_accounts');
}
}

15
public/css/built.css vendored
View File

@ -3345,3 +3345,18 @@ button .glyphicon {
width: 35px;
margin-top: 20px;
}
ul.user-accounts div.account {
font-size: large;
}
ul.user-accounts div.remove {
padding-top: 14px;
color: #BBB;
visibility: hidden;
}
ul.user-accounts a:hover div.remove {
visibility: visible;
}

15
public/css/style.css vendored
View File

@ -961,3 +961,18 @@ button .glyphicon {
width: 35px;
margin-top: 20px;
}
ul.user-accounts div.account {
font-size: large;
}
ul.user-accounts div.remove {
padding-top: 14px;
color: #BBB;
visibility: hidden;
}
ul.user-accounts a:hover div.remove {
visibility: visible;
}

View File

@ -696,6 +696,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',

View File

@ -687,6 +687,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -696,5 +696,12 @@ return array(
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -666,6 +666,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -695,6 +695,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -687,6 +687,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -688,5 +688,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -690,6 +690,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -697,6 +697,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -695,6 +695,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -690,6 +690,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -690,6 +690,15 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -693,6 +693,16 @@ return array(
'timezone_unset' => 'Please :link to set your timezone',
'click_here' => 'click here',
'email_receipt' => 'Email payment receipt to the client',
'created_payment_emailed_client' => 'Successfully created payment and emailed client',
'add_account' => 'Add Account',
'untitled' => 'Untitled',
'new_account' => 'New Account',
'associated_accounts' => 'Successfully linked accounts',
'unlinked_account' => 'Successfully unlinked accounts',
'login' => 'Login',
'or' => 'or',
);

View File

@ -79,7 +79,13 @@
{!! Former::hidden('remember')->raw() !!}
</p>
<p>{!! Button::success(trans('texts.lets_go'))->large()->submit()->block() !!}</p>
<p>{!! Button::success(trans(Utils::allowNewAccounts() ? 'texts.login' : 'texts.lets_go'))->large()->submit()->block() !!}</p>
@if (Utils::allowNewAccounts())
<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>
@endif
<p class="link">
{!! link_to('/forgot', trans('texts.forgot_password')) !!}

View File

@ -186,6 +186,13 @@
});
}
function unlinkAccount(userAccountId, userId) {
if (confirm('{!! trans("texts.are_you_sure") !!}')) {
window.location = '{{ URL::to('/unlink_account') }}' + '/' + userAccountId + '/' + userId;
}
return false;
}
function wordWrapText(value, width)
{
@if (Auth::user()->account->auto_wrap)
@ -321,7 +328,6 @@
{!! HTML::menu_link('task') !!}
{!! HTML::menu_link('invoice') !!}
{!! HTML::menu_link('payment') !!}
{!! HTML::menu_link('credit') !!}
</ul>
<div class="navbar-form navbar-right">
@ -333,61 +339,67 @@
@endif
@endif
@if (Auth::user()->getPopOverText() && !Utils::isRegistered())
<button id="ninjaPopOver" type="button" class="btn btn-default" data-toggle="popover" data-placement="bottom" data-content="{{ Auth::user()->getPopOverText() }}" data-html="true" style="display:none">
{{ trans('texts.sign_up') }}
</button>
@endif
@if (Auth::user()->getPopOverText())
<script>
$(function() {
if (screen.width < 1170) return;
$('#ninjaPopOver').show().popover('show').hide();
$('body').click(function() {
$('#ninjaPopOver').popover('hide');
});
});
</script>
@endif
<div class="btn-group">
<div class="btn-group user-dropdown">
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
<div id="myAccountButton" class="ellipsis" style="max-width:100px">
{{ Auth::user()->getDisplayName() }}
@if (session(SESSION_USER_ACCOUNTS) && count(session(SESSION_USER_ACCOUNTS)))
{{ Auth::user()->account->getDisplayName() }}
@else
{{ Auth::user()->getDisplayName() }}
@endif
<span class="caret"></span>
</div>
</button>
<ul class="dropdown-menu" role="menu">
<ul class="dropdown-menu user-accounts" role="menu">
@if (session(SESSION_USER_ACCOUNTS))
@foreach (session(SESSION_USER_ACCOUNTS) as $item)
<li><a href='{{ URL::to("/switch_account/{$item->user_id}") }}'>
@if ($item->user_id == Auth::user()->id)
<b>
@endif
@if (count(session(SESSION_USER_ACCOUNTS)) > 1)
<div class="pull-right glyphicon glyphicon-remove remove" onclick="return unlinkAccount({{ $item->id }}, {{ $item->user_id }})"></div>
@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
@else
<li><a href='#'><b>
<div class="account">{{ Auth::user()->account->name ?: trans('texts.untitled') }}</div>
<div class="user">{{ Auth::user()->getDisplayName() }}</div>
</b></a></li>
@endif
<li class="divider"></li>
@if (Auth::user()->isPro() && (!session(SESSION_USER_ACCOUNTS) || count(session(SESSION_USER_ACCOUNTS)) < 5))
<li>{!! link_to('/login', trans('texts.add_account')) !!}</li>
@endif
<li>{!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}</li>
</ul>
</div>
</div>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<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_settings') }}">{!! uctrans('texts.advanced_settings') . Utils::getProLabel(ACCOUNT_ADVANCED_SETTINGS) !!}</a></li>
<li class="divider"></li>
<li>{!! link_to('#', trans('texts.logout'), array('onclick'=>'logout()')) !!}</li>
</ul>
</div>
</li>
</ul>
@if (Auth::user()->getPopOverText() && Utils::isRegistered())
<button id="ninjaPopOver" type="button" class="btn btn-default" data-toggle="popover" data-placement="bottom" data-content="{{ Auth::user()->getPopOverText() }}" data-html="true" style="display:none">
{{ Auth::user()->getDisplayName() }}
</button>
@endif
</div>
<form class="navbar-form navbar-right" role="search">
<div class="form-group">
<input type="text" id="search" style="width: {{ Session::get(SESSION_LOCALE) == 'en' ? 180 : 140 }}px"
class="form-control" placeholder="{{ trans('texts.search') }}">
</div>
</form>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
@ -404,6 +416,15 @@
</ul>
</li>
</ul>
<form class="navbar-form navbar-right" role="search">
<div class="form-group">
<input type="text" id="search" style="width: {{ Session::get(SESSION_LOCALE) == 'en' ? 180 : 140 }}px"
class="form-control" placeholder="{{ trans('texts.search') }}">
</div>
</form>
</div><!-- /.navbar-collapse -->

View File

@ -27,6 +27,8 @@
<input id="tableFilter" type="text" style="width:140px;margin-right:17px;background-color: white !important" class="form-control pull-left" placeholder="{{ trans('texts.filter') }}"/>
@if (Auth::user()->isPro() && $entityType == ENTITY_INVOICE)
{!! Button::normal(trans('texts.quotes'))->asLinkTo(URL::to('/quotes'))->appendIcon(Icon::create('list')) !!}
@elseif ($entityType == ENTITY_CLIENT)
{!! Button::normal(trans('texts.credits'))->asLinkTo(URL::to('/credits'))->appendIcon(Icon::create('list')) !!}
@endif
{!! Button::primary(trans("texts.new_$entityType"))->asLinkTo(URL::to("/{$entityType}s/create"))->appendIcon(Icon::create('plus-sign')) !!}
</div>