Merge branch 'release/3.4.1'

This commit is contained in:
James Cole
2015-05-25 22:24:28 +02:00
77 changed files with 1485 additions and 932 deletions

View File

@@ -1,3 +1,3 @@
src_dir: . src_dir: .
coverage_clover: storage/coverage/clover.xml coverage_clover: build/logs/clover.xml
json_path: storage/coverage/coveralls-upload.json json_path: build/logs/coveralls-upload.json

22
.jshintrc Normal file
View File

@@ -0,0 +1,22 @@
{
"undef": true,
"unused": false,
"strict": true,
"browser": true,
"jquery": true,
"devel": true,
"globals": [
"language",
"token",
"currencyCode",
"$",
"token",
"accountID",
"billID",
"currentMonthName",
"previousMonthName",
"nextMonthName",
"everything",
"moment"
]
}

View File

@@ -6,10 +6,6 @@ php:
- 5.5 - 5.5
- 5.6 - 5.6
addons:
code_climate:
repo_token: 26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61
install: install:
- composer update - composer update
- php artisan env - php artisan env
@@ -20,3 +16,5 @@ script:
after_script: after_script:
- php vendor/bin/coveralls - php vendor/bin/coveralls
- CODECLIMATE_REPO_TOKEN=26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61 ./vendor/bin/test-reporter --stdout > codeclimate.json
- "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports"

View File

@@ -1,5 +1,5 @@
# Firefly III # Firefly III
#### v3.4.0.10 #### 3.4.1
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii) [![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii)
[![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii) [![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii)

View File

@@ -5,9 +5,11 @@ namespace FireflyIII\Helpers\Reminders;
use Amount; use Amount;
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use Config;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder; use FireflyIII\Models\Reminder;
use Navigation; use Navigation;
use Preferences;
/** /**
* Class ReminderHelper * Class ReminderHelper
@@ -154,14 +156,21 @@ class ReminderHelper implements ReminderHelperInterface
$piggyBank = $reminder->remindersable; $piggyBank = $reminder->remindersable;
if (is_null($piggyBank)) { if (is_null($piggyBank)) {
return 'Piggy bank no longer exists.'; return trans('firefly.piggy_bank_not_exists');
} }
if (is_null($piggyBank->targetdate)) { if (is_null($piggyBank->targetdate)) {
return 'Add money to this piggy bank to reach your target of ' . Amount::format($piggyBank->targetamount); return trans('firefly.add_any_amount_to_piggy', ['amount' => Amount::format($piggyBank->targetamount)]);
} }
return 'Add ' . Amount::format($reminder->metadata->perReminder) . ' to fill this piggy bank on ' . $piggyBank->targetdate->format('jS F Y'); $lang = Preferences::get('language', 'en')->data;
return trans(
'firefly.add_set_amount_to_piggy',
[
'amount' => Amount::format($reminder->metadata->perReminder),
'date' => $piggyBank->targetdate->formatLocalized(Config::get('firefly.monthAndDay.' . $lang))
]
);
} }
} }

View File

@@ -46,6 +46,8 @@ class AccountController extends Controller
Session::put('accounts.create.url', URL::previous()); Session::put('accounts.create.url', URL::previous());
} }
Session::forget('accounts.create.fromStore'); Session::forget('accounts.create.fromStore');
Session::flash('gaEventCategory', 'accounts');
Session::flash('gaEventAction', 'create-' . $what);
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle')); return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
@@ -63,6 +65,8 @@ class AccountController extends Controller
// put previous url in session // put previous url in session
Session::put('accounts.delete.url', URL::previous()); Session::put('accounts.delete.url', URL::previous());
Session::flash('gaEventCategory', 'accounts');
Session::flash('gaEventAction', 'delete-' . $typeName);
return view('accounts.delete', compact('account', 'subTitle')); return view('accounts.delete', compact('account', 'subTitle'));
} }
@@ -126,6 +130,8 @@ class AccountController extends Controller
'virtualBalance' => floatval($account->virtual_balance) 'virtualBalance' => floatval($account->virtual_balance)
]; ];
Session::flash('preFilled', $preFilled); Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'accounts');
Session::flash('gaEventAction', 'edit-' . $what);
return view('accounts.edit', compact('account', 'subTitle', 'subTitleIcon', 'openingBalance', 'what')); return view('accounts.edit', compact('account', 'subTitle', 'subTitleIcon', 'openingBalance', 'what'));
} }

View File

@@ -43,6 +43,8 @@ class BillController extends Controller
Session::put('bills.create.url', URL::previous()); Session::put('bills.create.url', URL::previous());
} }
Session::forget('bills.create.fromStore'); Session::forget('bills.create.fromStore');
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'create');
$subTitle = 'Create new bill'; $subTitle = 'Create new bill';
return view('bills.create', compact('periods', 'subTitle')); return view('bills.create', compact('periods', 'subTitle'));
@@ -57,7 +59,9 @@ class BillController extends Controller
{ {
// put previous url in session // put previous url in session
Session::put('bills.delete.url', URL::previous()); Session::put('bills.delete.url', URL::previous());
$subTitle = 'Delete "' . e($bill->name) . '"'; Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'delete');
$subTitle = trans('firefly.delete_bill', ['name' => $bill->name]);
return view('bills.delete', compact('bill', 'subTitle')); return view('bills.delete', compact('bill', 'subTitle'));
} }
@@ -93,6 +97,8 @@ class BillController extends Controller
Session::put('bills.edit.url', URL::previous()); Session::put('bills.edit.url', URL::previous());
} }
Session::forget('bills.edit.fromUpdate'); Session::forget('bills.edit.fromUpdate');
Session::flash('gaEventCategory', 'bills');
Session::flash('gaEventAction', 'edit');
return view('bills.edit', compact('subTitle', 'periods', 'bill')); return view('bills.edit', compact('subTitle', 'periods', 'bill'));
} }

View File

@@ -1,5 +1,6 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth; use Auth;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Requests; use FireflyIII\Http\Requests;
@@ -45,6 +46,9 @@ class BudgetController extends Controller
$amount = intval(Input::get('amount')); $amount = intval(Input::get('amount'));
$date = Session::get('start', Carbon::now()->startOfMonth()); $date = Session::get('start', Carbon::now()->startOfMonth());
$limitRepetition = $repository->updateLimitAmount($budget, $date, $amount); $limitRepetition = $repository->updateLimitAmount($budget, $date, $amount);
if ($amount == 0) {
$limitRepetition = null;
}
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]); return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]);
@@ -60,6 +64,8 @@ class BudgetController extends Controller
Session::put('budgets.create.url', URL::previous()); Session::put('budgets.create.url', URL::previous());
} }
Session::forget('budgets.create.fromStore'); Session::forget('budgets.create.fromStore');
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'create');
$subTitle = trans('firefly.create_new_budget'); $subTitle = trans('firefly.create_new_budget');
return view('budgets.create', compact('subTitle')); return view('budgets.create', compact('subTitle'));
@@ -72,10 +78,12 @@ class BudgetController extends Controller
*/ */
public function delete(Budget $budget) public function delete(Budget $budget)
{ {
$subTitle = 'Delete budget' . e($budget->name) . '"'; $subTitle = trans('firefly.delete_budget', ['name' => $budget->name]);
// put previous url in session // put previous url in session
Session::put('budgets.delete.url', URL::previous()); Session::put('budgets.delete.url', URL::previous());
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'delete');
return view('budgets.delete', compact('budget', 'subTitle')); return view('budgets.delete', compact('budget', 'subTitle'));
} }
@@ -95,6 +103,7 @@ class BudgetController extends Controller
Session::flash('success', 'The budget "' . e($name) . '" was deleted.'); Session::flash('success', 'The budget "' . e($name) . '" was deleted.');
return Redirect::to(Session::get('budgets.delete.url')); return Redirect::to(Session::get('budgets.delete.url'));
} }
@@ -112,6 +121,8 @@ class BudgetController extends Controller
Session::put('budgets.edit.url', URL::previous()); Session::put('budgets.edit.url', URL::previous());
} }
Session::forget('budgets.edit.fromUpdate'); Session::forget('budgets.edit.fromUpdate');
Session::flash('gaEventCategory', 'budgets');
Session::flash('gaEventAction', 'edit');
return view('budgets.edit', compact('budget', 'subTitle')); return view('budgets.edit', compact('budget', 'subTitle'));
@@ -126,7 +137,9 @@ class BudgetController extends Controller
{ {
$budgets = $repository->getActiveBudgets(); $budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets(); $inactive = $repository->getInactiveBudgets();
$spent = '0';
$budgeted = '0';
bcscale(2);
/** /**
* Do some cleanup: * Do some cleanup:
*/ */
@@ -134,24 +147,27 @@ class BudgetController extends Controller
// loop the budgets: // loop the budgets:
$budgets->each( /** @var Budget $budget */
function (Budget $budget) use ($repository) { foreach ($budgets as $budget) {
$date = Session::get('start', Carbon::now()->startOfMonth()); $date = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
$budget->spent = $repository->spentInPeriodCorrected($budget, $date, $end); $budget->spent = $repository->spentInPeriodCorrected($budget, $date, $end);
$budget->currentRep = $repository->getCurrentRepetition($budget, $date); $budget->currentRep = $repository->getCurrentRepetition($budget, $date);
if ($budget->currentRep) {
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
}
$spent = bcadd($spent, $budget->spent);
} }
);
$dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); $dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$spent = $budgets->sum('spent'); $budgetIncomeTotal = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data;
$amount = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data; $budgetMaximum = Preferences::get('budgetMaximum', 1000)->data;
$overspent = $spent > $amount; $defaultCurrency = Amount::getDefaultCurrency();
$spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
return view('budgets.index', compact('budgetMaximum', 'inactive', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount')); return view(
'budgets.index', compact('budgetMaximum', 'budgetIncomeTotal', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
);
} }
/** /**
@@ -164,7 +180,10 @@ class BudgetController extends Controller
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->startOfMonth()); $end = Session::get('end', Carbon::now()->startOfMonth());
$list = $repository->getWithoutBudget($start, $end); $list = $repository->getWithoutBudget($start, $end);
$subTitle = 'Transactions without a budget between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y'); $subTitle = trans(
'firefly.without_budget_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
return view('budgets.noBudget', compact('list', 'subTitle')); return view('budgets.noBudget', compact('list', 'subTitle'));
} }
@@ -198,7 +217,11 @@ class BudgetController extends Controller
$journals = $repository->getJournals($budget, $repetition); $journals = $repository->getJournals($budget, $repetition);
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget); $limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget);
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); $subTitle = !is_null($repetition->id)
?
trans('firefly.budget_in_month', ['name' => $budget->name, 'month' => $repetition->startdate->formatLocalized($this->monthFormat)])
:
e($budget->name);
$journals->setPath('/budgets/show/' . $budget->id); $journals->setPath('/budgets/show/' . $budget->id);
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle')); return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));

View File

@@ -40,6 +40,8 @@ class CategoryController extends Controller
Session::put('categories.create.url', URL::previous()); Session::put('categories.create.url', URL::previous());
} }
Session::forget('categories.create.fromStore'); Session::forget('categories.create.fromStore');
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'create');
$subTitle = 'Create a new category'; $subTitle = 'Create a new category';
return view('categories.create', compact('subTitle')); return view('categories.create', compact('subTitle'));
@@ -52,10 +54,12 @@ class CategoryController extends Controller
*/ */
public function delete(Category $category) public function delete(Category $category)
{ {
$subTitle = 'Delete category "' . e($category->name) . '"'; $subTitle = trans('firefly.delete_category', ['name' => $category->name]);
// put previous url in session // put previous url in session
Session::put('categories.delete.url', URL::previous()); Session::put('categories.delete.url', URL::previous());
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'delete');
return view('categories.delete', compact('category', 'subTitle')); return view('categories.delete', compact('category', 'subTitle'));
} }
@@ -91,6 +95,8 @@ class CategoryController extends Controller
Session::put('categories.edit.url', URL::previous()); Session::put('categories.edit.url', URL::previous());
} }
Session::forget('categories.edit.fromUpdate'); Session::forget('categories.edit.fromUpdate');
Session::flash('gaEventCategory', 'categories');
Session::flash('gaEventAction', 'edit');
return view('categories.edit', compact('category', 'subTitle')); return view('categories.edit', compact('category', 'subTitle'));

View File

@@ -45,6 +45,8 @@ class CurrencyController extends Controller
Session::put('currency.create.url', URL::previous()); Session::put('currency.create.url', URL::previous());
} }
Session::forget('currency.create.fromStore'); Session::forget('currency.create.fromStore');
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'create');
return view('currency.create', compact('subTitleIcon', 'subTitle')); return view('currency.create', compact('subTitleIcon', 'subTitle'));
} }
@@ -84,6 +86,8 @@ class CurrencyController extends Controller
// put previous url in session // put previous url in session
Session::put('currency.delete.url', URL::previous()); Session::put('currency.delete.url', URL::previous());
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'delete');
return view('currency.delete', compact('currency')); return view('currency.delete', compact('currency'));
@@ -127,6 +131,8 @@ class CurrencyController extends Controller
Session::put('currency.edit.url', URL::previous()); Session::put('currency.edit.url', URL::previous());
} }
Session::forget('currency.edit.fromUpdate'); Session::forget('currency.edit.fromUpdate');
Session::flash('gaEventCategory', 'currency');
Session::flash('gaEventAction', 'edit');
return view('currency.edit', compact('currency', 'subTitle', 'subTitleIcon')); return view('currency.edit', compact('currency', 'subTitle', 'subTitleIcon'));

View File

@@ -72,6 +72,8 @@ class PiggyBankController extends Controller
Session::put('piggy-banks.create.url', URL::previous()); Session::put('piggy-banks.create.url', URL::previous());
} }
Session::forget('piggy-banks.create.fromStore'); Session::forget('piggy-banks.create.fromStore');
Session::flash('gaEventCategory', 'piggy-banks');
Session::flash('gaEventAction', 'create');
return view('piggy-banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon')); return view('piggy-banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon'));
} }
@@ -83,10 +85,12 @@ class PiggyBankController extends Controller
*/ */
public function delete(PiggyBank $piggyBank) public function delete(PiggyBank $piggyBank)
{ {
$subTitle = 'Delete "' . e($piggyBank->name) . '"'; $subTitle = trans('firefly.delete_piggy_bank', ['name' => $piggyBank->name]);
// put previous url in session // put previous url in session
Session::put('piggy-banks.delete.url', URL::previous()); Session::put('piggy-banks.delete.url', URL::previous());
Session::flash('gaEventCategory', 'piggy-banks');
Session::flash('gaEventAction', 'delete');
return view('piggy-banks.delete', compact('piggyBank', 'subTitle')); return view('piggy-banks.delete', compact('piggyBank', 'subTitle'));
} }
@@ -118,7 +122,7 @@ class PiggyBankController extends Controller
$periods = Config::get('firefly.piggy_bank_periods'); $periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); $accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"'; $subTitle = trans('firefly.update_piggy_title', ['name' => $piggyBank->name]);
$subTitleIcon = 'fa-pencil'; $subTitleIcon = 'fa-pencil';
/* /*
@@ -138,6 +142,8 @@ class PiggyBankController extends Controller
'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false 'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false
]; ];
Session::flash('preFilled', $preFilled); Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'piggy-banks');
Session::flash('gaEventAction', 'edit');
// put previous url in session if not redirect from store (not "return_to_edit"). // put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('piggy-banks.edit.fromUpdate') !== true) { if (Session::get('piggy-banks.edit.fromUpdate') !== true) {

View File

@@ -109,6 +109,8 @@ class ProfileController extends Controller
// DELETE! // DELETE!
Auth::user()->delete(); Auth::user()->delete();
Session::flush(); Session::flush();
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'delete-account');
return Redirect::route('index'); return Redirect::route('index');
} }

View File

@@ -90,6 +90,10 @@ class ReportController extends Controller
$balance = $this->helper->getBalanceReport($start, $end, $shared); $balance = $this->helper->getBalanceReport($start, $end, $shared);
$bills = $this->helper->getBillReport($start, $end, $shared); $bills = $this->helper->getBillReport($start, $end, $shared);
Session::flash('gaEventCategory', 'report');
Session::flash('gaEventAction', 'month');
Session::flash('gaEventLabel', $start->format('F Y'));
return view( return view(
'reports.month', 'reports.month',
@@ -133,6 +137,10 @@ class ReportController extends Controller
$incomes = $this->helper->getIncomeReport($start, $end, $shared); $incomes = $this->helper->getIncomeReport($start, $end, $shared);
$expenses = $this->helper->getExpenseReport($start, $end, $shared); $expenses = $this->helper->getExpenseReport($start, $end, $shared);
Session::flash('gaEventCategory', 'report');
Session::flash('gaEventAction', 'year');
Session::flash('gaEventLabel', $start->format('Y'));
return view( return view(
'reports.year', 'reports.year',

View File

@@ -31,6 +31,9 @@ use View;
*/ */
class TagController extends Controller class TagController extends Controller
{ {
public $tagOptions = [];
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
*/ */
@@ -40,12 +43,12 @@ class TagController extends Controller
View::share('title', 'Tags'); View::share('title', 'Tags');
View::share('mainTitleIcon', 'fa-tags'); View::share('mainTitleIcon', 'fa-tags');
View::share('hideTags', true); View::share('hideTags', true);
$tagOptions = [ $this->tagOptions = [
'nothing' => 'Just a regular tag.', 'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.', 'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.', 'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
]; ];
View::share('tagOptions', $tagOptions); View::share('tagOptions', $this->tagOptions);
} }
/** /**
@@ -67,6 +70,8 @@ class TagController extends Controller
Session::put('tags.create.url', URL::previous()); Session::put('tags.create.url', URL::previous());
} }
Session::forget('tags.create.fromStore'); Session::forget('tags.create.fromStore');
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'create');
return view('tags.create', compact('subTitle', 'subTitleIcon')); return view('tags.create', compact('subTitle', 'subTitleIcon'));
} }
@@ -78,10 +83,12 @@ class TagController extends Controller
*/ */
public function delete(Tag $tag) public function delete(Tag $tag)
{ {
$subTitle = 'Delete "' . e($tag->tag) . '"'; $subTitle = trans('firefly.delete_tag', ['name' => $tag->tag]);
// put previous url in session // put previous url in session
Session::put('tags.delete.url', URL::previous()); Session::put('tags.delete.url', URL::previous());
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'delete');
return view('tags.delete', compact('tag', 'subTitle')); return view('tags.delete', compact('tag', 'subTitle'));
} }
@@ -108,7 +115,7 @@ class TagController extends Controller
* *
* @return View * @return View
*/ */
public function edit(Tag $tag) public function edit(Tag $tag, TagRepositoryInterface $repository)
{ {
$subTitle = 'Edit tag "' . e($tag->tag) . '"'; $subTitle = 'Edit tag "' . e($tag->tag) . '"';
$subTitleIcon = 'fa-tag'; $subTitleIcon = 'fa-tag';
@@ -116,67 +123,16 @@ class TagController extends Controller
/* /*
* Default tag options (again) * Default tag options (again)
*/ */
$tagOptions = [ $tagOptions = $this->tagOptions;
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
/* /*
* Can this tag become another type? * Can this tag become another type?
*/ */
$allowToAdvancePayment = true; $allowAdvance = $repository->tagAllowAdvance($tag);
$allowToBalancingAct = true; $allowToBalancingAct = $repository->tagAllowBalancing($tag);
/*
* If this tag is a balancing act, and it contains transfers, it cannot be
* changes to an advancePayment.
*/
if ($tag->tagMode == 'balancingAct' || $tag->tagMode == 'nothing') {
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Transfer') {
$allowToAdvancePayment = false;
}
}
}
/*
* If this tag contains more than one expenses, it cannot become an advance payment.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Withdrawal') {
$count++;
}
}
if ($count > 1) {
$allowToAdvancePayment = false;
}
/*
* If has more than two transactions already, cannot become a balancing act:
*/
if ($tag->transactionjournals->count() > 2) {
$allowToBalancingAct = false;
}
/*
* If any transaction is a deposit, cannot become a balancing act.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Deposit') {
$count++;
}
}
if ($count > 0) {
$allowToBalancingAct = false;
}
// edit tag options: // edit tag options:
if ($allowToAdvancePayment === false) { if ($allowAdvance === false) {
unset($tagOptions['advancePayment']); unset($tagOptions['advancePayment']);
} }
if ($allowToBalancingAct === false) { if ($allowToBalancingAct === false) {
@@ -189,6 +145,8 @@ class TagController extends Controller
Session::put('tags.edit.url', URL::previous()); Session::put('tags.edit.url', URL::previous());
} }
Session::forget('tags.edit.fromUpdate'); Session::forget('tags.edit.fromUpdate');
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'edit');
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions')); return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions'));
} }

View File

@@ -62,6 +62,8 @@ class TransactionController extends Controller
Session::put('transactions.create.url', URL::previous()); Session::put('transactions.create.url', URL::previous());
} }
Session::forget('transactions.create.fromStore'); Session::forget('transactions.create.fromStore');
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'create-' . $what);
asort($piggies); asort($piggies);
@@ -79,10 +81,12 @@ class TransactionController extends Controller
public function delete(TransactionJournal $journal) public function delete(TransactionJournal $journal)
{ {
$type = strtolower($journal->transactionType->type); $type = strtolower($journal->transactionType->type);
$subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"'; $subTitle = trans('firefly.delete_' . $type, ['description' => $journal->description]);
// put previous url in session // put previous url in session
Session::put('transactions.delete.url', URL::previous()); Session::put('transactions.delete.url', URL::previous());
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'delete-' . $type);
return view('transactions.delete', compact('journal', 'subTitle')); return view('transactions.delete', compact('journal', 'subTitle'));
@@ -158,6 +162,8 @@ class TransactionController extends Controller
$preFilled['account_to_id'] = $transactions[0]->account->id; $preFilled['account_to_id'] = $transactions[0]->account->id;
Session::flash('preFilled', $preFilled); Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'edit-' . $what);
// put previous url in session if not redirect from store (not "return_to_edit"). // put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('transactions.edit.fromUpdate') !== true) { if (Session::get('transactions.edit.fromUpdate') !== true) {

View File

@@ -6,7 +6,7 @@ use Config;
use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Preferences; use Preferences;
use Carbon\Carbon;
/** /**
* Class Authenticate * Class Authenticate
* *
@@ -54,6 +54,7 @@ class Authenticate
// if logged in, set user language: // if logged in, set user language:
$pref = Preferences::get('language', 'en'); $pref = Preferences::get('language', 'en');
App::setLocale($pref->data); App::setLocale($pref->data);
Carbon::setLocale($pref->data);
setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data)); setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data));

View File

@@ -4,12 +4,8 @@ use Closure;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Models\Reminder; use FireflyIII\Models\Reminder;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
@@ -56,16 +52,34 @@ class Cleanup
public function handle(Request $request, Closure $next) public function handle(Request $request, Closure $next)
{ {
if ($this->auth->guest()) { if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401); return response('Unauthorized.', 401);
} else {
return redirect()->guest('auth/login');
} }
} $count = -1;
$run = env('RUNCLEANUP') == 'true' ? true : false;
$count = 0;
if ($run) { bcscale(0);
if (env('RUNCLEANUP') == 'true') {
$count = 0;
$count = bcadd($count, $this->encryptAccountAndBills());
$count = bcadd($count, $this->encryptBudgetsAndCategories());
$count = bcadd($count, $this->encryptPiggiesAndJournals());
$count = bcadd($count, $this->encryptRemindersAndPreferences());
}
if ($count == 0) {
Session::flash('warning', 'Please open the .env file and change RUNCLEANUP=true to RUNCLEANUP=false');
}
return $next($request);
}
/**
* @return int
*/
protected function encryptAccountAndBills()
{
$count = 0;
// encrypt account name // encrypt account name
$set = Account::where('encrypted', 0)->take(5)->get(); $set = Account::where('encrypted', 0)->take(5)->get();
/** @var Account $entry */ /** @var Account $entry */
@@ -98,6 +112,17 @@ class Cleanup
} }
unset($set, $entry, $match); unset($set, $entry, $match);
return $count;
}
/**
* @return int
*/
protected function encryptBudgetsAndCategories()
{
$count = 0;
// encrypt budget name // encrypt budget name
$set = Budget::where('encrypted', 0)->take(5)->get(); $set = Budget::where('encrypted', 0)->take(5)->get();
/** @var Budget $entry */ /** @var Budget $entry */
@@ -120,6 +145,15 @@ class Cleanup
} }
unset($set, $entry, $name); unset($set, $entry, $name);
return $count;
}
/**
* @return int
*/
protected function encryptPiggiesAndJournals()
{
$count = 0;
// encrypt piggy bank name // encrypt piggy bank name
$set = PiggyBank::where('encrypted', 0)->take(5)->get(); $set = PiggyBank::where('encrypted', 0)->take(5)->get();
/** @var PiggyBank $entry */ /** @var PiggyBank $entry */
@@ -142,6 +176,15 @@ class Cleanup
} }
unset($set, $entry, $description); unset($set, $entry, $description);
return $count;
}
/**
* @return int
*/
protected function encryptRemindersAndPreferences()
{
$count = 0;
// encrypt reminder metadata // encrypt reminder metadata
$set = Reminder::where('encrypted', 0)->take(5)->get(); $set = Reminder::where('encrypted', 0)->take(5)->get();
/** @var Reminder $entry */ /** @var Reminder $entry */
@@ -175,12 +218,7 @@ class Cleanup
} }
unset($set, $entry, $data); unset($set, $entry, $data);
} return $count;
if ($count == 0 && $run) {
Session::flash('warning', 'Please open the .env file and change RUNCLEANUP=true to RUNCLEANUP=false');
}
return $next($request);
} }
} }

View File

@@ -6,6 +6,8 @@ use Illuminate\Support\ServiceProvider;
* Class AppServiceProvider * Class AppServiceProvider
* *
* @package FireflyIII\Providers * @package FireflyIII\Providers
*
* @codeCoverageIgnore
*/ */
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {

View File

@@ -6,6 +6,8 @@ use Illuminate\Support\ServiceProvider;
/** /**
* Class BusServiceProvider * Class BusServiceProvider
* *
* @codeCoverageIgnore
*
* @package FireflyIII\Providers * @package FireflyIII\Providers
*/ */
class BusServiceProvider extends ServiceProvider class BusServiceProvider extends ServiceProvider

View File

@@ -6,6 +6,8 @@ use Illuminate\Support\ServiceProvider;
* Class ConfigServiceProvider * Class ConfigServiceProvider
* *
* @package FireflyIII\Providers * @package FireflyIII\Providers
* @codeCoverageIgnore
*
*/ */
class ConfigServiceProvider extends ServiceProvider class ConfigServiceProvider extends ServiceProvider
{ {
@@ -23,232 +25,7 @@ class ConfigServiceProvider extends ServiceProvider
*/ */
public function register() public function register()
{ {
config(
[
'twigbridge' => [
'twig' => [
/*
|--------------------------------------------------------------------------
| Extension
|--------------------------------------------------------------------------
|
| File extension for Twig view files.
|
*/
'extension' => 'twig',
/*
|--------------------------------------------------------------------------
| Accepts all Twig environment configuration options
|--------------------------------------------------------------------------
|
| http://twig.sensiolabs.org/doc/api.html#environment-options
|
*/
'environment' => [
// When set to true, the generated templates have a __toString() method
// that you can use to display the generated nodes.
// default: false
'debug' => config('app.debug', false),
// The charset used by the templates.
// default: utf-8
'charset' => 'utf-8',
// The base template class to use for generated templates.
// default: TwigBridge\Twig\Template
'base_template_class' => 'TwigBridge\Twig\Template',
// An absolute path where to store the compiled templates, or false to disable caching. If null
// then the cache file path is used.
// default: cache file storage path
'cache' => null,
// When developing with Twig, it's useful to recompile the template
// whenever the source code changes. If you don't provide a value
// for the auto_reload option, it will be determined automatically based on the debug value.
'auto_reload' => true,
// If set to false, Twig will silently ignore invalid variables
// (variables and or attributes/methods that do not exist) and
// replace them with a null value. When set to true, Twig throws an exception instead.
// default: false
'strict_variables' => false,
// If set to true, auto-escaping will be enabled by default for all templates.
// default: true
'autoescape' => true,
// A flag that indicates which optimizations to apply
// (default to -1 -- all optimizations are enabled; set it to 0 to disable)
'optimizations' => -1,
],
/*
|--------------------------------------------------------------------------
| Global variables
|--------------------------------------------------------------------------
|
| These will always be passed in and can be accessed as Twig variables.
| NOTE: these will be overwritten if you pass data into the view with the same key.
|
*/
'globals' => [],
],
'extensions' => [
/*
|--------------------------------------------------------------------------
| Extensions
|--------------------------------------------------------------------------
|
| Enabled extensions.
|
| `Twig_Extension_Debug` is enabled automatically if twig.debug is TRUE.
|
*/
'enabled' => [
'TwigBridge\Extension\Loader\Facades',
'TwigBridge\Extension\Loader\Filters',
'TwigBridge\Extension\Loader\Functions',
'TwigBridge\Extension\Laravel\Auth',
'TwigBridge\Extension\Laravel\Config',
'TwigBridge\Extension\Laravel\Dump',
'TwigBridge\Extension\Laravel\Input',
'TwigBridge\Extension\Laravel\Session',
'TwigBridge\Extension\Laravel\String',
'TwigBridge\Extension\Laravel\Translator',
'TwigBridge\Extension\Laravel\Url',
// 'TwigBridge\Extension\Laravel\Form',
// 'TwigBridge\Extension\Laravel\Html',
// 'TwigBridge\Extension\Laravel\Legacy\Facades',
],
/*
|--------------------------------------------------------------------------
| Facades
|--------------------------------------------------------------------------
|
| Available facades. Access like `{{ Config.get('foo.bar') }}`.
|
| Each facade can take an optional array of options. To mark the whole facade
| as safe you can set the option `'is_safe' => true`. Setting the facade as
| safe means that any HTML returned will not be escaped.
|
| It is advisable to not set the whole facade as safe and instead mark the
| each appropriate method as safe for security reasons. You can do that with
| the following syntax:
|
| <code>
| 'Form' => [
| 'is_safe' => [
| 'open'
| ]
| ]
| </code>
|
| The values of the `is_safe` array must match the called method on the facade
| in order to be marked as safe.
|
*/
'facades' => [
'Breadcrumbs' => [
'is_safe' => [
'renderIfExists'
]
],
'Session',
'Route',
'Auth',
'Lang',
'URL',
'Config',
'ExpandedForm' => [
'is_safe' => [
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
'multiRadio'
]
],
'Form' => [
'is_safe' => [
'input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea'
]
],
],
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| Available functions. Access like `{{ secure_url(...) }}`.
|
| Each function can take an optional array of options. These options are
| passed directly to `Twig_SimpleFunction`.
|
| So for example, to mark a function as safe you can do the following:
|
| <code>
| 'link_to' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| function differently in your Twig templates than what it's actually called.
|
| <code>
| 'link' => [
| 'callback' => 'link_to'
| ]
| </code>
|
*/
'functions' => [
'elixir',
'head',
'last',
'old'
],
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Available filters. Access like `{{ variable|filter }}`.
|
| Each filter can take an optional array of options. These options are
| passed directly to `Twig_SimpleFilter`.
|
| So for example, to mark a filter as safe you can do the following:
|
| <code>
| 'studly_case' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| filter differently in your Twig templates than what is actually called.
|
| <code>
| 'snake' => [
| 'callback' => 'snake_case'
| ]
| </code>
|
*/
'filters' => [],
],
]
]
);
} }
} }

View File

@@ -23,6 +23,7 @@ use Validator;
* Class FireflyServiceProvider * Class FireflyServiceProvider
* *
* @package FireflyIII\Providers * @package FireflyIII\Providers
* @codeCoverageIgnore
*/ */
class FireflyServiceProvider extends ServiceProvider class FireflyServiceProvider extends ServiceProvider
{ {

View File

@@ -7,6 +7,7 @@ use Illuminate\Routing\Router;
* Class RouteServiceProvider * Class RouteServiceProvider
* *
* @package FireflyIII\Providers * @package FireflyIII\Providers
* @codeCoverageIgnore
*/ */
class RouteServiceProvider extends ServiceProvider class RouteServiceProvider extends ServiceProvider
{ {

View File

@@ -8,6 +8,7 @@ use Illuminate\Support\ServiceProvider;
/** /**
* Class TestingServiceProvider * Class TestingServiceProvider
* *
* @codeCoverageIgnore
* @package FireflyIII\Providers * @package FireflyIII\Providers
*/ */
class TestingServiceProvider extends ServiceProvider class TestingServiceProvider extends ServiceProvider

View File

@@ -13,18 +13,6 @@ use Illuminate\Support\Collection;
interface PiggyBankRepositoryInterface interface PiggyBankRepositoryInterface
{ {
/**
* @return Collection
*/
public function getPiggyBanks();
/**
* @param PiggyBank $piggyBank
*
* @return Collection
*/
public function getEvents(PiggyBank $piggyBank);
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* @param $amount * @param $amount
@@ -33,6 +21,13 @@ interface PiggyBankRepositoryInterface
*/ */
public function createEvent(PiggyBank $piggyBank, $amount); public function createEvent(PiggyBank $piggyBank, $amount);
/**
* @param PiggyBank $piggyBank
*
* @return bool
*/
public function destroy(PiggyBank $piggyBank);
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
@@ -43,9 +38,14 @@ interface PiggyBankRepositoryInterface
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return bool * @return Collection
*/ */
public function destroy(PiggyBank $piggyBank); public function getEvents(PiggyBank $piggyBank);
/**
* @return Collection
*/
public function getPiggyBanks();
/** /**
* Set all piggy banks to order 0. * Set all piggy banks to order 0.

View File

@@ -143,6 +143,79 @@ class TagRepository implements TagRepositoryInterface
} }
/**
* Can a tag become an advance payment?
*
* @param Tag $tag
*
* @return bool
*/
public function tagAllowAdvance(Tag $tag)
{
/*
* If this tag is a balancing act, and it contains transfers, it cannot be
* changes to an advancePayment.
*/
if ($tag->tagMode == 'balancingAct' || $tag->tagMode == 'nothing') {
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Transfer') {
return false;
}
}
}
/*
* If this tag contains more than one expenses, it cannot become an advance payment.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Withdrawal') {
$count++;
}
}
if ($count > 1) {
return false;
}
return true;
}
/**
* Can a tag become a balancing act?
*
* @param Tag $tag
*
* @return bool
*/
public function tagAllowBalancing(Tag $tag)
{
/*
* If has more than two transactions already, cannot become a balancing act:
*/
if ($tag->transactionjournals->count() > 2) {
return false;
}
/*
* If any transaction is a deposit, cannot become a balancing act.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Deposit') {
$count++;
}
}
if ($count > 0) {
return false;
}
return true;
}
/** /**
* @param Tag $tag * @param Tag $tag
* @param array $data * @param array $data

View File

@@ -18,6 +18,14 @@ interface TagRepositoryInterface
{ {
/**
* @param TransactionJournal $journal
* @param Tag $tag
*
* @return boolean
*/
public function connect(TransactionJournal $journal, Tag $tag);
/** /**
* This method scans the transaction journals from or to the given asset account * This method scans the transaction journals from or to the given asset account
* and checks if these are part of a balancing act. If so, it will sum up the amounts * and checks if these are part of a balancing act. If so, it will sum up the amounts
@@ -34,6 +42,18 @@ interface TagRepositoryInterface
*/ */
public function coveredByBalancingActs(Account $account, Carbon $start, Carbon $end); public function coveredByBalancingActs(Account $account, Carbon $start, Carbon $end);
/**
* @param Tag $tag
*
* @return boolean
*/
public function destroy(Tag $tag);
/**
* @return Collection
*/
public function get();
/** /**
* @param array $data * @param array $data
* *
@@ -42,9 +62,22 @@ interface TagRepositoryInterface
public function store(array $data); public function store(array $data);
/** /**
* @return Collection * Can a tag become an advance payment?
*
* @param Tag $tag
*
* @return bool
*/ */
public function get(); public function tagAllowAdvance(Tag $tag);
/**
* Can a tag become a balancing act?
*
* @param Tag $tag
*
* @return bool
*/
public function tagAllowBalancing(Tag $tag);
/** /**
* @param Tag $tag * @param Tag $tag
@@ -53,19 +86,4 @@ interface TagRepositoryInterface
* @return Tag * @return Tag
*/ */
public function update(Tag $tag, array $data); public function update(Tag $tag, array $data);
/**
* @param Tag $tag
*
* @return boolean
*/
public function destroy(Tag $tag);
/**
* @param TransactionJournal $journal
* @param Tag $tag
*
* @return boolean
*/
public function connect(TransactionJournal $journal, Tag $tag);
} }

View File

@@ -232,7 +232,7 @@ class ExpandedForm
$fields = ['title', 'name', 'description']; $fields = ['title', 'name', 'description'];
/** @var Eloquent $entry */ /** @var Eloquent $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$id = intval($entry->id); $entryId = intval($entry->id);
$title = null; $title = null;
foreach ($fields as $field) { foreach ($fields as $field) {
@@ -240,7 +240,7 @@ class ExpandedForm
$title = $entry->$field; $title = $entry->$field;
} }
} }
$selectList[$id] = $title; $selectList[$entryId] = $title;
} }
return $selectList; return $selectList;

View File

@@ -261,18 +261,20 @@ class Navigation
public function periodShow(Carbon $date, $repeatFrequency) public function periodShow(Carbon $date, $repeatFrequency)
{ {
$formatMap = [ $formatMap = [
'daily' => 'j F Y', 'daily' => '%e %B %Y',
'week' => '\W\e\e\k W, Y', 'week' => 'Week %W, %Y',
'weekly' => '\W\e\e\k W, Y', 'weekly' => 'Week %W, %Y',
'quarter' => 'F Y', 'quarter' => '%B %Y',
'month' => 'F Y', 'month' => '%B %Y',
'monthly' => 'F Y', 'monthly' => '%B %Y',
'year' => 'Y', 'year' => '%Y',
'yearly' => 'Y', 'yearly' => '%Y',
]; ];
if (isset($formatMap[$repeatFrequency])) { if (isset($formatMap[$repeatFrequency])) {
return $date->format($formatMap[$repeatFrequency]); return $date->formatLocalized($formatMap[$repeatFrequency]);
} }
throw new FireflyException('No date formats for frequency "' . $repeatFrequency . '"!'); throw new FireflyException('No date formats for frequency "' . $repeatFrequency . '"!');
} }

2
build/logs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.xml
*.json

View File

@@ -37,7 +37,9 @@
"phpspec/phpspec": "~2.1", "phpspec/phpspec": "~2.1",
"satooshi/php-coveralls": "0.6.1", "satooshi/php-coveralls": "0.6.1",
"mockery/mockery": "0.9.*", "mockery/mockery": "0.9.*",
"league/factory-muffin": "~2.1" "league/factory-muffin": "~2.1",
"codeclimate/php-test-reporter": "^0.1.2"
}, },

59
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"hash": "e3e90dd365b74f4878cf3b5b4a1c4007", "hash": "5c085b2cc90ffa610e386897066315a7",
"packages": [ "packages": [
{ {
"name": "classpreloader/classpreloader", "name": "classpreloader/classpreloader",
@@ -2689,6 +2689,63 @@
], ],
"time": "2015-03-17 08:00:28" "time": "2015-03-17 08:00:28"
}, },
{
"name": "codeclimate/php-test-reporter",
"version": "v0.1.2",
"source": {
"type": "git",
"url": "https://github.com/codeclimate/php-test-reporter.git",
"reference": "8ed24ff30f3663ecf40f1c12d6c97eb56c69e646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/codeclimate/php-test-reporter/zipball/8ed24ff30f3663ecf40f1c12d6c97eb56c69e646",
"reference": "8ed24ff30f3663ecf40f1c12d6c97eb56c69e646",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3",
"satooshi/php-coveralls": "0.6.*",
"symfony/console": ">=2.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*@stable"
},
"bin": [
"composer/bin/test-reporter"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.1.x-dev"
}
},
"autoload": {
"psr-0": {
"CodeClimate\\Component": "src/",
"CodeClimate\\Bundle": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Code Climate",
"email": "hello@codeclimate.com",
"homepage": "https://codeclimate.com"
}
],
"description": "PHP client for reporting test coverage to Code Climate",
"homepage": "https://github.com/codeclimate/php-test-reporter",
"keywords": [
"codeclimate",
"coverage"
],
"time": "2014-07-23 13:42:41"
},
{ {
"name": "doctrine/instantiator", "name": "doctrine/instantiator",
"version": "1.0.4", "version": "1.0.4",

223
config/twigbridge.php Normal file
View File

@@ -0,0 +1,223 @@
<?php
return [
'twig' => [
/*
|--------------------------------------------------------------------------
| Extension
|--------------------------------------------------------------------------
|
| File extension for Twig view files.
|
*/
'extension' => 'twig',
/*
|--------------------------------------------------------------------------
| Accepts all Twig environment configuration options
|--------------------------------------------------------------------------
|
| http://twig.sensiolabs.org/doc/api.html#environment-options
|
*/
'environment' => [
// When set to true, the generated templates have a __toString() method
// that you can use to display the generated nodes.
// default: false
'debug' => config('app.debug', false),
// The charset used by the templates.
// default: utf-8
'charset' => 'utf-8',
// The base template class to use for generated templates.
// default: TwigBridge\Twig\Template
'base_template_class' => 'TwigBridge\Twig\Template',
// An absolute path where to store the compiled templates, or false to disable caching. If null
// then the cache file path is used.
// default: cache file storage path
'cache' => null,
// When developing with Twig, it's useful to recompile the template
// whenever the source code changes. If you don't provide a value
// for the auto_reload option, it will be determined automatically based on the debug value.
'auto_reload' => true,
// If set to false, Twig will silently ignore invalid variables
// (variables and or attributes/methods that do not exist) and
// replace them with a null value. When set to true, Twig throws an exception instead.
// default: false
'strict_variables' => false,
// If set to true, auto-escaping will be enabled by default for all templates.
// default: true
'autoescape' => true,
// A flag that indicates which optimizations to apply
// (default to -1 -- all optimizations are enabled; set it to 0 to disable)
'optimizations' => -1,
],
/*
|--------------------------------------------------------------------------
| Global variables
|--------------------------------------------------------------------------
|
| These will always be passed in and can be accessed as Twig variables.
| NOTE: these will be overwritten if you pass data into the view with the same key.
|
*/
'globals' => [],
],
'extensions' => [
/*
|--------------------------------------------------------------------------
| Extensions
|--------------------------------------------------------------------------
|
| Enabled extensions.
|
| `Twig_Extension_Debug` is enabled automatically if twig.debug is TRUE.
|
*/
'enabled' => [
'TwigBridge\Extension\Loader\Facades',
'TwigBridge\Extension\Loader\Filters',
'TwigBridge\Extension\Loader\Functions',
'TwigBridge\Extension\Laravel\Auth',
'TwigBridge\Extension\Laravel\Config',
'TwigBridge\Extension\Laravel\Dump',
'TwigBridge\Extension\Laravel\Input',
'TwigBridge\Extension\Laravel\Session',
'TwigBridge\Extension\Laravel\String',
'TwigBridge\Extension\Laravel\Translator',
'TwigBridge\Extension\Laravel\Url',
// 'TwigBridge\Extension\Laravel\Form',
// 'TwigBridge\Extension\Laravel\Html',
// 'TwigBridge\Extension\Laravel\Legacy\Facades',
],
/*
|--------------------------------------------------------------------------
| Facades
|--------------------------------------------------------------------------
|
| Available facades. Access like `{{ Config.get('foo.bar') }}`.
|
| Each facade can take an optional array of options. To mark the whole facade
| as safe you can set the option `'is_safe' => true`. Setting the facade as
| safe means that any HTML returned will not be escaped.
|
| It is advisable to not set the whole facade as safe and instead mark the
| each appropriate method as safe for security reasons. You can do that with
| the following syntax:
|
| <code>
| 'Form' => [
| 'is_safe' => [
| 'open'
| ]
| ]
| </code>
|
| The values of the `is_safe` array must match the called method on the facade
| in order to be marked as safe.
|
*/
'facades' => [
'Breadcrumbs' => [
'is_safe' => [
'renderIfExists'
]
],
'Session',
'Route',
'Auth',
'Lang',
'URL',
'Config',
'ExpandedForm' => [
'is_safe' => [
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
'multiRadio'
]
],
'Form' => [
'is_safe' => [
'input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea'
]
],
],
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| Available functions. Access like `{{ secure_url(...) }}`.
|
| Each function can take an optional array of options. These options are
| passed directly to `Twig_SimpleFunction`.
|
| So for example, to mark a function as safe you can do the following:
|
| <code>
| 'link_to' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| function differently in your Twig templates than what it's actually called.
|
| <code>
| 'link' => [
| 'callback' => 'link_to'
| ]
| </code>
|
*/
'functions' => [
'elixir',
'head',
'last',
'old'
],
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Available filters. Access like `{{ variable|filter }}`.
|
| Each filter can take an optional array of options. These options are
| passed directly to `Twig_SimpleFilter`.
|
| So for example, to mark a filter as safe you can do the following:
|
| <code>
| 'studly_case' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| filter differently in your Twig templates than what is actually called.
|
| <code>
| 'snake' => [
| 'callback' => 'snake_case'
| ]
| </code>
|
*/
'filters' => [],
]
];

View File

@@ -1,3 +1,4 @@
/* globals require */
var elixir = require('laravel-elixir'); var elixir = require('laravel-elixir');
/* /*
@@ -12,5 +13,6 @@ var elixir = require('laravel-elixir');
*/ */
elixir(function(mix) { elixir(function(mix) {
"use strict";
mix.less('app.less'); mix.less('app.less');
}); });

View File

@@ -22,7 +22,7 @@
<!-- code coverage --> <!-- code coverage -->
<logging> <logging>
<log type="coverage-clover" target="./storage/coverage/clover.xml" charset="UTF-8" /> <log type="coverage-clover" target="./build/logs/clover.xml" charset="UTF-8" />
</logging> </logging>
<php> <php>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,23 @@
$(function () { /* global $ */
// Return a helper with preserved width of cells
var fixHelper = function (e, ui) {
"use strict";
ui.children().each(function () {
$(this).width($(this).width());
});
return ui;
};
$(function () {
"use strict";
if (typeof(googleLineChart) === "function" && typeof accountID !== 'undefined') { if (typeof(googleLineChart) === "function" && typeof accountID !== 'undefined') {
googleLineChart('chart/account/' + accountID, 'overview-chart'); googleLineChart('chart/account/' + accountID, 'overview-chart');
} }
// sortable! // sortable!
if (typeof $(".sortable-table tbody").sortable != "undefined") { if (typeof $(".sortable-table tbody").sortable !== "undefined") {
$(".sortable-table tbody").sortable( $(".sortable-table tbody").sortable(
{ {
helper: fixHelper, helper: fixHelper,
@@ -19,23 +31,14 @@ $(function () {
}); });
// Return a helper with preserved width of cells
var fixHelper = function (e, ui) {
ui.children().each(function () {
$(this).width($(this).width());
});
return ui;
};
function sortStop(event, ui) { function sortStop(event, ui) {
"use strict";
var current = $(ui.item); var current = $(ui.item);
var thisDate = current.data('date'); var thisDate = current.data('date');
var originalBG = current.css('backgroundColor'); var originalBG = current.css('backgroundColor');
if (current.prev().data('date') != thisDate && current.next().data('date') != thisDate) { if (current.prev().data('date') !== thisDate && current.next().data('date') !== thisDate) {
//console.log('False!');
//console.log('[' + current.prev().data('date') + '] [' + thisDate + '] [' + current.next().data('date') + ']');
// animate something with color: // animate something with color:
current.animate({ current.animate({
backgroundColor: "#d9534f" backgroundColor: "#d9534f"
@@ -59,10 +62,6 @@ function sortStop(event, ui) {
// do extra animation when done? // do extra animation when done?
$.post('/transaction/reorder', {items: submit, date: thisDate, _token: token}); $.post('/transaction/reorder', {items: submit, date: thisDate, _token: token});
console.log(submit);
//console.log('TRUE!');
//console.log('[' + current.prev().data('date') + '] [' + thisDate + '] [' + current.next().data('date') + ']');
current.animate({ current.animate({
backgroundColor: "#5cb85c" backgroundColor: "#5cb85c"

View File

@@ -1,5 +1,7 @@
$(document).ready(function () { /* global googleComboChart, billID */
$(document).ready(function () {
"use strict";
if (typeof(googleComboChart) === 'function' && typeof(billID) !== 'undefined') { if (typeof(googleComboChart) === 'function' && typeof(billID) !== 'undefined') {
googleComboChart('chart/bill/' + billID, 'bill-overview'); googleComboChart('chart/bill/' + billID, 'bill-overview');
} }

View File

@@ -1,12 +1,104 @@
/* globals $, budgeted:false, currencySymbol, budgetIncomeTotal ,budgetedMuch, budgetedPercentage, token, budgetID, repetitionID, spent, budgeted*/
function drawSpentBar() {
"use strict";
var overspent = spent > budgeted;
var pct;
if (overspent) {
// draw overspent bar
pct = (budgeted / spent) * 100;
$('.spentBar .progress-bar-warning').css('width', pct + '%');
$('.spentBar .progress-bar-danger').css('width', (100 - pct) + '%');
} else {
// draw normal bar:
pct = (spent / budgeted) * 100;
$('.spentBar .progress-bar-info').css('width', pct + '%');
}
}
function drawBudgetedBar() {
"use strict";
var budgetedMuch = budgeted > budgetIncomeTotal;
// recalculate percentage:
var pct;
if (budgetedMuch) {
// budgeted too much.
pct = (budgetIncomeTotal / budgeted) * 100;
$('.budgetedBar .progress-bar-warning').css('width', pct + '%');
$('.budgetedBar .progress-bar-danger').css('width', (100 - pct) + '%');
$('.budgetedBar .progress-bar-info').css('width', 0);
} else {
pct = (budgeted / budgetIncomeTotal) * 100;
$('.budgetedBar .progress-bar-warning').css('width', 0);
$('.budgetedBar .progress-bar-danger').css('width', 0);
$('.budgetedBar .progress-bar-info').css('width', pct + '%');
}
$('#budgetedAmount').html(currencySymbol + ' ' + budgeted.toFixed(2));
}
function updateBudgetedAmounts(e) {
"use strict";
var target = $(e.target);
var id = target.data('id');
var value = target.val();
var original = target.data('original');
var difference = value - original;
if (difference !== 0) {
// add difference to 'budgeted' var
budgeted = budgeted + difference;
// update original:
target.data('original', value);
// run drawBudgetedBar() again:
drawBudgetedBar();
// send a post to Firefly to update the amount:
$.post('budgets/amount/' + id, {amount: value, _token: token}).success(function (data) {
// update the link if relevant:
if (data.repetition > 0) {
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id + '/' + data.repetition);
} else {
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id);
}
});
}
console.log('Budget id is ' + id);
console.log('Difference = ' + (value - original ));
}
$(function () { $(function () {
updateRanges(); "use strict";
//$('input[type="range"]').change(updateSingleRange);
$('input[type="range"]').on('input', updateSingleRange);
//$('input[type="number"]').on('change', updateSingleRange);
$('input[type="number"]').on('input', updateSingleRange);
$('.updateIncome').on('click', updateIncome); $('.updateIncome').on('click', updateIncome);
/*
On start, fill the "spent"-bar using the content from the page.
*/
drawSpentBar();
drawBudgetedBar();
/*
When the input changes, update the percentages for the budgeted bar:
*/
$('input[type="number"]').on('input', updateBudgetedAmounts);
//updateRanges();
//$('input[type="range"]').on('input', updateSingleRange);
//$('input[type="number"]').on('input', updateSingleRange);
/*
Draw the charts, if necessary:
*/
if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') { if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') {
googleColumnChart('chart/budget/' + budgetID, 'budgetOverview'); googleColumnChart('chart/budget/' + budgetID, 'budgetOverview');
} }
@@ -17,139 +109,138 @@ $(function () {
}); });
function updateSingleRange(e) { //function updateSingleRange(e) {
// get some values: // "use strict";
var input = $(e.target); // // get some values:
var id = input.data('id'); // var input = $(e.target);
var value = parseInt(input.val()); // var id = input.data('id');
var spent = parseFloat($('#spent-' + id).data('value')); // var value = parseInt(input.val());
// var spent = parseFloat($('#spent-' + id).data('value'));
// update small display: //
if (value > 0) { // // update small display:
// show the input: // if (value > 0) {
$('#budget-info-' + id + ' span').show(); // // show the input:
$('#budget-info-' + id + ' input').show(); // $('#budget-info-' + id + ' span').show();
// $('#budget-info-' + id + ' input').show();
// update the text: //
$('#budget-description-' + id).text('Budgeted: '); // // update the text:
} else { // $('#budget-description-' + id).text('Budgeted: ');
// hide the input: // } else {
$('#budget-info-' + id + ' span').hide(); // // hide the input:
$('#budget-info-' + id + ' input').hide(); // $('#budget-info-' + id + ' span').hide();
// $('#budget-info-' + id + ' input').hide();
// update the text: //
$('#budget-description-' + id).html('<em>No budget</em>'); // // update the text:
} // $('#budget-description-' + id).html('<em>No budget</em>');
// }
// update the range display text: //
$('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2)); // // update the range display text:
// $('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2));
// send a post to Firefly to update the amount: //
$.post('budgets/amount/' + id, {amount: value, _token: token}).success(function (data) { // // send a post to Firefly to update the amount:
// update the link if relevant: // $.post('budgets/amount/' + id, {amount: value, _token: token}).success(function (data) {
$('#budget-link-' + id).attr('href', 'budgets/show/' + id + '/' + data.repetition); // // update the link if relevant:
}); // $('#budget-link-' + id).attr('href', 'budgets/show/' + id + '/' + data.repetition);
if (input.attr('type') == 'number') { // });
// update the range-input: // if (input.attr('type') === 'number') {
$('#budget-range-' + id).val(value); // // update the range-input:
} else { // $('#budget-range-' + id).val(value);
// update the number-input: // } else {
$('#budget-info-' + id + ' input').val(value); // // update the number-input:
} // $('#budget-info-' + id + ' input').val(value);
// }
// update or hide the bar, whichever is necessary. //
updateTotal(); // // update or hide the bar, whichever is necessary.
return value; // updateTotal();
} // return value;
//}
function updateTotal() { //
var sum = 0; //function updateTotal() {
$('input[type="range"]').each(function (i, v) { // "use strict";
// get some values: // var sum = 0;
sum += parseInt($(v).val()); // $('input[type="range"]').each(function (i, v) {
}); // // get some values:
// sum += parseInt($(v).val());
/** // });
* Update total sum: //
*/ // /**
var totalAmount = parseInt($('#totalAmount').data('value')); // * Update total sum:
var pct; // */
if (sum <= totalAmount) { // var totalAmount = parseInt($('#totalAmount').data('value'));
pct = sum / totalAmount * 100; // var pct;
$('#progress-bar-default').css('width', pct + '%'); // if (sum <= totalAmount) {
$('#progress-bar-warning').css('width', '0'); // pct = sum / totalAmount * 100;
$('#progress-bar-danger').css('width', '0'); // $('#progress-bar-default').css('width', pct + '%');
$('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger'); // $('#progress-bar-warning').css('width', '0');
} else { // $('#progress-bar-danger').css('width', '0');
// we gaan er X overheen, // $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger');
// } else {
pct = totalAmount / sum * 100; // // we gaan er X overheen,
var danger = 100 - pct; //
var err = 100 - danger; // pct = totalAmount / sum * 100;
$('#progress-bar-default').css('width', 0); // var danger = 100 - pct;
$('#progress-bar-warning').css('width', err + '%'); // var err = 100 - danger;
$('#progress-bar-danger').css('width', danger + '%'); // $('#progress-bar-default').css('width', 0);
$('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-danger').removeClass('text-success'); // $('#progress-bar-warning').css('width', err + '%');
} // $('#progress-bar-danger').css('width', danger + '%');
// $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-danger').removeClass('text-success');
} // }
//
function updateIncome(e) { //}
//
function updateIncome() {
"use strict";
$('#monthlyBudgetModal').empty().load('budgets/income', function () { $('#monthlyBudgetModal').empty().load('budgets/income', function () {
$('#monthlyBudgetModal').modal('show'); $('#monthlyBudgetModal').modal('show');
}); });
return false; return false;
} }
//
function updateRanges() { //function updateRanges() {
/** // "use strict";
* Update all ranges. //
*/ //
var sum = 0; // var sum = 0;
$('input[type="range"]').each(function (i, v) { // $('input[type="range"]').each(function (i, v) {
// get some values: // // get some values:
var input = $(v); // var input = $(v);
var id = input.data('id'); // var id = input.data('id');
var value = parseInt(input.val()); // var value = parseInt(input.val());
//
// calculate sum: // // calculate sum:
sum += value; // sum += value;
//
// update small display: // // update small display:
$('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2)); // $('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2));
//
// update progress bar (if relevant) // // send a post to Firefly to update the amount:
var barHolder = $('#budget-progress-' + id); // $.post('budgets/amount/' + id, {amount: value, _token: token});
var spent = parseFloat(barHolder.data('spent')); //
// });
// send a post to Firefly to update the amount: //
$.post('budgets/amount/' + id, {amount: value, _token: token}).success(function (data) { // /**
}); // * Update total sum:
// */
}); // var totalAmount = parseInt($('#totalAmount').data('value'));
// var pct;
/** // if (sum <= totalAmount) {
* Update total sum: // pct = sum / totalAmount * 100;
*/ // $('#progress-bar-default').css('width', pct + '%');
var totalAmount = parseInt($('#totalAmount').data('value')); // $('#progress-bar-warning').css('width', '0');
if (sum <= totalAmount) { // $('#progress-bar-danger').css('width', '0');
var pct = sum / totalAmount * 100; // $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger');
$('#progress-bar-default').css('width', pct + '%'); // } else {
$('#progress-bar-warning').css('width', '0'); // // we gaan er X overheen,
$('#progress-bar-danger').css('width', '0'); //
$('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger'); // pct = totalAmount / sum * 100;
} else { // var danger = 100 - pct;
// we gaan er X overheen, // var err = 100 - danger;
// $('#progress-bar-default').css('width', 0);
var pct = totalAmount / sum * 100; // $('#progress-bar-warning').css('width', err + '%');
var danger = 100 - pct; // $('#progress-bar-danger').css('width', danger + '%');
var err = 100 - danger; // $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-danger').removeClass('text-success');
$('#progress-bar-default').css('width', 0); // }
$('#progress-bar-warning').css('width', err + '%'); //
$('#progress-bar-danger').css('width', danger + '%'); //
$('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-danger').removeClass('text-success'); //}
}
}

View File

@@ -1,5 +1,6 @@
/* globals $, categoryID */
$(function () { $(function () {
"use strict";
if (typeof categoryID !== 'undefined') { if (typeof categoryID !== 'undefined') {
googleColumnChart('chart/category/' + categoryID + '/all', 'all'); googleColumnChart('chart/category/' + categoryID + '/all', 'all');
googleColumnChart('chart/category/' + categoryID + '/month', 'month'); googleColumnChart('chart/category/' + categoryID + '/month', 'month');

View File

@@ -1,8 +1,9 @@
/* globals start, end, dateRangeURL, everything, firstDate, moment, currentMonthName, $, previousMonthName, nextMonthName, applyLabel, cancelLabel, toLabel, customRangeLabel, fromLabel, */
$(function () { $(function () {
"use strict";
$('.currencySelect').click(currencySelect); $('.currencySelect').click(currencySelect);
ranges = {}; var ranges = {};
ranges[currentMonthName] = [moment().startOf('month'), moment().endOf('month')]; ranges[currentMonthName] = [moment().startOf('month'), moment().endOf('month')];
ranges[previousMonthName] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]; ranges[previousMonthName] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
ranges[nextMonthName] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')]; ranges[nextMonthName] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')];
@@ -10,11 +11,6 @@ $(function () {
$('#daterange').daterangepicker( $('#daterange').daterangepicker(
{ {
//View::share('currentMonthName', $current);
//View::share('previousMonthName', $prev);
//View::share('nextMonthName', $next);
ranges: ranges, ranges: ranges,
opens: 'left', opens: 'left',
locale: { locale: {
@@ -54,6 +50,7 @@ $(function () {
}); });
function currencySelect(e) { function currencySelect(e) {
"use strict";
var target = $(e.target); var target = $(e.target);
var symbol = target.data('symbol'); var symbol = target.data('symbol');
var code = target.data('code'); var code = target.data('code');

View File

@@ -1,13 +1,16 @@
/* globals currencyCode, language, defaultPieChartOptions, defaultLineChartOptions, defaultColumnChartOptions, defaultBarChartOptions, defaultStackedColumnChartOptions, defaultComboChartOptions */
/* exported googleLineChart, googleBarChart, googleColumnChart, googleStackedColumnChart, googleComboChart, googlePieChart */
var google = google || {}; var google = google || {};
google.load('visualization', '1.1', {'packages': ['corechart', 'bar', 'line'],'language': language }); google.load('visualization', '1.1', {'packages': ['corechart', 'bar', 'line'],'language': language });
function googleChart(chartType, URL, container, options) { function googleChart(chartType, URL, container, options) {
"use strict";
if ($('#' + container).length === 1) { if ($('#' + container).length === 1) {
$.getJSON(URL).success(function (data) { $.getJSON(URL).success(function (data) {
/* /*
Get the data from the JSON Get the data from the JSON
*/ */
gdata = new google.visualization.DataTable(data); var gdata = new google.visualization.DataTable(data);
/* /*
Format as money Format as money
@@ -67,25 +70,32 @@ function googleChart(chartType, URL, container, options) {
function googleLineChart(URL, container, options) { function googleLineChart(URL, container, options) {
"use strict";
return googleChart('line', URL, container, options); return googleChart('line', URL, container, options);
} }
function googleBarChart(URL, container, options) { function googleBarChart(URL, container, options) {
"use strict";
return googleChart('bar', URL, container, options); return googleChart('bar', URL, container, options);
} }
function googleColumnChart(URL, container, options) { function googleColumnChart(URL, container, options) {
"use strict";
return googleChart('column', URL, container, options); return googleChart('column', URL, container, options);
} }
function googleStackedColumnChart(URL, container, options) { function googleStackedColumnChart(URL, container, options) {
"use strict";
return googleChart('stackedColumn', URL, container, options); return googleChart('stackedColumn', URL, container, options);
} }
function googleComboChart(URL, container, options) { function googleComboChart(URL, container, options) {
"use strict";
return googleChart('combo', URL, container, options); return googleChart('combo', URL, container, options);
} }
function googlePieChart(URL, container, options) { function googlePieChart(URL, container, options) {
"use strict";
return googleChart('pie', URL, container, options); return googleChart('pie', URL, container, options);
} }

View File

@@ -1,3 +1,5 @@
/* exported defaultLineChartOptions, defaultBarChartOptions, defaultComboChartOptions, defaultColumnChartOptions, defaultStackedColumnChartOptions, defaultPieChartOptions */
var defaultLineChartOptions = { var defaultLineChartOptions = {
curveType: 'function', curveType: 'function',
legend: { legend: {
@@ -69,7 +71,7 @@ var defaultBarChartOptions = {
legend: { legend: {
position: 'none' position: 'none'
}, }
}; };
var defaultComboChartOptions = { var defaultComboChartOptions = {
@@ -127,7 +129,7 @@ var defaultColumnChartOptions = {
}, },
legend: { legend: {
position: 'none' position: 'none'
}, }
}; };
var defaultStackedColumnChartOptions = { var defaultStackedColumnChartOptions = {

View File

@@ -1,13 +1,16 @@
$(function () { $(function () {
"use strict";
$('#help').click(showHelp); $('#help').click(showHelp);
$(function () { $(function () {
$('[data-toggle="tooltip"]').tooltip()
}) $('[data-toggle="tooltip"]').tooltip();
});
}); });
function showHelp(e) { function showHelp(e) {
target = $(e.target); "use strict";
route = target.data('route'); var target = $(e.target);
var route = target.data('route');
// //
$('#helpBody').html('<i class="fa fa-refresh fa-spin"></i>'); $('#helpBody').html('<i class="fa fa-refresh fa-spin"></i>');
$('#helpTitle').html('Please hold...'); $('#helpTitle').html('Please hold...');

View File

@@ -1,7 +1,9 @@
/* globals google */
google.setOnLoadCallback(drawChart); google.setOnLoadCallback(drawChart);
function drawChart() { function drawChart() {
"use strict";
googleLineChart('chart/account/frontpage', 'accounts-chart'); googleLineChart('chart/account/frontpage', 'accounts-chart');
googlePieChart('chart/bill/frontpage', 'bills-chart'); googlePieChart('chart/bill/frontpage', 'bills-chart');
googleStackedColumnChart('chart/budget/frontpage', 'budgets-chart'); googleStackedColumnChart('chart/budget/frontpage', 'budgets-chart');
@@ -12,13 +14,20 @@ function drawChart() {
} }
function getBoxAmounts() { function getBoxAmounts() {
"use strict";
var boxes = ['in', 'out', 'bills-unpaid', 'bills-paid']; var boxes = ['in', 'out', 'bills-unpaid', 'bills-paid'];
for (x in boxes) { for (var x in boxes) {
var box = boxes[x]; var box = boxes[x];
$.getJSON('/json/box/' + box).success(function (data) { $.getJSON('/json/box/' + box).success(putData).fail(failData);
$('#box-' + data.box).html(data.amount);
}).fail(function () {
console.log('Failed to get box!')
});
} }
} }
function putData(data) {
"use strict";
$('#box-' + data.box).html(data.amount);
}
function failData() {
"use strict";
console.log('Failed to get box!');
}

View File

@@ -1,4 +1,19 @@
/* globals $, googleLineChart, token */
// Return a helper with preserved width of cells
var fixHelper = function (e, tr) {
"use strict";
var $originals = tr.children();
var $helper = tr.clone();
$helper.children().each(function (index) {
// Set helper cell sizes to match the original sizes
$(this).width($originals.eq(index).width());
});
return $helper;
};
$(function () { $(function () {
"use strict";
$('.addMoney').on('click', addMoney); $('.addMoney').on('click', addMoney);
$('.removeMoney').on('click', removeMoney); $('.removeMoney').on('click', removeMoney);
@@ -31,18 +46,9 @@ $(function () {
); );
}); });
// Return a helper with preserved width of cells
var fixHelper = function(e, tr) {
var $originals = tr.children();
var $helper = tr.clone();
$helper.children().each(function (index) {
// Set helper cell sizes to match the original sizes
$(this).width($originals.eq(index).width());
});
return $helper;
}
function addMoney(e) { function addMoney(e) {
"use strict";
var pigID = parseInt($(e.target).data('id')); var pigID = parseInt($(e.target).data('id'));
$('#moneyManagementModal').empty().load('piggy-banks/add/' + pigID, function () { $('#moneyManagementModal').empty().load('piggy-banks/add/' + pigID, function () {
$('#moneyManagementModal').modal('show'); $('#moneyManagementModal').modal('show');
@@ -52,6 +58,7 @@ function addMoney(e) {
} }
function removeMoney(e) { function removeMoney(e) {
"use strict";
var pigID = parseInt($(e.target).data('id')); var pigID = parseInt($(e.target).data('id'));
$('#moneyManagementModal').empty().load('piggy-banks/remove/' + pigID, function () { $('#moneyManagementModal').empty().load('piggy-banks/remove/' + pigID, function () {
$('#moneyManagementModal').modal('show'); $('#moneyManagementModal').modal('show');
@@ -60,15 +67,15 @@ function removeMoney(e) {
return false; return false;
} }
function stopSorting() { function stopSorting() {
"use strict";
$('.loadSpin').addClass('fa fa-refresh fa-spin'); $('.loadSpin').addClass('fa fa-refresh fa-spin');
var order = []; var order = [];
$.each($('#sortable>tbody>tr'), function(i,v) { $.each($('#sortable>tbody>tr'), function (i, v) {
var holder = $(v); var holder = $(v);
var id = holder.data('id'); var id = holder.data('id');
order.push(id); order.push(id);
}); });
$.post('/piggy-banks/sort',{_token: token, order: order}).success(function(data) { $.post('/piggy-banks/sort', {_token: token, order: order}).success(function () {
"use strict";
$('.loadSpin').removeClass('fa fa-refresh fa-spin'); $('.loadSpin').removeClass('fa fa-refresh fa-spin');
}); });
} }

View File

@@ -1,9 +1,11 @@
if (typeof(google) != 'undefined') { /* globals expenseRestShow:true, incomeRestShow:true, year, shared, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, googleColumnChart, googleLineChart, googleStackedColumnChartg */
if (typeof(google) !== 'undefined') {
google.setOnLoadCallback(drawChart); google.setOnLoadCallback(drawChart);
} }
function drawChart() { function drawChart() {
"use strict";
googleColumnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart'); googleColumnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart');
googleColumnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart'); googleColumnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart');
@@ -13,16 +15,8 @@ function drawChart() {
googleLineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart'); googleLineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
} }
$(function () {
$('.openModal').on('click', openModal);
// click open the top X income list:
$('#showIncomes').click(showIncomes);
// click open the top X expense list:
$('#showExpenses').click(showExpenses);
});
function openModal(e) { function openModal(e) {
"use strict"; "use strict";
var target = $(e.target).parent(); var target = $(e.target).parent();
@@ -61,6 +55,7 @@ function showIncomes() {
} }
function showExpenses() { function showExpenses() {
"use strict";
if (expenseRestShow) { if (expenseRestShow) {
// hide everything, make button say "show" // hide everything, make button say "show"
$('#showExpenses').text(showTheRestExpense); $('#showExpenses').text(showTheRestExpense);
@@ -79,3 +74,14 @@ function showExpenses() {
return false; return false;
} }
$(function () {
"use strict";
$('.openModal').on('click', openModal);
// click open the top X income list:
$('#showIncomes').click(showIncomes);
// click open the top X expense list:
$('#showExpenses').click(showExpenses);
});

View File

@@ -1,5 +1,6 @@
/* globals zoomLevel, token, google, latitude, longitude */
$(function () { $(function () {
"use strict";
/* /*
Hide and show the tag index help. Hide and show the tag index help.
*/ */
@@ -47,7 +48,7 @@ function clearLocation() {
} }
function initialize() { function initialize() {
"use strict";
/* /*
Create new map: Create new map:
*/ */
@@ -91,6 +92,7 @@ function saveZoomLevel() {
* @param event * @param event
*/ */
function placeMarker(event) { function placeMarker(event) {
"use strict";
deleteMarkers(); deleteMarkers();
var marker = new google.maps.Marker({position: event.latLng, map: map}); var marker = new google.maps.Marker({position: event.latLng, map: map});
$('input[name="latitude"]').val(event.latLng.lat()); $('input[name="latitude"]').val(event.latLng.lat());
@@ -105,6 +107,7 @@ function placeMarker(event) {
* Deletes all markers in the array by removing references to them. * Deletes all markers in the array by removing references to them.
*/ */
function deleteMarkers() { function deleteMarkers() {
"use strict";
for (var i = 0; i < markers.length; i++) { for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null); markers[i].setMap(null);
} }

View File

@@ -1,8 +1,6 @@
/* globals what, $ */
$(document).ready(function () { $(document).ready(function () {
if (typeof googleTablePaged != 'undefined') { "use strict";
googleTablePaged('table/transactions/' + what, 'transaction-table');
}
if ($('input[name="expense_account"]').length > 0) { if ($('input[name="expense_account"]').length > 0) {
$.getJSON('json/expense-accounts').success(function (data) { $.getJSON('json/expense-accounts').success(function (data) {
$('input[name="expense_account"]').typeahead({source: data}); $('input[name="expense_account"]').typeahead({source: data});
@@ -28,7 +26,7 @@ $(document).ready(function () {
}); });
} }
if ($('input[name="description"]').length > 0 && what != undefined) { if ($('input[name="description"]').length > 0 && what !== undefined) {
$.getJSON('json/transaction-journals/' + what).success(function (data) { $.getJSON('json/transaction-journals/' + what).success(function (data) {
$('input[name="description"]').typeahead({source: data}); $('input[name="description"]').typeahead({source: data});
}); });

View File

@@ -176,7 +176,6 @@
// Allow for dropdowns to go bottom up (aka, dropup-menu) // Allow for dropdowns to go bottom up (aka, dropup-menu)
// //
// Just add .dropup after the standard .dropdown class and you're set, bro. // Just add .dropup after the standard .dropdown class and you're set, bro.
// TODO: abstract this so that the navbar fixed styles are not placed here?
.dropup, .dropup,
.navbar-fixed-bottom .dropdown { .navbar-fixed-bottom .dropdown {

View File

@@ -185,7 +185,6 @@
//** `<input>` border color //** `<input>` border color
@input-border: #ccc; @input-border: #ccc;
// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4
//** Default `.form-control` border radius //** Default `.form-control` border radius
@input-border-radius: @border-radius-base; @input-border-radius: @border-radius-base;
//** Large `.form-control` border radius //** Large `.form-control` border radius

View File

@@ -1,37 +1,44 @@
<?php <?php
return [ return [
// general stuff:
'test' => 'You have selected English.', 'test' => 'You have selected English.',
'close' => 'Close', 'close' => 'Close',
'pleaseHold' => 'Please hold...', 'pleaseHold' => 'Please hold...',
'mandatoryFields' => 'Mandatory fields',
'optionalFields' => 'Optional fields',
'options' => 'Options',
'something' => 'Something!',
'actions' => 'Actions', 'actions' => 'Actions',
'edit' => 'Edit', 'edit' => 'Edit',
'delete' => 'Delete', 'delete' => 'Delete',
'welcomeBack' => 'What\'s playing?', 'welcomeBack' => 'What\'s playing?',
'everything' => 'Everything', 'everything' => 'Everything',
'customRange' => 'Custom range', 'customRange' => 'Custom range',
'apply' => 'Apply', 'apply' => 'Apply',
'cancel' => 'Cancel', 'cancel' => 'Cancel',
'from' => 'From', 'from' => 'From',
'to' => 'To', 'to' => 'To',
'showEverything' => 'Show everything', 'showEverything' => 'Show everything',
// forms:
'mandatoryFields' => 'Mandatory fields',
'optionalFields' => 'Optional fields',
'options' => 'Options',
'something' => 'Something!',
// budgets:
'create_new_budget' => 'Create a new budget', 'create_new_budget' => 'Create a new budget',
'store_new_budget' => ' Store new budget', 'store_new_budget' => ' Store new budget',
'availableIn' => 'Available in :date', 'availableIn' => 'Available in :date',
'transactionsWithoutBudget' => 'Expenses without budget', 'transactionsWithoutBudget' => 'Expenses without budget',
'transactionsWithoutBudgetDate' => 'Expenses without budget in :date', 'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
'createBudget' => 'New budget', 'createBudget' => 'New budget',
'inactiveBudgets' => 'Inactive budgets', 'inactiveBudgets' => 'Inactive budgets',
'without_budget_between' => 'Transactions without a budget between :start and :end',
'budget_in_month' => ':name in :month',
'delete_budget' => 'Delete budget ":name"',
// bills:
'delete_bill' => 'Delete bill ":name"',
// accounts: // accounts:
'details_for_asset' => 'Details for asset account ":name"', 'details_for_asset' => 'Details for asset account ":name"',
'details_for_expense' => 'Details for expense account ":name"', 'details_for_expense' => 'Details for expense account ":name"',
'details_for_revenue' => 'Details for revenue account ":name"', 'details_for_revenue' => 'Details for revenue account ":name"',
@@ -57,9 +64,17 @@ return [
'update_expense_account' => 'Update expense account', 'update_expense_account' => 'Update expense account',
'update_revenue_account' => 'Update revenue account', 'update_revenue_account' => 'Update revenue account',
'make_new_asset_account' => 'New asset account', 'make_new_asset_account' => 'Create a new asset account',
'make_new_expense_account' => 'New expense account', 'make_new_expense_account' => 'Create a new expense account',
'make_new_revenue_account' => 'New revenue account', 'make_new_revenue_account' => 'Create a new revenue account',
'asset_accounts' => 'Asset accounts',
'expense_accounts' => 'Expense accounts',
'revenue_accounts' => 'Revenue accounts',
'accountExtraHelp_asset' => '',
'accountExtraHelp_expense' => '',
'accountExtraHelp_revenue' => '',
// categories: // categories:
'new_category' => 'New category', 'new_category' => 'New category',
@@ -68,10 +83,20 @@ return [
'categories' => 'Categories', 'categories' => 'Categories',
'no_category' => '(no category)', 'no_category' => '(no category)',
'category' => 'Category', 'category' => 'Category',
'delete_category' => 'Delete category ":name"',
// transactions:
'update_withdrawal' => 'Update withdrawal',
'update_deposit' => 'Update deposit',
'update_transfer' => 'Update transfer',
'delete_withdrawal' => 'Delete withdrawal ":description"',
'delete_deposit' => 'Delete deposit ":description"',
'delete_transfer' => 'Delete transfer ":description"',
// new user: // new user:
'welcome' => 'Welcome to Firefly!', 'welcome' => 'Welcome to Firefly!',
'createNewAsset' => 'Create a new asset account to get started. This will allow you to create transactions and start your financial management', 'createNewAsset' => 'Create a new asset account to get started. ' .
'This will allow you to create transactions and start your financial management',
'createNewAssetButton' => 'Create new asset account', 'createNewAssetButton' => 'Create new asset account',
// home page: // home page:
@@ -122,11 +147,12 @@ return [
'createNew' => 'Create new', 'createNew' => 'Create new',
'withdrawal' => 'Withdrawal', 'withdrawal' => 'Withdrawal',
'deposit' => 'Deposit', 'deposit' => 'Deposit',
'account' => 'Account',
'transfer' => 'Transfer', 'transfer' => 'Transfer',
'Withdrawal' => 'Withdrawal', 'Withdrawal' => 'Withdrawal',
'Deposit' => 'Deposit', 'Deposit' => 'Deposit',
'Transfer' => 'Transfer', 'Transfer' => 'Transfer',
'bill' => 'Rekening', 'bill' => 'Bill',
'yes' => 'Yes', 'yes' => 'Yes',
'no' => 'No', 'no' => 'No',
'amount' => 'Amount', 'amount' => 'Amount',
@@ -141,6 +167,7 @@ return [
'half-year' => 'Every six months', 'half-year' => 'Every six months',
'yearly' => 'Yearly', 'yearly' => 'Yearly',
// reports:
'reportForYear' => 'Yearly report for :year', 'reportForYear' => 'Yearly report for :year',
'reportForYearShared' => 'Yearly report for :year (including shared accounts)', 'reportForYearShared' => 'Yearly report for :year (including shared accounts)',
'reportForMonth' => 'Montly report for :year', 'reportForMonth' => 'Montly report for :year',
@@ -151,15 +178,10 @@ return [
'balanceEndOfYear' => 'Balance at end of year', 'balanceEndOfYear' => 'Balance at end of year',
'balanceStartOfMonth' => 'Balance at end of month', 'balanceStartOfMonth' => 'Balance at end of month',
'balanceEndOfMonth' => 'Balance at end of month', 'balanceEndOfMonth' => 'Balance at end of month',
'balanceStart' => 'Balance at end of period', 'balanceStart' => 'Balance at end of period',
'balanceEnd' => 'Balance at end of period', 'balanceEnd' => 'Balance at end of period',
'reportsOwnAccounts' => 'Reports for your own accounts', 'reportsOwnAccounts' => 'Reports for your own accounts',
'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts', 'reportsOwnAccountsAndShared' => 'Reports for your own accounts and shared accounts',
'account' => 'Account',
'splitByAccount' => 'Split by account', 'splitByAccount' => 'Split by account',
'balancedByTransfersAndTags' => 'Balanced by transfers and tags', 'balancedByTransfersAndTags' => 'Balanced by transfers and tags',
'coveredWithTags' => 'Covered with tags', 'coveredWithTags' => 'Covered with tags',
@@ -167,11 +189,9 @@ return [
'expectedBalance' => 'Expected balance', 'expectedBalance' => 'Expected balance',
'outsideOfBudgets' => 'Outside of budgets', 'outsideOfBudgets' => 'Outside of budgets',
'leftInBudget' => 'Left in budget', 'leftInBudget' => 'Left in budget',
'sumOfSums' => 'Sum of sums', 'sumOfSums' => 'Sum of sums',
'notCharged' => 'Not charged (yet)', 'notCharged' => 'Not charged (yet)',
'inactive' => 'Inactive', 'inactive' => 'Inactive',
'difference' => 'Difference', 'difference' => 'Difference',
'in' => 'In', 'in' => 'In',
'out' => 'Out', 'out' => 'Out',
@@ -203,12 +223,40 @@ return [
'average' => 'Average', 'average' => 'Average',
'balanceFor' => 'Balance for :name', 'balanceFor' => 'Balance for :name',
'asset_accounts' => 'Asset accounts', // piggy banks:
'expense_accounts' => 'Expense accounts', 'new_piggy_bank' => 'Create new piggy bank',
'revenue_accounts' => 'Revenue accounts', 'account_status' => 'Account status',
'left_for_piggy_banks' => 'Left for piggy banks',
'sum_of_piggy_banks' => 'Sum of piggy banks',
'saved_so_far' => 'Saved so far',
'left_to_save' => 'Left to save',
'add_money_to_piggy_title' => 'Add money to piggy bank ":name"',
'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"',
'add' => 'Add',
'remove' => 'Remove',
'max_amount_add' => 'The maximum amount you can add is',
'max_amount_remove' => 'The maximum amount you can remove is',
'update_piggy_button' => 'Update piggy bank',
'update_piggy_title' => 'Update piggy bank ":name"',
'details' => 'Details',
'events' => 'Events',
'target_amount' => 'Target amount',
'start_date' => 'Start date',
'target_date' => 'Target date',
'no_target_date' => 'No target date',
'reminder' => 'Reminder',
'no_reminder' => 'No reminder',
'reminders_left' => 'Reminders left',
'expected_amount_per_reminder' => 'Expected amount per reminder',
'todo' => 'to do',
'table' => 'Table',
'piggy_bank_not_exists' => 'Piggy bank no longer exists.',
'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
'delete_piggy_bank' => 'Delete piggy bank ":name"',
// tags
'delete_tag' => 'Delete tag ":name"',
// some extra help:
'accountExtraHelp_asset' => '',
'accountExtraHelp_expense' => '',
'accountExtraHelp_revenue' => '',
]; ];

View File

@@ -1,37 +1,44 @@
<?php <?php
return [ return [
// general stuff:
'test' => 'Nederlands geselecteerd!', 'test' => 'Nederlands geselecteerd!',
'close' => 'Sluiten', 'close' => 'Sluiten',
'pleaseHold' => 'Momentje...', 'pleaseHold' => 'Momentje...',
'mandatoryFields' => 'Verplichte velden',
'optionalFields' => 'Optionele velden',
'options' => 'Opties',
'something' => 'Iets!',
'actions' => 'Acties', 'actions' => 'Acties',
'edit' => 'Wijzig', 'edit' => 'Wijzig',
'delete' => 'Verwijder', 'delete' => 'Verwijder',
'welcomeBack' => 'Hoe staat het er voor?', 'welcomeBack' => 'Hoe staat het er voor?',
'everything' => 'Alles', 'everything' => 'Alles',
'customRange' => 'Zelf bereik kiezen', 'customRange' => 'Zelf bereik kiezen',
'apply' => 'Go', 'apply' => 'Go',
'cancel' => 'Annuleren', 'cancel' => 'Annuleren',
'from' => 'Van', 'from' => 'Van',
'to' => 'Tot', 'to' => 'Tot',
'showEverything' => 'Laat alles zien', 'showEverything' => 'Laat alles zien',
// forms:
'mandatoryFields' => 'Verplichte velden',
'optionalFields' => 'Optionele velden',
'options' => 'Opties',
'something' => 'Iets!',
// budgets:
'create_new_budget' => 'Maak een nieuw budget', 'create_new_budget' => 'Maak een nieuw budget',
'store_new_budget' => 'Sla nieuw budget op', 'store_new_budget' => 'Sla nieuw budget op',
'availableIn' => 'Beschikbaar in :date', 'availableIn' => 'Beschikbaar in :date',
'transactionsWithoutBudget' => 'Uitgaven zonder budget', 'transactionsWithoutBudget' => 'Uitgaven zonder budget',
'transactionsWithoutBudgetDate' => 'Uitgaven zonder budget in :date', 'transactionsWithoutBudgetDate' => 'Uitgaven zonder budget in :date',
'createBudget' => 'Maak nieuw budget', 'createBudget' => 'Maak nieuw budget',
'inactiveBudgets' => 'Inactieve budgetten', 'inactiveBudgets' => 'Inactieve budgetten',
'without_budget_between' => 'Transacties zonder budget tussen :start en :end',
'budget_in_month' => ':name in :month',
'delete_budget' => 'Verwijder budget ":name"',
// bills:
'delete_bill' => 'Verwijder rekening ":name"',
// accounts: // accounts:
'details_for_asset' => 'Overzicht voor betaalrekening ":name"', 'details_for_asset' => 'Overzicht voor betaalrekening ":name"',
'details_for_expense' => 'Overzicht voor crediteur ":name"', 'details_for_expense' => 'Overzicht voor crediteur ":name"',
'details_for_revenue' => 'Overzicht voor debiteur ":name"', 'details_for_revenue' => 'Overzicht voor debiteur ":name"',
@@ -61,6 +68,23 @@ return [
'make_new_expense_account' => 'Nieuwe crediteur', 'make_new_expense_account' => 'Nieuwe crediteur',
'make_new_revenue_account' => 'Nieuwe debiteur', 'make_new_revenue_account' => 'Nieuwe debiteur',
'asset_accounts' => 'Betaalrekeningen',
'expense_accounts' => 'Crediteuren',
'revenue_accounts' => 'Debiteuren',
// some extra help:
'accountExtraHelp_asset' => '',
'accountExtraHelp_expense' =>
'Een crediteur is een persoon of een bedrijf waar je geld aan moet betalen. Je staat bij ze in het krijt. Een verwarrende' .
' term misschien, maar zo werkt het nou eenmaal. De supermarkt, je huurbaas of de bank zijn crediteuren. Jouw ' .
'geld (krediet) gaat naar hen toe. De term komt uit de wereld van de boekhouding. De uitgaves die je hier ziet zijn ' .
'positief, want je kijkt uit hun perspectief. Zodra jij afrekent in een winkel, komt het geld er bij hen bij (positief).',
'accountExtraHelp_revenue' => 'Als je geld krijgt van een bedrijf of een persoon is dat een debiteur. ' .
'Dat kan salaris zijn, of een andere betaling. ' .
' Ze hebben een schuld (debet) aan jou. De term komt uit de wereld van de boekhouding.' .
' De inkomsten die je hier ziet zijn negatief, want je kijkt uit hun perspectief. Zodra een debiteur geld naar jou ' .
'overmaakt gaat het er bij hen af (negatief).',
// categories: // categories:
'new_category' => 'Nieuwe categorie', 'new_category' => 'Nieuwe categorie',
'without_category' => 'Zonder categorie', 'without_category' => 'Zonder categorie',
@@ -68,12 +92,22 @@ return [
'categories' => 'Categorieën', 'categories' => 'Categorieën',
'no_category' => '(geen categorie)', 'no_category' => '(geen categorie)',
'category' => 'Categorie', 'category' => 'Categorie',
'delete_category' => 'Verwijder categorie ":name"',
// transactions:
'update_withdrawal' => 'Wijzig uitgave',
'update_deposit' => 'Wijzig inkomsten',
'update_transfer' => 'Wijzig overschrijving',
'delete_withdrawal' => 'Verwijder uitgave ":description"',
'delete_deposit' => 'Verwijder inkomsten ":description"',
'delete_transfer' => 'Verwijder overschrijving ":description"',
// new user: // new user:
'welcome' => 'Welkom bij Firefly!', 'welcome' => 'Welkom bij Firefly!',
'createNewAsset' => 'Maak om te beginnen een nieuwe betaalrekening. Dit is je start van je financiële beheer.', 'createNewAsset' => 'Maak om te beginnen een nieuwe betaalrekening. Dit is je start van je financiële beheer.',
'createNewAssetButton' => 'Maak een nieuwe betaalrekening', 'createNewAssetButton' => 'Maak een nieuwe betaalrekening',
// home page: // home page:
'yourAccounts' => 'Je betaalrekeningen', 'yourAccounts' => 'Je betaalrekeningen',
'budgetsAndSpending' => 'Budgetten en uitgaven', 'budgetsAndSpending' => 'Budgetten en uitgaven',
@@ -122,6 +156,7 @@ return [
'createNew' => 'Nieuw', 'createNew' => 'Nieuw',
'withdrawal' => 'Uitgave', 'withdrawal' => 'Uitgave',
'deposit' => 'Inkomsten', 'deposit' => 'Inkomsten',
'account' => 'Rekening',
'transfer' => 'Overschrijving', 'transfer' => 'Overschrijving',
'Withdrawal' => 'Uitgave', 'Withdrawal' => 'Uitgave',
'Deposit' => 'Inkomsten', 'Deposit' => 'Inkomsten',
@@ -141,6 +176,7 @@ return [
'half-year' => 'Elk half jaar', 'half-year' => 'Elk half jaar',
'yearly' => 'Jaarlijks', 'yearly' => 'Jaarlijks',
// reports:
'reportForYear' => 'Jaaroverzicht :year', 'reportForYear' => 'Jaaroverzicht :year',
'reportForYearShared' => 'Jaaroverzicht :year (inclusief gedeelde rekeningen)', 'reportForYearShared' => 'Jaaroverzicht :year (inclusief gedeelde rekeningen)',
'reportForMonth' => 'Maandoverzicht van :date', 'reportForMonth' => 'Maandoverzicht van :date',
@@ -151,15 +187,10 @@ return [
'balanceEndOfYear' => 'Saldo aan het einde van het jaar', 'balanceEndOfYear' => 'Saldo aan het einde van het jaar',
'balanceStartOfMonth' => 'Saldo aan het begin van de maand', 'balanceStartOfMonth' => 'Saldo aan het begin van de maand',
'balanceEndOfMonth' => 'Saldo aan het einde van de maand', 'balanceEndOfMonth' => 'Saldo aan het einde van de maand',
'balanceStart' => 'Saldo aan het begin van de periode', 'balanceStart' => 'Saldo aan het begin van de periode',
'balanceEnd' => 'Saldo aan het einde van de periode', 'balanceEnd' => 'Saldo aan het einde van de periode',
'reportsOwnAccounts' => 'Overzichten voor je eigen betaalrekeningen', 'reportsOwnAccounts' => 'Overzichten voor je eigen betaalrekeningen',
'reportsOwnAccountsAndShared' => 'Overzichten voor je eigen betaalrekeningen en gedeelde rekeningen', 'reportsOwnAccountsAndShared' => 'Overzichten voor je eigen betaalrekeningen en gedeelde rekeningen',
'account' => 'Rekening',
'splitByAccount' => 'Per betaalrekening', 'splitByAccount' => 'Per betaalrekening',
'balancedByTransfersAndTags' => 'Gecorrigeerd met overschrijvingen en tags', 'balancedByTransfersAndTags' => 'Gecorrigeerd met overschrijvingen en tags',
'coveredWithTags' => 'Gecorrigeerd met tags', 'coveredWithTags' => 'Gecorrigeerd met tags',
@@ -167,11 +198,9 @@ return [
'expectedBalance' => 'Verwacht saldo', 'expectedBalance' => 'Verwacht saldo',
'outsideOfBudgets' => 'Buiten budgetten', 'outsideOfBudgets' => 'Buiten budgetten',
'leftInBudget' => 'Over van budget', 'leftInBudget' => 'Over van budget',
'sumOfSums' => 'Alles bij elkaar', 'sumOfSums' => 'Alles bij elkaar',
'notCharged' => '(Nog) niet betaald', 'notCharged' => '(Nog) niet betaald',
'inactive' => 'Niet actief', 'inactive' => 'Niet actief',
'difference' => 'Verschil', 'difference' => 'Verschil',
'in' => 'In', 'in' => 'In',
'out' => 'Uit', 'out' => 'Uit',
@@ -203,20 +232,38 @@ return [
'average' => 'Gemiddeld', 'average' => 'Gemiddeld',
'balanceFor' => 'Saldo op :name', 'balanceFor' => 'Saldo op :name',
'asset_accounts' => 'Betaalrekeningen', // piggy banks:
'expense_accounts' => 'Crediteuren', 'new_piggy_bank' => 'Nieuw spaarpotje',
'revenue_accounts' => 'Debiteuren', 'account_status' => 'Rekeningoverzicht',
'left_for_piggy_banks' => 'Over voor spaarpotjes',
'sum_of_piggy_banks' => 'Som van spaarpotjes',
'saved_so_far' => 'Gespaard',
'left_to_save' => 'Te sparen',
'add_money_to_piggy_title' => 'Stop geld in spaarpotje ":name"',
'remove_money_from_piggy_title' => 'Haal geld uit spaarpotje ":name"',
'add' => 'Toevoegen',
'remove' => 'Verwijderen',
'max_amount_add' => 'Hooguit toe te voegen',
'max_amount_remove' => 'Hooguit te verwijderen',
'update_piggy_button' => 'Wijzig spaarpotje',
'update_piggy_title' => 'Wijzig spaarpotje ":name"',
'details' => 'Details',
'events' => 'Gebeurtenissen',
'target_amount' => 'Doelbedrag',
'start_date' => 'Startdatum',
'target_date' => 'Doeldatum',
'no_target_date' => 'Geen doeldatum',
'reminder' => 'Herinnering',
'no_reminder' => 'Geen herinnering',
'reminders_left' => 'Herinneringen te gaan',
'expected_amount_per_reminder' => 'Verwacht bedrag per herinnering',
'todo' => 'te doen',
'table' => 'Tabel',
'add_any_amount_to_piggy' => 'Stop geld in dit spaarpotje om het doel van :amount te halen.',
'add_set_amount_to_piggy' => 'Stop voor :date :amount in dit spaarpotje om hem op tijd te vullen.',
'delete_piggy_bank' => 'Verwijder spaarpotje ":name"',
// tags
'delete_tag' => 'Verwijder tag ":name"',
// some extra help:
'accountExtraHelp_asset' => '',
'accountExtraHelp_expense' =>
'Een crediteur is een persoon of een bedrijf waar je geld aan moet betalen. Je staat bij ze in het krijt. Een verwarrende' .
' term misschien, maar zo werkt het nou eenmaal. De supermarkt, je huurbaas of de bank zijn crediteuren. Jouw ' .
'geld (krediet) gaat naar hen toe. De term komt uit de wereld van de boekhouding. De uitgaves die je hier ziet zijn ' .
'positief, want je kijkt uit hun perspectief. Zodra jij afrekent in een winkel, komt het geld er bij hen bij (positief).',
'accountExtraHelp_revenue' => 'Als je geld krijgt van een bedrijf of een persoon is dat een debiteur. ' .
'Dat kan salaris zijn, of een andere betaling. ' .
' Ze hebben een schuld (debet) aan jou. De term komt uit de wereld van de boekhouding.' .
' De inkomsten die je hier ziet zijn negatief, want je kijkt uit hun perspectief. Zodra een debiteur geld naar jou ' .
'overmaakt gaat het er bij hen af (negatief).',
]; ];

View File

@@ -11,23 +11,20 @@
<div class="panel-body"> <div class="panel-body">
<div class="row"> <div class="row">
<div class="col-lg-6 col-md-4 col-sm-3"> <div class="col-lg-6 col-md-4 col-sm-3">
<small>{{ 'budgeted'|_ }}: <span id="budgetedAmount" data-value="300"></span></small> <small>{{ 'budgeted'|_ }}: <span id="budgetedAmount" class="text-success">{{ budgeted|formatAmountPlain }}</span></small>
</div> </div>
<div class="col-lg-6 col-md-4 col-sm-3" style="text-align:right;"> <div class="col-lg-6 col-md-4 col-sm-3" style="text-align:right;">
<small>{{ trans('firefly.availableIn',{date : Session.get('start').formatLocalized(monthFormat) }) }}: <small>{{ trans('firefly.availableIn',{date : Session.get('start').formatLocalized(monthFormat) }) }}:
<a href="#" class="updateIncome"><span id="totalAmount" data-value="{{ amount }}">{{ amount|formatAmount }}</span></a></small> <a href="#" class="updateIncome"><span id="budgetIncomeTotal" data-value="{{ budgetIncomeTotal }}">{{ budgetIncomeTotal|formatAmount }}</span></a></small>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-12 col-md-12 col-sm-12">
<div class="progress progress-striped"> <div class="progress progress-striped budgetedBar">
<div class="progress-bar progress-bar-info" id="progress-bar-default" role="progressbar" aria-valuenow="0" aria-valuemin="0" <div class="progress-bar progress-bar-danger" id="progress-bar-danger" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0;"></div>
aria-valuemax="100" style="width: 0;"></div> <div class="progress-bar progress-bar-warning" id="progress-bar-warning" role="progressbar" aria-valuenow="10" aria-valuemin="0" aria-valuemax="100" style="width: 0;"></div>
<div class="progress-bar progress-bar-danger" id="progress-bar-danger" role="progressbar" aria-valuenow="0" aria-valuemin="0" <div class="progress-bar progress-bar-info" id="progress-bar-default" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0;"></div>
aria-valuemax="100" style="width: 0;"></div>
<div class="progress-bar progress-bar-warning" id="progress-bar-warning" role="progressbar" aria-valuenow="10" aria-valuemin="0"
aria-valuemax="100" style="width: 0;"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -38,16 +35,10 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-12 col-md-12 col-sm-12">
<div class="progress progress-striped"> <div class="progress progress-striped spentBar">
{% if overspent %} <div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0;"></div>
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="{{ spentPCT }}" aria-valuemin="0" <div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0;"></div>
aria-valuemax="100" style="width: {{ spentPCT }}%;"></div> <div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0;"></div>
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="{{ 100-spentPCT }}" aria-valuemin="0"
aria-valuemax="100" style="width: {{ 100-spentPCT }}%;"></div>
{% else %}
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="{{ spentPCT }}" aria-valuemin="0"
aria-valuemax="100" style="width: {{ spentPCT }}%;"></div>
{% endif %}
</div> </div>
</div> </div>
</div> </div>
@@ -80,10 +71,11 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-fw fa-tasks"></i> <i class="fa fa-fw fa-tasks"></i>
<!-- link in header -->
{% if budget.currentRep %} {% if budget.currentRep %}
<a href="{{ route('budgets.show', [budget.id, budget.currentRep.id]) }}" id="budget-link-{{ budget.id }}">{{ budget.name }}</a> <a href="{{ route('budgets.show', [budget.id, budget.currentRep.id]) }}" class="budget-link" data-id="{{ budget.id }}">{{ budget.name }}</a>
{% else %} {% else %}
<a href="{{ route('budgets.show',budget.id) }}" id="budget-link-{{ budget.id }}">{{ budget.name }}</a> <a href="{{ route('budgets.show',budget.id) }}" class="budget-link" data-id="{{ budget.id }}">{{ budget.name }}</a>
{% endif %} {% endif %}
@@ -100,55 +92,26 @@
</ul> </ul>
</div> </div>
</div> </div>
</div> </div>
<div class="panel-body"> <table class="table">
<!-- the range in which the budget can be set --> <tr>
<p> <td style="width:40%;">{{ 'budgeted'|_ }}</td>
{% if budget.currentRep %} <td>
<input type="range" data-id="{{ budget.id }}" data-spent="{{ budget.spent }}" id="budget-range-{{ budget.id }}" <div class="form-group" style="margin-bottom:0;">
max="{{ budgetMaximum }}" min="0" value="{{ budget.currentRep.amount }}"/> <div class="input-group">
{% else %} <div class="input-group-addon">{{ defaultCurrency.symbol|raw }}</div>
<input type="range" data-id="{{ budget.id }}" data-spent="{{ budget.spent }}" id="budget-range-{{ budget.id }}" <input type="hidden" name="balance_currency_id" value="1" />
max="{{ budgetMaximum }}" min="0" value="0"/> <input class="form-control budgetAmount" data-original="{{ budget.currentRep.amount|number_format(0,'','') }}" data-id="{{ budget.id }}" value="{{ budget.currentRep.amount|number_format(0,'','') }}" autocomplete="off" step="1" min="0" max="{{ budgetMaximum }}" name="amount" type="number">
{% endif %}
</p>
<!-- some textual info about the budget. Updates dynamically. -->
<p>
<!-- budget-holder-X holds all the elements -->
<span id="budget-holder-{{ budget.id }}">
{% if budget.currentRep %}
<!-- budget-description-X holds the description. -->
<span id="budget-description-{{ budget.id }}">Budgeted: </span>
<!-- budget-info-X holds the input and the euro-sign: -->
<span id="budget-info-{{ budget.id }}">
{% if budget.currentRep.amount > budget.spent %}
<span class="text-success">{{ getCurrencySymbol()|raw }}</span> <input type="number" min="0" max="{{ budgetMaximum }}" data-id="{{ budget.id }}"
step="1" value="{{ budget.currentRep.amount }}"
style="width:90px;color:#3c763d;"/>
{% else %}
<span class="text-danger">{{ getCurrencySymbol()|raw }}</span> <input type="number" min="0" max="{{ budgetMaximum }}" data-id="{{ budget.id }}"
step="1" value="{{ budget.currentRep.amount }}"
style="width:90px;color:#a94442;"/>
{% endif %}
</span>
{% else %}
<span id="budget-description-{{ budget.id }}"><em>No budget</em></span>
<span id="budget-info-{{ budget.id }}">
<span class="text-success" style="display:none;">{{ getCurrencySymbol()|raw }}</span> <input data-id="{{ budget.id }}" type="number"
min="0" max="{{ budgetMaximum }}" step="1"
value="0"
style="width:50px;color:#3c763d;display:none;"/>
</span>
{% endif %}
</span>
</p>
<p>
<span id="spent-{{ budget.id }}" data-value="{{ budget.spent }}">{{ 'spent'|_ }}: {{ budget.spent|formatAmount }}</span>
</p>
</div> </div>
</div> </div>
</td>
</tr>
<tr>
<td style="width:50%;">{{ 'spent'|_ }}</td>
<td>{{ budget.spent|formatAmount }}</td>
</tr>
</table>
</div>
</div> </div>
{% endfor %} {% endfor %}
<div class="col-lg-3 col-sm-4 col-md-6"> <div class="col-lg-3 col-sm-4 col-md-6">
@@ -191,5 +154,15 @@
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script type="text/javascript">
// actually spent bar data:
var spent = {{ spent }};
var currencySymbol = "{{ getCurrencySymbol()|raw }}";
// budgeted data:
var budgeted = {{ budgeted }};
var budgetIncomeTotal = {{ budgetIncomeTotal }};
</script>
<script type="text/javascript" src="js/budgets.js"></script> <script type="text/javascript" src="js/budgets.js"></script>
{% endblock %} {% endblock %}

View File

@@ -37,5 +37,18 @@
<div class="title">Be right back.</div> <div class="title">Be right back.</div>
</div> </div>
</div> </div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', 'auto');
ga('send', 'pageview');
</script>
</body> </body>
</html> </html>

View File

@@ -169,9 +169,12 @@
ga('send', 'pageview'); ga('send', 'pageview');
// send an event if relevant: // send an event if relevant:
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') %} {% if Session.has('gaEventCategory') and Session.has('gaEventAction') and not Session.has('gaEventLabel') %}
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}'); ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
{% endif %} {% endif %}
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') and Session.has('gaEventLabel') %}
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}','{{ Session.get('gaEventLabel') }}');
{% endif %}
</script> </script>
</body> </body>

View File

@@ -58,5 +58,28 @@
<script type="text/javascript" src="js/metisMenu.min.js"></script> <script type="text/javascript" src="js/metisMenu.min.js"></script>
<script type="text/javascript" src="js/sb-admin-2.js"></script> <script type="text/javascript" src="js/sb-admin-2.js"></script>
<script>
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', 'auto');
ga('send', 'pageview');
// send an event if relevant:
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') %}
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
{% endif %}
</script>
</body> </body>
</html> </html>

View File

@@ -9,7 +9,7 @@
<td style="width:100px;"> <td style="width:100px;">
<div class="btn-group btn-group-xs"> <div class="btn-group btn-group-xs">
<a href="{{ route('piggy-banks.edit', piggyBank.id)}}" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a> <a href="{{ route('piggy-banks.edit', piggyBank.id)}}" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
<a href="{{ route('piggy-banks.delete', piggyBank.id)}}" class="btn btn-default btn-xs"><i class="fa fa-trash fa-fw"></i></a> <a href="{{ route('piggy-banks.delete', piggyBank.id)}}" class="btn btn-danger btn-xs"><i class="fa fa-trash fa-fw"></i></a>
</div> </div>
</td> </td>
<td> <td>

View File

@@ -171,7 +171,24 @@
</ul> </ul>
<!-- /.nav-second-level --> <!-- /.nav-second-level -->
</li> </li>
<!-- profile, again--> <!-- top menu again -->
<li class="hidden-sm hidden-md hidden-lg">
<a class="{{ activeRoute('profile',null,true) }}" href="{{ route('profile') }}"><i class="fa fa-user fa-fw"></i> {{ Auth.user.email }}</a>
</li>
<li class="hidden-sm hidden-md hidden-lg">
<a class="{{ activeRoute('preferences',null,true) }}" href="{{ route('preferences') }}"><i class="fa fa-gear fa-fw"></i> {{ 'preferences'|_ }}</a>
</li>
<li class="hidden-sm hidden-md hidden-lg">
<a class="{{ activeRoute('currency') }}" href="{{ route('currency.index') }}"><i class="fa fa-usd fa-fw"></i> {{ 'currency'|_ }}</a>
</li>
<li class="hidden-sm hidden-md hidden-lg">
<a class="{{ activeRoute('reminders') }}" href="{{ route('reminders.index') }}"><i class="fa fa-clock-o fa-fw"></i> {{ 'reminders'|_ }}</a>
</li>
<li class="hidden-sm hidden-md hidden-lg">
<a href="{{ route('logout') }}"><i class="fa fa-sign-out fa-fw"></i> {{ 'logout'|_ }}</a>
</li>
<!-- reminders, again--> <!-- reminders, again-->
</ul> </ul>
</div> </div>

View File

@@ -2,12 +2,12 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{{ 'close'|_ }}</span></button> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{{ 'close'|_ }}</span></button>
<h4 class="modal-title" id="myModalLabel">Add money to {{ piggyBank.name }}</h4> <h4 class="modal-title" id="myModalLabel">{{ trans('firefly.add_money_to_piggy_title', {name: piggyBank.name}) }}</h4>
</div> </div>
<form style="display: inline;" id="add" action="{{ route('piggy-banks.add', piggyBank.id) }}" method="POST"> <form style="display: inline;" id="add" action="{{ route('piggy-banks.add', piggyBank.id) }}" method="POST">
<div class="modal-body"> <div class="modal-body">
<p> <p>
The maximum amount you can add is {{ maxAmount|formatAmount }}. {{ 'max_amount_add'|_ }}: {{ maxAmount|formatAmount }}.
</p> </p>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">{{ getCurrencySymbol()|raw }}</div> <div class="input-group-addon">{{ getCurrencySymbol()|raw }}</div>
@@ -17,7 +17,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>
<button type="submit" class="btn btn-primary">Add</button> <button type="submit" class="btn btn-primary">{{ 'add'|_ }}</button>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -50,7 +50,7 @@
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p> <p>
<button type="submit" class="btn btn-lg btn-success"> <button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-pencil"></i> Update piggy bank <i class="fa fa-pencil"></i> {{ 'update_piggy_button'|_ }}
</button> </button>
</p> </p>
</div> </div>

View File

@@ -4,7 +4,7 @@
<div class="row"> <div class="row">
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-12 col-md-12 col-sm-12">
<p> <p>
<a href="{{ route('piggy-banks.create') }}" class="btn btn-success"><i class="fa fa-sort-amount-asc fa-fw"></i> Create new piggy bank</a> <a href="{{ route('piggy-banks.create') }}" class="btn btn-success"><i class="fa fa-sort-amount-asc fa-fw"></i> {{ 'new_piggy_bank'|_ }}</a>
</p> </p>
</div> </div>
</div> </div>
@@ -22,16 +22,16 @@
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-fw fa-money"></i> Account status <i class="fa fa-fw fa-money"></i> {{ 'account_status'|_ }}
</div> </div>
<table class="table table-striped"> <table class="table table-striped">
<tr> <tr>
<th>Account</th> <th>{{ 'account'|_ }}</th>
<th>Balance</th> <th>{{ 'balance'|_ }}</th>
<th>Left for piggy banks</th> <th>{{ 'left_for_piggy_banks'|_ }}</th>
<th>Sum of piggy banks</th> <th>{{ 'sum_of_piggy_banks'|_ }}</th>
<th>Saved so far</th> <th>{{ 'saved_so_far'|_ }}</th>
<th>Left to save</th> <th>{{ 'left_to_save'|_ }}</th>
</tr> </tr>
{% for id,info in accounts %} {% for id,info in accounts %}
<tr> <tr>

View File

@@ -4,12 +4,12 @@
<input type="hidden" name="_token" value="{{ csrf_token() }}" /> <input type="hidden" name="_token" value="{{ csrf_token() }}" />
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{{ 'close'|_ }}</span></button> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">{{ 'close'|_ }}</span></button>
<h4 class="modal-title" id="myModalLabel">Remove money from {{ piggyBank.name }}</h4> <h4 class="modal-title" id="myModalLabel">{{ trans('firefly.remove_money_from_piggy_title', {name: piggyBank.name}) }}</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p> <p>
The maximum amount you can remove is {{ currentRelevantRepAmount(piggyBank)|formatAmount }} {{ 'max_amount_remove'|_ }}: {{ currentRelevantRepAmount(piggyBank)|formatAmount }}.
</p> </p>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">{{ getCurrencySymbol()|raw }}</div> <div class="input-group-addon">{{ getCurrencySymbol()|raw }}</div>
@@ -18,7 +18,7 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>
<button type="submit" class="btn btn-primary">Remove</button> <button type="submit" class="btn btn-primary">{{ 'remove'|_ }}</button>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -5,7 +5,7 @@
<div class="col-lg-8 col-md-8 col-sm-6"> <div class="col-lg-8 col-md-8 col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-fw fa-clock-o"></i> Events <i class="fa fa-fw fa-clock-o"></i> {{ 'events'|_ }}
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div id="piggy-bank-history"></div> <div id="piggy-bank-history"></div>
@@ -15,7 +15,7 @@
<div class="col-lg-4 col-md-4 col-sm-6"> <div class="col-lg-4 col-md-4 col-sm-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-fw fa-info-circle"></i> Details <i class="fa fa-fw fa-info-circle"></i> {{ 'details'|_ }}
<!-- ACTIONS MENU --> <!-- ACTIONS MENU -->
<div class="pull-right"> <div class="pull-right">
@@ -34,49 +34,49 @@
</div> </div>
<table class="table table-bordered table-striped"> <table class="table table-bordered table-striped">
<tr> <tr>
<td>Account</td> <td>{{ 'account'|_ }}</td>
<td><a href="{{ route('accounts.show', piggyBank.account_id) }}">{{ piggyBank.account.name }}</a></td> <td><a href="{{ route('accounts.show', piggyBank.account_id) }}">{{ piggyBank.account.name }}</a></td>
</tr> </tr>
<tr> <tr>
<td>Target amount</td> <td>{{ 'target_amount'|_ }}</td>
<td>{{ piggyBank.targetAmount|formatAmount }}</td> <td>{{ piggyBank.targetAmount|formatAmount }}</td>
</tr> </tr>
<tr> <tr>
<td>Saved so far</td> <td>{{ 'saved_so_far'|_ }}</td>
<td>{{ currentRelevantRepAmount(piggyBank)|formatAmount }}</td> <td>{{ currentRelevantRepAmount(piggyBank)|formatAmount }}</td>
</tr> </tr>
<tr> <tr>
<td>Left to save</td> <td>{{ 'left_to_save'|_ }}</td>
<td>{{ piggyBank.targetamount - currentRelevantRepAmount(piggyBank)|formatAmount }}</td> <td>{{ piggyBank.targetamount - currentRelevantRepAmount(piggyBank)|formatAmount }}</td>
</tr> </tr>
<tr> <tr>
<td>Start date</td> <td>{{ 'start_date'|_ }}</td>
<td> <td>
{% if piggyBank.startdate %} {% if piggyBank.startdate %}
{{ piggyBank.startdate.format('jS F Y')}} {{ piggyBank.startdate.format('jS F Y')}}
{% else %} {% else %}
<em>No start date</em> <em>{{ 'no_start_date'|_ }}</em>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
<tr> <tr>
<td>Target date</td> <td>{{ 'target_date'|_ }}</td>
<td> <td>
{% if piggyBank.targetdate %} {% if piggyBank.targetdate %}
{{ piggyBank.targetdate.format('jS F Y') }} {{ piggyBank.targetdate.format('jS F Y') }}
{% else %} {% else %}
<em>No start date</em> <em>{{ 'no_target_date'|_ }}</em>
{% endif %} {% endif %}
</td> </td>
</tr> </tr>
{% if piggyBank.reminder %} {% if piggyBank.reminder %}
<tr> <tr>
<td>Reminder</td> <td>{{ 'reminder'|_ }}</td>
<td> <td>
{% if piggyBank.remind_me == 0 %} {% if piggyBank.remind_me == 0 %}
<em>(no reminder)</em> <em>{{ 'no_reminder'|_ }}</em>
{% else %} {% else %}
Every {{ 'every'|_ }}
{% if piggyBank.reminder_skip != 0 %} {% if piggyBank.reminder_skip != 0 %}
{{ piggyBank.reminder_skip }} {{ piggyBank.reminder_skip }}
{% else %} {% else %}
@@ -87,18 +87,18 @@
</tr> </tr>
{% endif %} {% endif %}
<tr> <tr>
<td>Reminders left</td> <td>{{ 'reminders_left'|_ }}</td>
<td>(in progress...)</td> <td>{{ 'todo'|_ }}</td>
</tr> </tr>
<tr> <tr>
<td>Expected amount per reminder</td> <td>{{ 'expected_amount_per_reminder'|_ }}</td>
<td>(in progress...)</td> <td>{{ 'todo'|_ }}</td>
</tr> </tr>
</table> </table>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-fw fa-clock-o"></i> Table <i class="fa fa-fw fa-clock-o"></i> {{ 'table'|_ }}
</div> </div>
{% include 'list/piggy-bank-events' %} {% include 'list/piggy-bank-events' %}
</div> </div>

View File

@@ -87,7 +87,7 @@
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p> <p>
<button type="submit" class="btn btn-lg btn-success"> <button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-pencil"></i> Update transaction <i class="fa fa-pencil"></i> {{ ('update_' ~ what)|_ }}
</button> </button>
</p> </p>
</div> </div>

View File

@@ -57,6 +57,24 @@ class BudgetControllerTest extends TestCase
} }
/**
* @covers FireflyIII\Http\Controllers\BudgetController::amount
*/
public function testAmountZero()
{
$repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$limitRepetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition');
$budget = $limitRepetition->budgetlimit->budget;
$this->be($budget->user);
$today = new Carbon;
$this->session(['start' => $today]);
$repository->shouldReceive('updateLimitAmount')->once()->andReturn($limitRepetition);
$this->call('POST', '/budgets/amount/' . $budget->id, ['amount' => 0, '_token' => 'replaceme']);
$this->assertResponseOk();
}
/** /**
* @covers FireflyIII\Http\Controllers\BudgetController::create * @covers FireflyIII\Http\Controllers\BudgetController::create
*/ */
@@ -122,20 +140,23 @@ class BudgetControllerTest extends TestCase
*/ */
public function testIndex() public function testIndex()
{ {
$currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency');
$budget = FactoryMuffin::create('FireflyIII\Models\Budget'); $budget = FactoryMuffin::create('FireflyIII\Models\Budget');
$this->be($budget->user); $this->be($budget->user);
$collection = new Collection; $collection = new Collection;
$collection->push($budget); $collection->push($budget);
$repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition');
$repository->shouldReceive('getActiveBudgets')->once()->andReturn($collection); $repository->shouldReceive('getActiveBudgets')->once()->andReturn($collection);
$repository->shouldReceive('getInactiveBudgets')->once()->andReturn($collection); $repository->shouldReceive('getInactiveBudgets')->once()->andReturn($collection);
$repository->shouldReceive('cleanupBudgets')->once(); $repository->shouldReceive('cleanupBudgets')->once();
$repository->shouldReceive('spentInPeriodCorrected')->once(); $repository->shouldReceive('spentInPeriodCorrected')->once();
$repository->shouldReceive('getCurrentRepetition')->once(); $repository->shouldReceive('getCurrentRepetition')->once()->andReturn($repetition);
Amount::shouldReceive('getCurrencySymbol')->andReturn('x'); Amount::shouldReceive('getCurrencySymbol')->andReturn('x');
Amount::shouldReceive('format')->andReturn('x'); Amount::shouldReceive('format')->andReturn('x');
Amount::shouldReceive('getCurrencyCode')->andReturn('X'); Amount::shouldReceive('getCurrencyCode')->andReturn('X');
Amount::shouldReceive('getDefaultCurrency')->andReturn($currency);
$this->call('GET', '/budgets'); $this->call('GET', '/budgets');
$this->assertResponseOk(); $this->assertResponseOk();

View File

@@ -38,6 +38,7 @@ class HelpControllerTest extends TestCase
/** /**
* Everything present and accounted for, and in cache: * Everything present and accounted for, and in cache:
*
* @covers FireflyIII\Http\Controllers\HelpController::show * @covers FireflyIII\Http\Controllers\HelpController::show
*/ */
public function testGetHelpText() public function testGetHelpText()
@@ -59,6 +60,7 @@ class HelpControllerTest extends TestCase
/** /**
* Everything present and accounted for, but not cached * Everything present and accounted for, but not cached
*
* @covers FireflyIII\Http\Controllers\HelpController::show * @covers FireflyIII\Http\Controllers\HelpController::show
*/ */
public function testGetHelpTextNoCache() public function testGetHelpTextNoCache()
@@ -82,6 +84,7 @@ class HelpControllerTest extends TestCase
/** /**
* No such route. * No such route.
*
* @covers FireflyIII\Http\Controllers\HelpController::show * @covers FireflyIII\Http\Controllers\HelpController::show
*/ */
public function testGetHelpTextNoRoute() public function testGetHelpTextNoRoute()

View File

@@ -233,16 +233,20 @@ class ReportHelperTest extends TestCase
$left->save(); $left->save();
// save meta for account: // save meta for account:
AccountMeta::create([ AccountMeta::create(
[
'account_id' => $left->id, 'account_id' => $left->id,
'name' => 'accountRole', 'name' => 'accountRole',
'data' => 'defaultAsset' 'data' => 'defaultAsset'
]); ]
AccountMeta::create([ );
AccountMeta::create(
[
'account_id' => $right->id, 'account_id' => $right->id,
'name' => 'accountRole', 'name' => 'accountRole',
'data' => 'defaultAsset' 'data' => 'defaultAsset'
]); ]
);
for ($i = 0; $i < 5; $i++) { for ($i = 0; $i < 5; $i++) {
@@ -292,16 +296,20 @@ class ReportHelperTest extends TestCase
$right->account_type_id = $asset->id; $right->account_type_id = $asset->id;
// save meta for account: // save meta for account:
AccountMeta::create([ AccountMeta::create(
[
'account_id' => $left->id, 'account_id' => $left->id,
'name' => 'accountRole', 'name' => 'accountRole',
'data' => 'defaultAsset' 'data' => 'defaultAsset'
]); ]
AccountMeta::create([ );
AccountMeta::create(
[
'account_id' => $right->id, 'account_id' => $right->id,
'name' => 'accountRole', 'name' => 'accountRole',
'data' => 'defaultAsset' 'data' => 'defaultAsset'
]); ]
);
$right->save(); $right->save();
$left->save(); $left->save();

View File

@@ -38,24 +38,6 @@ class TagModelTest extends TestCase
parent::tearDown(); parent::tearDown();
} }
/**
* @covers FireflyIII\Models\Tag::firstOrCreateEncrypted
*/
public function testFirstOrCreateEncryptedNew()
{
$tag = FactoryMuffin::create('FireflyIII\Models\Tag');
$search = [
'tagMode' => 'something',
'tag' => 'Something else',
'user_id' => $tag->user_id,
];
$result = Tag::firstOrCreateEncrypted($search);
$this->assertNotEquals($tag->id, $result->id);
}
/** /**
* @covers FireflyIII\Models\Tag::firstOrCreateEncrypted * @covers FireflyIII\Models\Tag::firstOrCreateEncrypted
*/ */
@@ -74,4 +56,22 @@ class TagModelTest extends TestCase
$this->assertEquals($tag->id, $result->id); $this->assertEquals($tag->id, $result->id);
} }
/**
* @covers FireflyIII\Models\Tag::firstOrCreateEncrypted
*/
public function testFirstOrCreateEncryptedNew()
{
$tag = FactoryMuffin::create('FireflyIII\Models\Tag');
$search = [
'tagMode' => 'something',
'tag' => 'Something else',
'user_id' => $tag->user_id,
];
$result = Tag::firstOrCreateEncrypted($search);
$this->assertNotEquals($tag->id, $result->id);
}
} }

View File

@@ -142,6 +142,21 @@ class TagRepositoryTest extends TestCase
} }
/**
* @covers FireflyIII\Repositories\Tag\TagRepository::connect
*/
public function testConnectInvalidType()
{
$journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal');
$tag = FactoryMuffin::create('FireflyIII\Models\Tag');
$tag->tagMode = 'Idontknow';
$tag->save();
$result = $this->object->connect($journal, $tag);
$this->assertFalse($result);
}
/** /**
* Once one or more journals have been accepted by the tag, others must match the asset account * Once one or more journals have been accepted by the tag, others must match the asset account
* id. For this to work, we must also create an asset account, and a transaction. * id. For this to work, we must also create an asset account, and a transaction.