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

Fixed money format in PDF for EU

This commit is contained in:
Hillel Coren 2015-09-25 12:57:40 +03:00
parent 6b063abe9a
commit 4268c18f8a
30 changed files with 279 additions and 111 deletions

View File

@ -1,34 +1,51 @@
<?php namespace App\Console;
<?php namespace app\Console;
use Utils;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel {
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
'App\Console\Commands\SendRecurringInvoices',
'App\Console\Commands\CreateRandomData',
'App\Console\Commands\ResetData',
'App\Console\Commands\CheckData',
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
'App\Console\Commands\SendRecurringInvoices',
'App\Console\Commands\CreateRandomData',
'App\Console\Commands\ResetData',
'App\Console\Commands\CheckData',
'App\Console\Commands\SendRenewalInvoices',
'App\Console\Commands\SendReminders',
];
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$logFile = storage_path() . '/logs/cron.log';
$schedule
->command('ninja:send-invoices --force')
->sendOutputTo($logFile)
->withoutOverlapping()
->hourly();
$schedule
->command('ninja:send-reminders --force')
->sendOutputTo($logFile)
->daily();
if (Utils::isNinja()) {
$schedule
->command('ninja:send-renewals --force')
->sendOutputTo($logFile)
->daily();
}
}
}

View File

@ -0,0 +1,21 @@
<?php namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
class UserSignedUp extends Event {
use SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{
//
}
}

View File

@ -27,11 +27,13 @@ class Handler extends ExceptionHandler {
*/
public function report(Exception $e)
{
Utils::logError(Utils::getErrorString($e));
return false;
//return parent::report($e);
}
if (Utils::isNinja()) {
Utils::logError(Utils::getErrorString($e));
return false;
} else {
return parent::report($e);
}
}
/**
* Render an exception into an HTTP response.
@ -41,8 +43,7 @@ class Handler extends ExceptionHandler {
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
{
if ($e instanceof ModelNotFoundException) {
return Redirect::to('/');
}

View File

@ -40,6 +40,7 @@ use App\Models\InvoiceDesign;
use App\Ninja\Repositories\AccountRepository;
use App\Ninja\Mailers\UserMailer;
use App\Ninja\Mailers\ContactMailer;
use App\Events\UserSignedUp;
use App\Events\UserLoggedIn;
use App\Events\UserSettingsChanged;
@ -109,7 +110,8 @@ class AccountController extends BaseController
}
Auth::login($user, true);
Event::fire(new UserLoggedIn());
event(new UserSignedUp());
event(new UserLoggedIn());
$redirectTo = Input::get('redirect_to', 'invoices/create');
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
@ -151,7 +153,7 @@ class AccountController extends BaseController
public function showSection($section = ACCOUNT_DETAILS, $subSection = false)
{
if ($section == ACCOUNT_DETAILS) {
$primaryUser = Auth::user()->account->getPrimaryUser();
$primaryUser = Auth::user()->account->users()->orderBy('id')->first();
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'countries' => Cache::get('countries'),
@ -721,6 +723,7 @@ class AccountController extends BaseController
$account->save();
if (Auth::user()->id === $user->id) {
$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'));
@ -837,11 +840,10 @@ class AccountController extends BaseController
public function doRegister()
{
$affiliate = Affiliate::where('affiliate_key', '=', SELF_HOST_AFFILIATE_KEY)->first();
$email = trim(Input::get('email'));
if (!$email || $email == 'user@example.com') {
return '';
if (!$email || $email == TEST_USERNAME) {
return RESULT_FAILURE;
}
$license = new License();
@ -855,7 +857,7 @@ class AccountController extends BaseController
$license->is_claimed = 1;
$license->save();
return '';
return RESULT_SUCCESS;
}
public function cancelAccount()

View File

@ -90,7 +90,8 @@ class AppController extends BaseController
"MAIL_HOST={$mail['host']}\n".
"MAIL_USERNAME={$mail['username']}\n".
"MAIL_FROM_NAME={$mail['from']['name']}\n".
"MAIL_PASSWORD={$mail['password']}";
"MAIL_PASSWORD={$mail['password']}\n\n".
"PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address'";
// Write Config Settings
$fp = fopen(base_path()."/.env", 'w');

View File

@ -12,7 +12,6 @@ use DB;
use Event;
use URL;
use Datatable;
use finfo;
use Request;
use DropdownButton;
use App\Models\Invoice;

View File

@ -216,6 +216,14 @@ class TaskController extends BaseController
return self::bulk();
}
if ($validator = $this->taskRepo->getErrors(Input::all())) {
$url = $publicId ? 'tasks/'.$publicId.'/edit' : 'tasks/create';
Session::flash('error', trans('texts.task_errors'));
return Redirect::to($url)
->withErrors($validator)
->withInput();
}
$task = $this->taskRepo->save($publicId, Input::all());
Session::flash('message', trans($publicId ? 'texts.updated_task' : 'texts.created_task'));

View File

@ -26,10 +26,8 @@ class StartupCheck
public function handle($request, Closure $next)
{
// Ensure all request are over HTTPS in production
if (App::environment() == ENV_PRODUCTION) {
if (!Request::secure()) {
return Redirect::secure(Request::getRequestUri());
}
if (App::environment() == ENV_PRODUCTION && !Request::secure()) {
return Redirect::secure(Request::getRequestUri());
}
// If the database doens't yet exist we'll skip the rest
@ -37,7 +35,19 @@ class StartupCheck
return $next($request);
}
// check the application is up to date and for any news feed messages
// Check if a new version was installed
if (!Utils::isNinja()) {
$file = storage_path() . '/version.txt';
$version = @file_get_contents($file);
if ($version != NINJA_VERSION) {
$handle = fopen($file, 'w');
fwrite($handle, NINJA_VERSION);
fclose($handle);
return Redirect::to('/update');
}
}
// Check the application is up to date and for any news feed messages
if (Auth::check()) {
$count = Session::get(SESSION_COUNTER, 0);
Session::put(SESSION_COUNTER, ++$count);
@ -160,8 +170,8 @@ class StartupCheck
}
}
}
// Show message to IE 8 and before users
if (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(?i)msie [2-8]/', $_SERVER['HTTP_USER_AGENT'])) {
Session::flash('error', trans('texts.old_browser'));
}

View File

@ -391,6 +391,7 @@ if (!defined('CONTACT_EMAIL')) {
define('OUTDATE_BROWSER_URL', 'http://browsehappy.com/');
define('PDFMAKE_DOCS', 'http://pdfmake.org/playground.html');
define('PHANTOMJS_CLOUD', 'http://api.phantomjscloud.com/single/browser/v1/');
define('GITHUB_RELEASES', 'https://github.com/hillelcoren/invoice-ninja/releases');
define('REFERRAL_PROGRAM_URL', false);
define('COUNT_FREE_DESIGNS', 4);
@ -460,7 +461,6 @@ if (!defined('CONTACT_EMAIL')) {
}
}
/*
// Log all SQL queries to laravel.log
Event::listen('illuminate.query', function($query, $bindings, $time, $name)
{
@ -485,7 +485,7 @@ Event::listen('illuminate.query', function($query, $bindings, $time, $name)
Log::info($query, $data);
});
*/
/*
if (Auth::check() && Auth::user()->id === 1)

View File

@ -5,6 +5,7 @@ use Auth;
use Carbon;
use Session;
use App\Events\UserLoggedIn;
use App\Events\UserSignedUp;
use App\Ninja\Repositories\AccountRepository;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;
@ -33,8 +34,8 @@ class HandleUserLoggedIn {
{
$account = Auth::user()->account;
if (!Utils::isNinja() && Auth::user()->id == 1 && empty($account->last_login)) {
$this->accountRepo->registerUser(Auth::user());
if (empty($account->last_login)) {
event(new UserSignedUp());
}
$account->last_login = Carbon::now()->toDateTimeString();

View File

@ -0,0 +1,37 @@
<?php namespace App\Listeners;
use Utils;
use Auth;
use App\Events\UserSignedUp;
use App\Ninja\Repositories\AccountRepository;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;
class HandleUserSignedUp {
protected $accountRepo;
/**
* Create the event handler.
*
* @return void
*/
public function __construct(AccountRepository $accountRepo)
{
$this->accountRepo = $accountRepo;
}
/**
* Handle the event.
*
* @param UserSignedUp $event
* @return void
*/
public function handle(UserSignedUp $event)
{
if (!Utils::isNinjaProd()) {
$this->accountRepo->registerUser(Auth::user());
}
}
}

View File

@ -25,13 +25,6 @@ class Account extends Eloquent
return $this->hasMany('App\Models\User');
}
public function getPrimaryUser()
{
return $this->hasMany('App\Models\User')
->whereRaw('public_id = 0 OR public_id IS NULL')
->first();
}
public function clients()
{
return $this->hasMany('App\Models\Client');

View File

@ -21,7 +21,7 @@ class Invoice extends EntityModel
public function user()
{
return $this->belongsTo('App\Models\User');
return $this->belongsTo('App\Models\User')->withTrashed();
}
public function client()

View File

@ -5,4 +5,9 @@ use Eloquent;
class Language extends Eloquent
{
public $timestamps = false;
public function getName()
{
return $this->name;
}
}

View File

@ -5,6 +5,7 @@ use Auth;
use Event;
use App\Libraries\Utils;
use App\Events\UserSettingsChanged;
use App\Events\UserSignedUp;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
@ -35,7 +36,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*
* @var array
*/
protected $hidden = ['password', 'remember_token'];
protected $hidden = ['password', 'remember_token', 'confirmation_code'];
use SoftDeletes;
protected $dates = ['deleted_at'];
@ -203,20 +204,30 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
}
}
public static function updateUser($user)
public static function onUpdatingUser($user)
{
if ($user->password != !$user->getOriginal('password')) {
if ($user->password != $user->getOriginal('password')) {
$user->failed_logins = 0;
}
}
public static function onUpdatedUser($user)
{
if (!$user->getOriginal('email')
|| $user->getOriginal('email') == TEST_USERNAME
|| $user->getOriginal('username') == TEST_USERNAME) {
event(new UserSignedUp());
}
event(new UserSettingsChanged());
}
}
User::updating(function ($user) {
User::updateUser($user);
User::onUpdatingUser($user);
});
User::updated(function ($user) {
Event::fire(new UserSettingsChanged());
});
User::onUpdatedUser($user);
});

View File

@ -38,7 +38,7 @@ class ContactMailer extends Mailer
} else {
$user = $invitation->user;
if ($invitation->user->trashed()) {
$user = $account->getPrimaryUser();
$user = $account->users()->orderBy('id')->first();
}
}

View File

@ -233,7 +233,11 @@ class AccountRepository
public function registerUser($user)
{
$url = (Utils::isNinjaDev() ? '' : NINJA_APP_URL) . '/signup/register';
if ($user->email == TEST_USERNAME) {
return false;
}
$url = (Utils::isNinjaDev() ? SITE_URL : NINJA_APP_URL) . '/signup/register';
$data = '';
$fields = [
'first_name' => urlencode($user->first_name),
@ -250,6 +254,7 @@ class AccountRepository
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($fields));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
curl_close($ch);
}

View File

@ -45,8 +45,22 @@ class TaskRepository
return $query;
}
public function getErrors($input)
{
$rules = [
'time_log' => 'time_log',
];
$validator = \Validator::make($input, $rules);
if ($validator->fails()) {
return $validator;
}
return false;
}
public function save($publicId, $data)
{
{
if ($publicId) {
$task = Task::scope($publicId)->firstOrFail();
} else {

View File

@ -116,6 +116,26 @@ class AppServiceProvider extends ServiceProvider {
return $credit >= $amount;
});
// check that the time log elements don't overlap
Validator::extend('time_log', function($attribute, $value, $parameters) {
$lastTime = 0;
$value = json_decode($value);
array_multisort($value);
foreach ($value as $timeLog) {
list($startTime, $endTime) = $timeLog;
if (!$endTime) {
continue;
}
if ($startTime < $lastTime || $startTime > $endTime) {
return false;
}
if ($endTime < min($startTime, $lastTime)) {
return false;
}
$lastTime = max($lastTime, $endTime);
}
return true;
});
Validator::extend('less_than', function($attribute, $value, $parameters) {
return floatval($value) <= floatval($parameters[0]);

View File

@ -11,6 +11,9 @@ class EventServiceProvider extends ServiceProvider {
* @var array
*/
protected $listen = [
'App\Events\UserSignedUp' => [
'App\Listeners\HandleUserSignedUp',
],
'App\Events\UserLoggedIn' => [
'App\Listeners\HandleUserLoggedIn',
],

View File

@ -29,7 +29,7 @@ return [
|
*/
'lifetime' => env('SESSION_LIFETIME', 120),
'lifetime' => env('SESSION_LIFETIME', 1),
'expire_on_close' => false,

View File

@ -14,7 +14,7 @@ class SupportTokenBilling extends Migration {
{
Schema::table('accounts', function($table)
{
$table->smallInteger('token_billing_type_id')->default(TOKEN_BILLING_OPT_IN);
$table->smallInteger('token_billing_type_id')->default(TOKEN_BILLING_ALWAYS);
});
Schema::create('account_gateway_tokens', function($table)
@ -35,7 +35,7 @@ class SupportTokenBilling extends Migration {
$table->foreign('client_id')->references('id')->on('clients')->onDelete('cascade');
});
DB::table('accounts')->update(['token_billing_type_id' => TOKEN_BILLING_OPT_IN]);
DB::table('accounts')->update(['token_billing_type_id' => TOKEN_BILLING_ALWAYS]);
}
/**

View File

@ -70,27 +70,27 @@ class PaymentLibrariesSeeder extends Seeder
$currencies = [
['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => 'SGD ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => 'VND ', 'precision' => '0', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => 'CHF ', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => '.'],
['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => 'VND ', 'precision' => '0', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => 'CHF ', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => ','],
['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'Thai baht', 'code' => 'THB', 'symbol' => 'THB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => 'NGN ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','],
['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'],
];
@ -98,6 +98,8 @@ class PaymentLibrariesSeeder extends Seeder
$record = Currency::whereCode($currency['code'])->first();
if ($record) {
$record->name = $currency['name'];
$record->thousand_separator = $currency['thousand_separator'];
$record->decimal_separator = $currency['decimal_separator'];
$record->save();
} else {
Currency::create($currency);

View File

@ -2,6 +2,7 @@
use App\Models\User;
use App\Models\Account;
use App\Models\Affiliate;
class UserTableSeeder extends Seeder
{
@ -26,6 +27,11 @@ class UserTableSeeder extends Seeder
'registered' => true,
'confirmed' => true,
]);
Affiliate::create([
'affiliate_key' => SELF_HOST_AFFILIATE_KEY
]);
}
}

View File

@ -31834,7 +31834,7 @@ NINJA.invoiceLines = function(invoice) {
}
// show at most one blank line
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
if (shownItem && (!cost || cost == '0.00' || cost == '0,00') && !notes && !productKey) {
continue;
}

View File

@ -278,7 +278,7 @@ NINJA.invoiceLines = function(invoice) {
}
// show at most one blank line
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
if (shownItem && (!cost || cost == '0.00' || cost == '0,00') && !notes && !productKey) {
continue;
}

View File

@ -76,7 +76,9 @@
@endif
@if ($gateway->id == GATEWAY_STRIPE)
{!! Former::select('token_billing_type_id')->options($tokenBillingOptions)->help(trans('texts.token_billing_help')) !!}
{!! Former::select('token_billing_type_id')
->options($tokenBillingOptions)
->help(trans('texts.token_billing_help')) !!}
@endif
</div>

View File

@ -637,7 +637,8 @@
@if (!Utils::isNinjaProd())
<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> |
{{ trans('texts.powered_by') }} <a href="https://www.invoiceninja.com/?utm_source=powered_by" target="_blank">InvoiceNinja.com</a> -
{!! link_to(GITHUB_RELEASES, 'v' . NINJA_VERSION, ['target' => '_blank']) !!} |
@if (Auth::user()->account->isWhiteLabel())
{{ trans('texts.white_labeled') }}
@else

View File

@ -1847,7 +1847,7 @@
}
@if ($data)
window.model = new ViewModel({!! $data !!});
window.model = new ViewModel({!! $data !!});
@else
window.model = new ViewModel();
model.addTaxRate();

View File

@ -180,15 +180,7 @@
if (!timeLog.isEmpty()) {
data.push([timeLog.startTime(),timeLog.endTime()]);
}
@if ($task && !$task->is_running)
if (!timeLog.isStartValid() || !timeLog.isEndValid()) {
alert("{!! trans('texts.task_errors') !!}");
showTimeDetails();
return;
}
@endif
}
}
$('#invoice_id').val(invoice_id);
$('#time_log').val(JSON.stringify(data));
$('#action').val(action);
@ -279,6 +271,15 @@
};
}
function loadTimeLog(data) {
model.time_log.removeAll();
data = JSON.parse(data);
for (var i=0; i<data.length; i++) {
model.time_log.push(new TimeModel(data[i]));
}
model.time_log.push(new TimeModel());
}
function ViewModel(data) {
var self = this;
self.time_log = ko.observableArray();
@ -287,31 +288,36 @@
data = JSON.parse(data.time_log);
for (var i=0; i<data.length; i++) {
self.time_log.push(new TimeModel(data[i]));
}
}
}
self.time_log.push(new TimeModel());
self.removeItem = function(item) {
self.time_log.remove(item);
self.refresh();
self.removeItem = function(item) {
self.time_log.remove(item);
self.refresh();
}
self.refresh = function() {
var hasEmpty = false;
var lastTime = 0;
self.time_log.sort(function(left, right) {
if (left.isEmpty() || right.isEmpty()) {
return -1;
for (var i=0; i<self.time_log().length; i++) {
var timeLog = self.time_log()[i];
if (timeLog.isEmpty()) {
hasEmpty = true;
}
return left.startTime() - right.startTime();
});
}
if (!hasEmpty) {
self.addItem();
}
}
self.showTimeOverlaps = function() {
var lastTime = 0;
for (var i=0; i<self.time_log().length; i++) {
var timeLog = self.time_log()[i];
var startValid = true;
var endValid = true;
if (timeLog.isEmpty()) {
hasEmpty = true;
} else {
if (!timeLog.isEmpty()) {
if (timeLog.startTime() < lastTime || timeLog.startTime() > timeLog.endTime()) {
startValid = false;
}
@ -323,9 +329,6 @@
timeLog.isStartValid(startValid);
timeLog.isEndValid(endValid);
}
if (!hasEmpty) {
self.addItem();
}
}
self.addItem = function() {
@ -360,7 +363,7 @@
if (val == 'timer') {
$('#datetime-details').hide();
} else {
$('#datetime-details').fadeIn();
$('#datetime-details').fadeIn();
}
$('#start-button').toggle();
$('#save-button').toggle();
@ -384,6 +387,12 @@
tock({{ $duration }});
@endif
@endif
@if (Session::has('error'))
loadTimeLog({!! json_encode(Input::old('time_log')) !!});
model.showTimeOverlaps();
showTimeDetails();
@endif
});
</script>