mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/3.4.6'
This commit is contained in:
commit
f15932b2ac
20
README.md
20
README.md
@ -1,4 +1,4 @@
|
||||
# Firefly III (v3.4.5)
|
||||
# Firefly III (v3.4.6)
|
||||
|
||||
[](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
|
||||
[](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
|
||||
@ -82,11 +82,25 @@ and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**
|
||||
If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).
|
||||
This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site.
|
||||
|
||||
## Credits
|
||||
|
||||
Firefly III uses the following libraries and tools:
|
||||
|
||||
* The AdminLTE template by [Almsaseed Studio](https://almsaeedstudio.com/)
|
||||
* The [Google charts](https://developers.google.com/chart/) library.
|
||||
* [Bootstrap](http://getbootstrap.com/)
|
||||
* [Laravel](http://laravel.com/)
|
||||
* [Twig](http://twig.sensiolabs.org/)
|
||||
* For development, some of the excellent tools made by [Barry van den Heuvel](https://github.com/barryvdh)
|
||||
* [Bootstrap sortable](https://github.com/drvic10k/bootstrap-sortable) by [Matúš Brliť](https://github.com/drvic10k).
|
||||
* [Date range picker](https://github.com/dangrossman/bootstrap-daterangepicker/) by [Dan Grossman](https://github.com/dangrossman)
|
||||
* The [real favicon generator](http://realfavicongenerator.net/)
|
||||
* Various other open source components (see [composer.json](https://github.com/JC5/firefly-iii/blob/master/composer.json))
|
||||
|
||||
|
||||
## Current state
|
||||
|
||||
Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. One of the things on the todo-list
|
||||
is adding translations.
|
||||
Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. Translations are a work in progress.
|
||||
|
||||
Questions, ideas, bugs or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
|
||||
|
||||
|
43
app/Generator/Chart/Account/AccountChartGenerator.php
Normal file
43
app/Generator/Chart/Account/AccountChartGenerator.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface AccountChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Account
|
||||
*/
|
||||
interface AccountChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $accounts, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function single(Account $account, Carbon $start, Carbon $end);
|
||||
}
|
114
app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
Normal file
114
app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class ChartJsAccountChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Account
|
||||
*/
|
||||
class ChartJsAccountChartGenerator implements AccountChartGenerator
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
return $this->frontpage($accounts, $start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.monthAndDay.' . $language);
|
||||
$data = [
|
||||
'count' => 0,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
$current = clone $start;
|
||||
while ($current <= $end) {
|
||||
$data['labels'][] = $current->formatLocalized($format);
|
||||
$current->addDay();
|
||||
}
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$set = [
|
||||
'label' => $account->name,
|
||||
'fillColor' => 'rgba(220,220,220,0.2)',
|
||||
'strokeColor' => 'rgba(220,220,220,1)',
|
||||
'pointColor' => 'rgba(220,220,220,1)',
|
||||
'pointStrokeColor' => '#fff',
|
||||
'pointHighlightFill' => '#fff',
|
||||
'pointHighlightStroke' => 'rgba(220,220,220,1)',
|
||||
'data' => [],
|
||||
];
|
||||
$current = clone $start;
|
||||
while ($current <= $end) {
|
||||
$set['data'][] = Steam::balance($account, $current);
|
||||
$current->addDay();
|
||||
}
|
||||
$data['datasets'][] = $set;
|
||||
}
|
||||
$data['count'] = count($data['datasets']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function single(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.monthAndDay.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => $account->name,
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
$current = clone $start;
|
||||
|
||||
while ($end >= $current) {
|
||||
$data['labels'][] = $current->formatLocalized($format);
|
||||
$data['datasets'][0]['data'][] = Steam::balance($account, $current);
|
||||
$current->addDay();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
122
app/Generator/Chart/Account/GoogleAccountChartGenerator.php
Normal file
122
app/Generator/Chart/Account/GoogleAccountChartGenerator.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Steam;
|
||||
|
||||
|
||||
/**
|
||||
* Class GoogleAccountChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Account
|
||||
*/
|
||||
class GoogleAccountChartGenerator implements AccountChartGenerator
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
// make chart (original code):
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty($index);
|
||||
$index++;
|
||||
}
|
||||
$current = clone $start;
|
||||
$current->subDay();
|
||||
$today = Carbon::now();
|
||||
while ($end >= $current) {
|
||||
$row = [clone $current];
|
||||
$certain = $current < $today;
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = Steam::balance($account, $current);
|
||||
$row[] = $certain;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$current->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty($index);
|
||||
$index++;
|
||||
}
|
||||
$current = clone $start;
|
||||
$current->subDay();
|
||||
$today = Carbon::now();
|
||||
while ($end >= $current) {
|
||||
$row = [clone $current];
|
||||
$certain = $current < $today;
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = Steam::balance($account, $current);
|
||||
$row[] = $certain;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$current->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function single(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$current = clone $start;
|
||||
$today = new Carbon;
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty(1);
|
||||
|
||||
while ($end >= $current) {
|
||||
$certain = $current < $today;
|
||||
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
|
||||
$current->addDay();
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
32
app/Generator/Chart/Bill/BillChartGenerator.php
Normal file
32
app/Generator/Chart/Bill/BillChartGenerator.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
namespace FireflyIII\Generator\Chart\Bill;
|
||||
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface BillChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Bill
|
||||
*/
|
||||
interface BillChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $paid
|
||||
* @param Collection $unpaid
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $paid, Collection $unpaid);
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function single(Bill $bill, Collection $entries);
|
||||
|
||||
}
|
125
app/Generator/Chart/Bill/ChartJsBillChartGenerator.php
Normal file
125
app/Generator/Chart/Bill/ChartJsBillChartGenerator.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 27/06/15
|
||||
* Time: 17:21
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Bill;
|
||||
|
||||
use Config;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class ChartJsBillChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Bill
|
||||
*/
|
||||
class ChartJsBillChartGenerator implements BillChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $paid
|
||||
* @param Collection $unpaid
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $paid, Collection $unpaid)
|
||||
{
|
||||
|
||||
// loop paid and create single entry:
|
||||
$paidDescriptions = [];
|
||||
$paidAmount = 0;
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount += floatval($entry->amount);
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount += $amount;
|
||||
unset($amount, $description);
|
||||
}
|
||||
|
||||
$data = [
|
||||
[
|
||||
'value' => $unpaidAmount,
|
||||
'color' => 'rgba(53, 124, 165,0.7)',
|
||||
'highlight' => 'rgba(53, 124, 165,0.9)',
|
||||
'label' => trans('firefly.unpaid'),
|
||||
],
|
||||
[
|
||||
'value' => $paidAmount,
|
||||
'color' => 'rgba(0, 141, 76, 0.7)',
|
||||
'highlight' => 'rgba(0, 141, 76, 0.9)',
|
||||
'label' => trans('firefly.paid'),
|
||||
]
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function single(Bill $bill, Collection $entries)
|
||||
{
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 3,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
|
||||
// dataset: max amount
|
||||
// dataset: min amount
|
||||
// dataset: actual amount
|
||||
|
||||
$minAmount = [];
|
||||
$maxAmount = [];
|
||||
$actualAmount = [];
|
||||
foreach ($entries as $entry) {
|
||||
$data['labels'][] = $entry->date->formatLocalized($format);
|
||||
$minAmount[] = round($bill->amount_min, 2);
|
||||
$maxAmount[] = round($bill->amount_max, 2);
|
||||
$actualAmount[] = round($entry->amount, 2);
|
||||
}
|
||||
|
||||
$data['datasets'][] = [
|
||||
'label' => trans('firefly.minAmount'),
|
||||
'data' => $minAmount,
|
||||
];
|
||||
$data['datasets'][] = [
|
||||
'label' => trans('firefly.billEntry'),
|
||||
'data' => $actualAmount,
|
||||
];
|
||||
$data['datasets'][] = [
|
||||
'label' => trans('firefly.maxAmount'),
|
||||
'data' => $maxAmount,
|
||||
];
|
||||
|
||||
$data['count'] = count($data['datasets']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
87
app/Generator/Chart/Bill/GoogleBillChartGenerator.php
Normal file
87
app/Generator/Chart/Bill/GoogleBillChartGenerator.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Bill;
|
||||
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleBillChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Bill
|
||||
*/
|
||||
class GoogleBillChartGenerator implements BillChartGenerator
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $paid
|
||||
* @param Collection $unpaid
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $paid, Collection $unpaid)
|
||||
{
|
||||
// loop paid and create single entry:
|
||||
$paidDescriptions = [];
|
||||
$paidAmount = 0;
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount += floatval($entry->amount);
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount += $amount;
|
||||
unset($amount, $description);
|
||||
}
|
||||
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.name'), 'string');
|
||||
$chart->addColumn(trans('firefly.amount'), 'number');
|
||||
|
||||
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
|
||||
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function single(Bill $bill, Collection $entries)
|
||||
{
|
||||
// make chart:
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.date'), 'date');
|
||||
$chart->addColumn(trans('firefly.maxAmount'), 'number');
|
||||
$chart->addColumn(trans('firefly.minAmount'), 'number');
|
||||
$chart->addColumn(trans('firefly.billEntry'), 'number');
|
||||
|
||||
/** @var TransactionJournal $result */
|
||||
foreach ($entries as $result) {
|
||||
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
43
app/Generator/Chart/Budget/BudgetChartGenerator.php
Normal file
43
app/Generator/Chart/Budget/BudgetChartGenerator.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Budget;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface BudgetChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Budget
|
||||
*/
|
||||
interface BudgetChartGenerator
|
||||
{
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budget(Collection $entries);
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budgetLimit(Collection $entries);
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries);
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $budgets, Collection $entries);
|
||||
|
||||
}
|
139
app/Generator/Chart/Budget/ChartJsBudgetChartGenerator.php
Normal file
139
app/Generator/Chart/Budget/ChartJsBudgetChartGenerator.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Budget;
|
||||
|
||||
|
||||
use Config;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class ChartJsBudgetChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Budget
|
||||
*/
|
||||
class ChartJsBudgetChartGenerator implements BudgetChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budget(Collection $entries)
|
||||
{
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => 'Amount',
|
||||
'data' => [],
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$data['labels'][] = trans('firefly.spent');
|
||||
$data['datasets'][0]['data'][] = $entry[1];
|
||||
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budgetLimit(Collection $entries)
|
||||
{
|
||||
return $this->budget($entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries)
|
||||
{
|
||||
$data = [
|
||||
'count' => 0,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
// dataset: left
|
||||
// dataset: spent
|
||||
// dataset: overspent
|
||||
$left = [];
|
||||
$spent = [];
|
||||
$overspent = [];
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
|
||||
$data['labels'][] = $entry[0];
|
||||
$left[] = round($entry[1], 2);
|
||||
$spent[] = round($entry[2], 2);
|
||||
$overspent[] = round($entry[3], 2);
|
||||
}
|
||||
}
|
||||
|
||||
$data['datasets'][] = [
|
||||
'label' => trans('firefly.left'),
|
||||
'data' => $left,
|
||||
];
|
||||
$data['datasets'][] = [
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => $spent,
|
||||
];
|
||||
$data['datasets'][] = [
|
||||
'label' => trans('firefly.overspent'),
|
||||
'data' => $overspent,
|
||||
];
|
||||
|
||||
$data['count'] = count($data['datasets']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $budgets, Collection $entries)
|
||||
{
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 0,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
|
||||
foreach ($budgets as $budget) {
|
||||
$data['labels'][] = $budget->name;
|
||||
}
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$array = [
|
||||
'label' => $entry[0]->formatLocalized($format),
|
||||
'data' => [],
|
||||
];
|
||||
array_shift($entry);
|
||||
$array['data'] = $entry;
|
||||
$data['datasets'][] = $array;
|
||||
|
||||
}
|
||||
$data['count'] = count($data['datasets']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
101
app/Generator/Chart/Budget/GoogleBudgetChartGenerator.php
Normal file
101
app/Generator/Chart/Budget/GoogleBudgetChartGenerator.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Budget;
|
||||
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleBudgetChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Budget
|
||||
*/
|
||||
class GoogleBudgetChartGenerator implements BudgetChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budget(Collection $entries)
|
||||
{
|
||||
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRow($entry[0], $entry[1]);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function budgetLimit(Collection $entries)
|
||||
{
|
||||
return $this->budget($entries);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.budget'), 'string');
|
||||
$chart->addColumn(trans('firefly.left'), 'number');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
$chart->addColumn(trans('firefly.overspent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
|
||||
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $budgets, Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
// add columns:
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
foreach ($budgets as $budget) {
|
||||
$chart->addColumn($budget->name, 'number');
|
||||
}
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
44
app/Generator/Chart/Category/CategoryChartGenerator.php
Normal file
44
app/Generator/Chart/Category/CategoryChartGenerator.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Category;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface CategoryChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Category
|
||||
*/
|
||||
interface CategoryChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $entries);
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries);
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function month(Collection $entries);
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $categories, Collection $entries);
|
||||
}
|
116
app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
Normal file
116
app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Category;
|
||||
|
||||
use Config;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
|
||||
/**
|
||||
* Class ChartJsCategoryChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Category
|
||||
*/
|
||||
class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $entries)
|
||||
{
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$data['labels'][] = trans('firefly.spent');
|
||||
$data['datasets'][0]['data'][] = round($entry[1], 2);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries)
|
||||
{
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.spent'),
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry['sum'] != 0) {
|
||||
$data['labels'][] = $entry['name'];
|
||||
$data['datasets'][0]['data'][] = round($entry['sum'], 2);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function month(Collection $entries)
|
||||
{
|
||||
return $this->all($entries);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $categories, Collection $entries)
|
||||
{
|
||||
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 0,
|
||||
'labels' => [],
|
||||
'datasets' => [],
|
||||
];
|
||||
|
||||
foreach ($categories as $category) {
|
||||
$data['labels'][] = $category->name;
|
||||
}
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$date = $entry[0]->formatLocalized($format);
|
||||
array_shift($entry);
|
||||
$data['count']++;
|
||||
$data['datasets'][] = ['label' => $date, 'data' => $entry];
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
}
|
105
app/Generator/Chart/Category/GoogleCategoryChartGenerator.php
Normal file
105
app/Generator/Chart/Category/GoogleCategoryChartGenerator.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Category;
|
||||
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleCategoryChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Category
|
||||
*/
|
||||
class GoogleCategoryChartGenerator implements CategoryChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function all(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRow($entry[0], $entry[1]);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function frontpage(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.category'), 'string');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$sum = $entry['sum'];
|
||||
if ($sum != 0) {
|
||||
$chart->addRow($entry['name'], $sum);
|
||||
}
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function month(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRow($entry[0], $entry[1]);
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function year(Collection $categories, Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
foreach ($categories as $category) {
|
||||
$chart->addColumn($category->name, 'number');
|
||||
}
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
$chart->generate();
|
||||
return $chart->getData();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\PiggyBank;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
|
||||
/**
|
||||
* Class GooglePiggyBankChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\PiggyBank
|
||||
*/
|
||||
class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function history(Collection $set)
|
||||
{
|
||||
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 1,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => 'Diff',
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
$sum = '0';
|
||||
bcscale(2);
|
||||
foreach ($set as $entry) {
|
||||
$date = new Carbon($entry->date);
|
||||
$sum = bcadd($sum, $entry->sum);
|
||||
$data['labels'][] = $date->formatLocalized($format);
|
||||
$data['datasets'][0]['data'][] = round($sum, 2);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\PiggyBank;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Class GooglePiggyBankChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\PiggyBank
|
||||
*/
|
||||
class GooglePiggyBankChartGenerator implements PiggyBankChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function history(Collection $set)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.date'), 'date');
|
||||
$chart->addColumn(trans('firefly.balance'), 'number');
|
||||
|
||||
$sum = '0';
|
||||
bcscale(2);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$sum = bcadd($sum, $entry->sum);
|
||||
$chart->addRow(new Carbon($entry->date), $sum);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
20
app/Generator/Chart/PiggyBank/PiggyBankChartGenerator.php
Normal file
20
app/Generator/Chart/PiggyBank/PiggyBankChartGenerator.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\PiggyBank;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface PiggyBankChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\PiggyBank
|
||||
*/
|
||||
interface PiggyBankChartGenerator
|
||||
{
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function history(Collection $set);
|
||||
}
|
83
app/Generator/Chart/Report/ChartJsReportChartGenerator.php
Normal file
83
app/Generator/Chart/Report/ChartJsReportChartGenerator.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Report;
|
||||
|
||||
use Config;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class GoogleReportChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Report
|
||||
*/
|
||||
class ChartJsReportChartGenerator implements ReportChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOut(Collection $entries)
|
||||
{
|
||||
// language:
|
||||
$language = Preferences::get('language', 'en')->data;
|
||||
$format = Config::get('firefly.month.' . $language);
|
||||
|
||||
$data = [
|
||||
'count' => 2,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.income'),
|
||||
'data' => []
|
||||
],
|
||||
[
|
||||
'label' => trans('firefly.expenses'),
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
$data['labels'][] = $entry[0]->formatLocalized($format);
|
||||
$data['datasets'][0]['data'][] = round($entry[1], 2);
|
||||
$data['datasets'][1]['data'][] = round($entry[2], 2);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $income
|
||||
* @param string $expense
|
||||
* @param int $count
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOutSummarized($income, $expense, $count)
|
||||
{
|
||||
|
||||
$data = [
|
||||
'count' => 2,
|
||||
'labels' => [],
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => trans('firefly.income'),
|
||||
'data' => []
|
||||
],
|
||||
[
|
||||
'label' => trans('firefly.expenses'),
|
||||
'data' => []
|
||||
]
|
||||
],
|
||||
];
|
||||
$data['datasets'][0]['data'][] = round($income, 2);
|
||||
$data['datasets'][1]['data'][] = round($expense, 2);
|
||||
$data['datasets'][0]['data'][] = round(($income / $count), 2);
|
||||
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
|
||||
return $data;
|
||||
}
|
||||
}
|
58
app/Generator/Chart/Report/GoogleReportChartGenerator.php
Normal file
58
app/Generator/Chart/Report/GoogleReportChartGenerator.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Report;
|
||||
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class GoogleReportChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Report
|
||||
*/
|
||||
class GoogleReportChartGenerator implements ReportChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOut(Collection $entries)
|
||||
{
|
||||
$chart = new GChart;
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
$chart->addColumn(trans('firefly.income'), 'number');
|
||||
$chart->addColumn(trans('firefly.expenses'), 'number');
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($entries as $entry) {
|
||||
$chart->addRowArray($entry);
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $income
|
||||
* @param string $expense
|
||||
* @param int $count
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOutSummarized($income, $expense, $count)
|
||||
{
|
||||
$chart = new GChart;
|
||||
|
||||
$chart->addColumn(trans('firefly.summary'), 'string');
|
||||
$chart->addColumn(trans('firefly.income'), 'number');
|
||||
$chart->addColumn(trans('firefly.expenses'), 'number');
|
||||
$chart->addRow(trans('firefly.sum'), $income, $expense);
|
||||
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return $chart->getData();
|
||||
}
|
||||
}
|
31
app/Generator/Chart/Report/ReportChartGenerator.php
Normal file
31
app/Generator/Chart/Report/ReportChartGenerator.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Generator\Chart\Report;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface ReportChartGenerator
|
||||
*
|
||||
* @package FireflyIII\Generator\Chart\Report
|
||||
*/
|
||||
interface ReportChartGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Collection $entries
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOut(Collection $entries);
|
||||
|
||||
/**
|
||||
* @param string $income
|
||||
* @param string $expense
|
||||
* @param int $count
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearInOutSummarized($income, $expense, $count);
|
||||
|
||||
}
|
@ -51,9 +51,15 @@ class ConnectJournalToPiggyBank
|
||||
if (is_null($repetition)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$amount = $journal->correct_amount;
|
||||
bcscale(2);
|
||||
|
||||
$amount = $journal->actual_amount;
|
||||
// if piggy account matches source account, the amount is positive
|
||||
if ($piggyBank->account_id == $journal->source_account->id) {
|
||||
$amount = $amount * -1;
|
||||
}
|
||||
|
||||
|
||||
$repetition->currentamount = bcadd($repetition->currentamount, $amount);
|
||||
$repetition->save();
|
||||
|
||||
|
@ -1,176 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Reminders;
|
||||
|
||||
use Amount;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
* Class ReminderHelper
|
||||
*
|
||||
* @package FireflyIII\Helpers\Reminders
|
||||
*/
|
||||
class ReminderHelper implements ReminderHelperInterface
|
||||
{
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Reminder
|
||||
*/
|
||||
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end)
|
||||
{
|
||||
$reminder = Auth::user()->reminders()->where('remindersable_id', $piggyBank->id)->onDates($start, $end)->first();
|
||||
if (is_null($reminder)) {
|
||||
|
||||
if (!is_null($piggyBank->targetdate)) {
|
||||
// get ranges again, but now for the start date
|
||||
$ranges = $this->getReminderRanges($piggyBank, $start);
|
||||
$currentRep = $piggyBank->currentRelevantRep();
|
||||
$left = $piggyBank->targetamount - $currentRep->currentamount;
|
||||
$perReminder = count($ranges) == 0 ? $left : $left / count($ranges);
|
||||
} else {
|
||||
$perReminder = null;
|
||||
$ranges = [];
|
||||
$left = 0;
|
||||
}
|
||||
$metaData = [
|
||||
'perReminder' => $perReminder,
|
||||
'rangesCount' => count($ranges),
|
||||
'ranges' => $ranges,
|
||||
'leftToSave' => $left,
|
||||
];
|
||||
|
||||
$reminder = new Reminder;
|
||||
$reminder->user()->associate(Auth::user());
|
||||
$reminder->startdate = $start;
|
||||
$reminder->enddate = $end;
|
||||
$reminder->active = true;
|
||||
$reminder->metadata = $metaData;
|
||||
$reminder->notnow = false;
|
||||
$reminder->remindersable()->associate($piggyBank);
|
||||
$reminder->save();
|
||||
|
||||
return $reminder;
|
||||
|
||||
} else {
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create all reminders for a piggy bank for a given date.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function createReminders(PiggyBank $piggyBank, Carbon $date)
|
||||
{
|
||||
$ranges = $this->getReminderRanges($piggyBank);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
if ($date < $range['end'] && $date > $range['start']) {
|
||||
// create a reminder here!
|
||||
$this->createReminder($piggyBank, $range['start'], $range['end']);
|
||||
// stop looping, we're done.
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine will return an array consisting of two dates which indicate the start
|
||||
* and end date for each reminder that this piggy bank will have, if the piggy bank has
|
||||
* any reminders. For example:
|
||||
*
|
||||
* [12 mar - 15 mar]
|
||||
* [15 mar - 18 mar]
|
||||
*
|
||||
* etcetera.
|
||||
*
|
||||
* Array is filled with tiny arrays with Carbon objects in them.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param Carbon $date ;
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReminderRanges(PiggyBank $piggyBank, Carbon $date = null)
|
||||
{
|
||||
$ranges = [];
|
||||
if (is_null($date)) {
|
||||
$date = new Carbon;
|
||||
}
|
||||
|
||||
if ($piggyBank->remind_me === false) {
|
||||
return $ranges;
|
||||
}
|
||||
|
||||
if (!is_null($piggyBank->targetdate)) {
|
||||
// count back until now.
|
||||
$start = $piggyBank->targetdate;
|
||||
$end = $piggyBank->startdate;
|
||||
|
||||
while ($start > $end) {
|
||||
$currentEnd = clone $start;
|
||||
$start = Navigation::subtractPeriod($start, $piggyBank->reminder, 1);
|
||||
$currentStart = clone $start;
|
||||
$ranges[] = ['start' => clone $currentStart, 'end' => clone $currentEnd];
|
||||
}
|
||||
} else {
|
||||
$start = clone $piggyBank->startdate;
|
||||
while ($start < $date) {
|
||||
$currentStart = clone $start;
|
||||
$start = Navigation::addPeriod($start, $piggyBank->reminder, 0);
|
||||
$currentEnd = clone $start;
|
||||
$ranges[] = ['start' => clone $currentStart, 'end' => clone $currentEnd];
|
||||
}
|
||||
}
|
||||
|
||||
return $ranges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a reminder, finds the piggy bank and tells you what to do now.
|
||||
* Aka how much money to put in.
|
||||
*
|
||||
*
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReminderText(Reminder $reminder)
|
||||
{
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = $reminder->remindersable;
|
||||
|
||||
if (is_null($piggyBank)) {
|
||||
return trans('firefly.piggy_bank_not_exists');
|
||||
}
|
||||
|
||||
if (is_null($piggyBank->targetdate)) {
|
||||
return trans('firefly.add_any_amount_to_piggy', ['amount' => Amount::format($piggyBank->targetamount)]);
|
||||
}
|
||||
|
||||
$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))
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Reminders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
|
||||
/**
|
||||
* Interface ReminderHelperInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Reminders
|
||||
*/
|
||||
interface ReminderHelperInterface
|
||||
{
|
||||
/**
|
||||
* Takes a reminder, finds the piggy bank and tells you what to do now.
|
||||
* Aka how much money to put in.
|
||||
*
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReminderText(Reminder $reminder);
|
||||
|
||||
/**
|
||||
* This routine will return an array consisting of two dates which indicate the start
|
||||
* and end date for each reminder that this piggy bank will have, if the piggy bank has
|
||||
* any reminders. For example:
|
||||
*
|
||||
* [12 mar - 15 mar]
|
||||
* [15 mar - 18 mar]
|
||||
*
|
||||
* etcetera.
|
||||
*
|
||||
* Array is filled with tiny arrays with Carbon objects in them.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReminderRanges(PiggyBank $piggyBank);
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Reminder
|
||||
*/
|
||||
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Create all reminders for a piggy bank for a given date.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function createReminders(PiggyBank $piggyBank, Carbon $date);
|
||||
}
|
@ -2,17 +2,16 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
@ -21,10 +20,24 @@ use Steam;
|
||||
*/
|
||||
class AccountController extends Controller
|
||||
{
|
||||
|
||||
/** @var \FireflyIII\Generator\Chart\Account\AccountChartGenerator */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Account\AccountChartGenerator');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows the balances for all the user's accounts.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @param $year
|
||||
@ -33,7 +46,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function all(GChart $chart, AccountRepositoryInterface $repository, $year, $month, $shared = false)
|
||||
public function all(AccountRepositoryInterface $repository, $year, $month, $shared = false)
|
||||
{
|
||||
$start = new Carbon($year . '-' . $month . '-01');
|
||||
$end = clone $start;
|
||||
@ -49,9 +62,6 @@ class AccountController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
|
||||
/** @var Collection $accounts */
|
||||
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
|
||||
if ($shared === false) {
|
||||
@ -63,31 +73,8 @@ class AccountController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty($index);
|
||||
$index++;
|
||||
}
|
||||
$current = clone $start;
|
||||
$current->subDay();
|
||||
$today = Carbon::now();
|
||||
while ($end >= $current) {
|
||||
$row = [clone $current];
|
||||
$certain = $current < $today;
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = Steam::balance($account, $current);
|
||||
$row[] = $certain;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$current->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
// make chart:
|
||||
$data = $this->generator->all($accounts, $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -96,18 +83,15 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Shows the balances for all the user's frontpage accounts.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function frontpage(GChart $chart, AccountRepositoryInterface $repository)
|
||||
public function frontpage(AccountRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = clone Session::get('end', Carbon::now()->endOfMonth());
|
||||
$accounts = $repository->getFrontpageAccounts($frontPage);
|
||||
|
||||
// chart properties for cache:
|
||||
@ -120,30 +104,7 @@ class AccountController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty($index);
|
||||
$index++;
|
||||
}
|
||||
$current = clone $start;
|
||||
$current->subDay();
|
||||
$today = Carbon::now();
|
||||
while ($end >= $current) {
|
||||
$row = [clone $current];
|
||||
$certain = $current < $today;
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = Steam::balance($account, $current);
|
||||
$row[] = $certain;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$current->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$data = $this->generator->frontpage($accounts, $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -153,21 +114,16 @@ class AccountController extends Controller
|
||||
/**
|
||||
* Shows an account's balance for a single month.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function single(GChart $chart, Account $account)
|
||||
public function single(Account $account)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
|
||||
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
|
||||
$chart->addCertainty(1);
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$current = clone $start;
|
||||
$today = new Carbon;
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
@ -180,16 +136,7 @@ class AccountController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
while ($end >= $current) {
|
||||
$certain = $current < $today;
|
||||
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
|
||||
$current->addDay();
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$data = $this->generator->single($account, $start, $end);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
@ -2,14 +2,13 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
use Session;
|
||||
@ -22,60 +21,30 @@ use Steam;
|
||||
*/
|
||||
class BillController extends Controller
|
||||
{
|
||||
|
||||
/** @var \FireflyIII\Generator\Chart\Bill\BillChartGenerator */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* Shows the overview for a bill. The min/max amount and matched journals.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function single(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
$chart->addColumn(trans('firefly.date'), 'date');
|
||||
$chart->addColumn(trans('firefly.maxAmount'), 'number');
|
||||
$chart->addColumn(trans('firefly.minAmount'), 'number');
|
||||
$chart->addColumn(trans('firefly.billEntry'), 'number');
|
||||
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('single');
|
||||
$cache->addProperty('bill');
|
||||
$cache->addProperty($bill->id);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// get first transaction or today for start:
|
||||
$results = $repository->getJournals($bill);
|
||||
/** @var TransactionJournal $result */
|
||||
foreach ($results as $result) {
|
||||
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Bill\BillChartGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows all bills and whether or not theyve been paid this month (pie chart).
|
||||
*
|
||||
* @param GChart $chart
|
||||
*
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param AccountRepositoryInterface $accounts
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function frontpage(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
|
||||
public function frontpage(BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.name'), 'string');
|
||||
$chart->addColumn(trans('firefly.amount'), 'number');
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
@ -88,17 +57,13 @@ class BillController extends Controller
|
||||
$cache->addProperty('bills');
|
||||
$cache->addProperty('frontpage');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$bills = $repository->getActiveBills();
|
||||
$paid = new Collection; // journals.
|
||||
$unpaid = new Collection; // bills
|
||||
// loop paid and create single entry:
|
||||
$paidDescriptions = [];
|
||||
$paidAmount = 0;
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
@ -136,30 +101,35 @@ class BillController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// build chart:
|
||||
$data = $this->generator->frontpage($paid, $unpaid);
|
||||
$cache->store($data);
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount += floatval($entry->amount);
|
||||
/**
|
||||
* Shows the overview for a bill. The min/max amount and matched journals.
|
||||
*
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function single(BillRepositoryInterface $repository, Bill $bill)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('single');
|
||||
$cache->addProperty('bill');
|
||||
$cache->addProperty($bill->id);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount += $amount;
|
||||
unset($amount, $description);
|
||||
}
|
||||
// get first transaction or today for start:
|
||||
$results = $repository->getJournals($bill);
|
||||
|
||||
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
|
||||
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$data = $this->generator->single($bill, $results);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
@ -22,19 +22,30 @@ use Session;
|
||||
*/
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
|
||||
/** @var \FireflyIII\Generator\Chart\Budget\BudgetChartGenerator */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GChart $chart
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function budget(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget)
|
||||
public function budget(BudgetRepositoryInterface $repository, Budget $budget)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
|
||||
// dates and times
|
||||
$first = $repository->getFirstBudgetLimitDate($budget);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$last = Session::get('end', new Carbon);
|
||||
@ -47,33 +58,23 @@ class BudgetController extends Controller
|
||||
$cache->addProperty($first);
|
||||
$cache->addProperty($last);
|
||||
$cache->addProperty('budget');
|
||||
$cache->addProperty('budget');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$entries = new Collection;
|
||||
|
||||
while ($first < $last) {
|
||||
$end = Navigation::addPeriod($first, $range, 0);
|
||||
$end->subDay();
|
||||
|
||||
// start date for chart.
|
||||
$chartDate = clone $end;
|
||||
$chartDate->startOfMonth();
|
||||
|
||||
$spent = $repository->spentInPeriodCorrected($budget, $first, $end);
|
||||
$chart->addRow($chartDate, $spent);
|
||||
|
||||
$entries->push([$chartDate, $spent]);
|
||||
$first = Navigation::addPeriod($first, $range, 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
|
||||
|
||||
$data = $this->generator->budget($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -82,14 +83,13 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* Shows the amount left in a specific budget limit.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param Budget $budget
|
||||
* @param LimitRepetition $repetition
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function budgetLimit(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
|
||||
public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
|
||||
{
|
||||
$start = clone $repetition->startdate;
|
||||
$end = $repetition->enddate;
|
||||
@ -106,11 +106,8 @@ class BudgetController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$chart->addColumn(trans('firefly.day'), 'date');
|
||||
$chart->addColumn(trans('firefly.left'), 'number');
|
||||
|
||||
|
||||
$amount = $repetition->amount;
|
||||
$entries = new Collection;
|
||||
$amount = $repetition->amount;
|
||||
|
||||
while ($start <= $end) {
|
||||
/*
|
||||
@ -118,12 +115,11 @@ class BudgetController extends Controller
|
||||
*/
|
||||
$sum = $repository->expensesOnDayCorrected($budget, $start);
|
||||
$amount += $sum;
|
||||
$chart->addRow(clone $start, $amount);
|
||||
$entries->push([clone $start, $amount]);
|
||||
$start->addDay();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$data = $this->generator->budgetLimit($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -133,18 +129,12 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* Shows a budget list with spent/left/overspent.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function frontpage(GChart $chart, BudgetRepositoryInterface $repository)
|
||||
public function frontpage(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.budget'), 'string');
|
||||
$chart->addColumn(trans('firefly.left'), 'number');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
$chart->addColumn(trans('firefly.overspent'), 'number');
|
||||
|
||||
$budgets = $repository->getBudgets();
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
@ -160,43 +150,38 @@ class BudgetController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
bcscale(2);
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
|
||||
if ($repetitions->count() == 0) {
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true);
|
||||
$allEntries->push([$budget->name, 0, 0, $expenses]);
|
||||
$allEntries->push([$budget->name, 0, 0, $expenses, 0, 0]);
|
||||
continue;
|
||||
}
|
||||
/** @var LimitRepetition $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
|
||||
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
|
||||
$spent = $expenses > floatval($repetition->amount) ? floatval($repetition->amount) : $expenses;
|
||||
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
|
||||
$allEntries->push(
|
||||
[$budget->name . ' (' . $repetition->startdate->formatLocalized($this->monthAndDayFormat) . ')',
|
||||
$left,
|
||||
$spent,
|
||||
$overspent
|
||||
]
|
||||
);
|
||||
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
|
||||
// $left can be less than zero.
|
||||
// $overspent can be more than zero ( = overspending)
|
||||
|
||||
$left = max(bcsub($repetition->amount, $expenses), 0); // limited at zero.
|
||||
$overspent = max(bcsub($expenses, $repetition->amount), 0); // limited at zero.
|
||||
$name = $budget->name;
|
||||
|
||||
// $spent is maxed to the repetition amount:
|
||||
$spent = $expenses > $repetition->amount ? $repetition->amount : $expenses;
|
||||
|
||||
|
||||
$allEntries->push([$name, $left, $spent, $overspent, $repetition->amount, $expenses]);
|
||||
}
|
||||
}
|
||||
|
||||
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1;
|
||||
$allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses]);
|
||||
$allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses, 0, 0]);
|
||||
|
||||
foreach ($allEntries as $entry) {
|
||||
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
|
||||
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
|
||||
}
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$data = $this->generator->frontpage($allEntries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
@ -206,14 +191,13 @@ class BudgetController extends Controller
|
||||
/**
|
||||
* Show a yearly overview for a budget.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param $year
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function year(GChart $chart, BudgetRepositoryInterface $repository, $year, $shared = false)
|
||||
public function year(BudgetRepositoryInterface $repository, $year, $shared = false)
|
||||
{
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
@ -230,17 +214,12 @@ class BudgetController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// add columns:
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
foreach ($budgets as $budget) {
|
||||
$chart->addColumn($budget->name, 'number');
|
||||
}
|
||||
$entries = new Collection;
|
||||
|
||||
while ($start < $end) {
|
||||
// month is the current end of the period:
|
||||
$month = clone $start;
|
||||
$month->endOfMonth();
|
||||
// make a row:
|
||||
$row = [clone $start];
|
||||
|
||||
// each budget, fill the row:
|
||||
@ -248,14 +227,11 @@ class BudgetController extends Controller
|
||||
$spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
|
||||
$row[] = $spent;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
|
||||
$entries->push($row);
|
||||
$start->endOfMonth()->addDay();
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$data = $this->generator->year($budgets, $entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
@ -3,12 +3,13 @@
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
@ -21,42 +22,61 @@ use Session;
|
||||
*/
|
||||
class CategoryController extends Controller
|
||||
{
|
||||
/** @var \FireflyIII\Generator\Chart\Category\CategoryChartGenerator */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Category\CategoryChartGenerator');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show an overview for a category for all time, per month/week/year.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function all(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
|
||||
public function all(CategoryRepositoryInterface $repository, Category $category)
|
||||
{
|
||||
// oldest transaction in category:
|
||||
$start = $repository->getFirstActivityDate($category);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
// jump to start of week / month / year / etc
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = new Carbon;
|
||||
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
$entries = new Collection;
|
||||
|
||||
|
||||
$end = new Carbon;
|
||||
while ($start <= $end) {
|
||||
|
||||
$currentEnd = Navigation::endOfPeriod($start, $range);
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
|
||||
$chart->addRow(clone $start, $spent);
|
||||
|
||||
$start = Navigation::addPeriod($start, $range, 0);
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('all');
|
||||
$cache->addProperty('categories');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
while ($start <= $end) {
|
||||
$currentEnd = Navigation::endOfPeriod($start, $range);
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
|
||||
$entries->push([clone $start, $spent]);
|
||||
$start = Navigation::addPeriod($start, $range, 0);
|
||||
|
||||
return Response::json($chart->getData());
|
||||
}
|
||||
|
||||
$data = $this->generator->all($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
|
||||
}
|
||||
@ -64,15 +84,12 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* Show this month's category overview.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function frontpage(GChart $chart, CategoryRepositoryInterface $repository)
|
||||
public function frontpage(CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.category'), 'string');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
@ -87,11 +104,10 @@ class CategoryController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$set = $repository->getCategoriesAndExpensesCorrected($start, $end);
|
||||
|
||||
$array = $repository->getCategoriesAndExpensesCorrected($start, $end);
|
||||
// sort by callback:
|
||||
uasort(
|
||||
$set,
|
||||
$array,
|
||||
function ($left, $right) {
|
||||
if ($left['sum'] == $right['sum']) {
|
||||
return 0;
|
||||
@ -100,48 +116,48 @@ class CategoryController extends Controller
|
||||
return ($left['sum'] < $right['sum']) ? 1 : -1;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$sum = floatval($entry['sum']);
|
||||
if ($sum != 0) {
|
||||
$chart->addRow($entry['name'], $sum);
|
||||
}
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
$data = $chart->getData();
|
||||
$cache->store($data);
|
||||
$set = new Collection($array);
|
||||
$data = $this->generator->frontpage($set);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GChart $chart
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function month(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
|
||||
public function month(CategoryRepositoryInterface $repository, Category $category)
|
||||
{
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
|
||||
$chart->addColumn(trans('firefly.period'), 'date');
|
||||
$chart->addColumn(trans('firefly.spent'), 'number');
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty($category->id);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('month');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$entries = new Collection;
|
||||
|
||||
|
||||
while ($start <= $end) {
|
||||
$spent = $repository->spentOnDaySumCorrected($category, $start);
|
||||
$chart->addRow(clone $start, $spent);
|
||||
|
||||
$entries->push([clone $start, $spent]);
|
||||
$start->addDay();
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
$data = $this->generator->month($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($chart->getData());
|
||||
return Response::json($data);
|
||||
|
||||
|
||||
}
|
||||
@ -149,25 +165,31 @@ class CategoryController extends Controller
|
||||
/**
|
||||
* This chart will only show expenses.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
* @param $year
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function year(GChart $chart, CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||
public function year(CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||
{
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('year');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$categories = $repository->getCategories();
|
||||
|
||||
// add columns:
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
foreach ($categories as $category) {
|
||||
$chart->addColumn($category->name, 'number');
|
||||
}
|
||||
$entries = new Collection;
|
||||
|
||||
while ($start < $end) {
|
||||
// month is the current end of the period:
|
||||
@ -181,13 +203,14 @@ class CategoryController extends Controller
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
||||
$row[] = $spent;
|
||||
}
|
||||
$chart->addRowArray($row);
|
||||
$entries->push($row);
|
||||
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
$data = $this->generator->year($categories, $entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($chart->getData());
|
||||
return Response::json($data);
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,11 @@
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
|
||||
@ -18,32 +18,44 @@ use Response;
|
||||
*/
|
||||
class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
/** @var \FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator');
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the piggy bank history.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function history(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
public function history(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
$chart->addColumn(trans('firefly.date'), 'date');
|
||||
$chart->addColumn(trans('firefly.balance'), 'number');
|
||||
|
||||
/** @var Collection $set */
|
||||
$set = $repository->getEventSummarySet($piggyBank);
|
||||
$sum = 0;
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$sum += floatval($entry->sum);
|
||||
$chart->addRow(new Carbon($entry->date), $sum);
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('piggy-history');
|
||||
$cache->addProperty($piggyBank->id);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
/** @var Collection $set */
|
||||
$set = new Collection($repository->getEventSummarySet($piggyBank));
|
||||
$data = $this->generator->history($set);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($chart->getData());
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,12 @@
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\ReportQueryInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
@ -17,85 +19,108 @@ use Response;
|
||||
class ReportController extends Controller
|
||||
{
|
||||
|
||||
/** @var \FireflyIII\Generator\Chart\Report\ReportChartGenerator */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = App::make('FireflyIII\Generator\Chart\Report\ReportChartGenerator');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Summarizes all income and expenses, per month, for a given year.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param ReportQueryInterface $query
|
||||
* @param $year
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function yearInOut(GChart $chart, ReportQueryInterface $query, $year, $shared = false)
|
||||
public function yearInOut(ReportQueryInterface $query, $year, $shared = false)
|
||||
{
|
||||
// get start and end of year
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
|
||||
$chart->addColumn(trans('firefly.month'), 'date');
|
||||
$chart->addColumn(trans('firefly.income'), 'number');
|
||||
$chart->addColumn(trans('firefly.expenses'), 'number');
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('yearInOut');
|
||||
$cache->addProperty($year);
|
||||
$cache->addProperty($shared);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$entries = new Collection;
|
||||
while ($start < $end) {
|
||||
$month = clone $start;
|
||||
$month->endOfMonth();
|
||||
// total income and total expenses:
|
||||
$incomeSum = floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$expenseSum = floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$incomeSum = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount');
|
||||
$expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount');
|
||||
|
||||
$chart->addRow(clone $start, $incomeSum, $expenseSum);
|
||||
$entries->push([clone $start, $incomeSum, $expenseSum]);
|
||||
$start->addMonth();
|
||||
}
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
$data = $this->generator->yearInOut($entries);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarizes all income and expenses for a given year. Gives a total and an average.
|
||||
*
|
||||
* @param GChart $chart
|
||||
* @param ReportQueryInterface $query
|
||||
* @param $year
|
||||
* @param bool $shared
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function yearInOutSummarized(GChart $chart, ReportQueryInterface $query, $year, $shared = false)
|
||||
public function yearInOutSummarized(ReportQueryInterface $query, $year, $shared = false)
|
||||
{
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('yearInOutSummarized');
|
||||
$cache->addProperty($year);
|
||||
$cache->addProperty($shared);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$start = new Carbon($year . '-01-01');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$income = 0;
|
||||
$expense = 0;
|
||||
$income = '0';
|
||||
$expense = '0';
|
||||
$count = 0;
|
||||
|
||||
$chart->addColumn(trans('firefly.summary'), 'string');
|
||||
$chart->addColumn(trans('firefly.income'), 'number');
|
||||
$chart->addColumn(trans('firefly.expenses'), 'number');
|
||||
bcscale(2);
|
||||
|
||||
while ($start < $end) {
|
||||
$month = clone $start;
|
||||
$month->endOfMonth();
|
||||
// total income and total expenses:
|
||||
$income += floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$expense += floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$income = bcadd($income, $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$expense = bcadd($expense, $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
|
||||
$count++;
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
// add total + average:
|
||||
$chart->addRow(trans('firefly.sum'), $income, $expense);
|
||||
$count = $count > 0 ? $count : 1;
|
||||
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
|
||||
$data = $this->generator->yearInOutSummarized($income, $expense, $count);
|
||||
$cache->store($data);
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -142,8 +142,6 @@ class PiggyBankController extends Controller
|
||||
'account_id' => $piggyBank->account_id,
|
||||
'targetamount' => $piggyBank->targetamount,
|
||||
'targetdate' => $targetDate,
|
||||
'reminder' => $piggyBank->reminder,
|
||||
'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
Session::flash('gaEventCategory', 'piggy-banks');
|
||||
@ -299,12 +297,7 @@ class PiggyBankController extends Controller
|
||||
*/
|
||||
public function show(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
|
||||
{
|
||||
$events = $repository->getEvents($piggyBank);
|
||||
|
||||
/*
|
||||
* Number of reminders:
|
||||
*/
|
||||
|
||||
$events = $repository->getEvents($piggyBank);
|
||||
$subTitle = e($piggyBank->name);
|
||||
|
||||
return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle'));
|
||||
@ -321,13 +314,13 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
$piggyBankData = [
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'reminder' => $request->get('reminder'),
|
||||
'remind_me' => $request->get('remind_me'),
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'remind_me' => false,
|
||||
'reminder_skip' => 0,
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
];
|
||||
|
||||
$piggyBank = $repository->store($piggyBankData);
|
||||
@ -356,13 +349,13 @@ class PiggyBankController extends Controller
|
||||
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
|
||||
{
|
||||
$piggyBankData = [
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'reminder' => $request->get('reminder'),
|
||||
'remind_me' => $request->get('remind_me')
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'remind_me' => false,
|
||||
'reminder_skip' => 0,
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
];
|
||||
|
||||
$piggyBank = $repository->update($piggyBank, $piggyBankData);
|
||||
|
@ -1,92 +0,0 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Repositories\Reminder\ReminderRepositoryInterface;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
|
||||
/**
|
||||
* Class ReminderController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class ReminderController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function act(Reminder $reminder)
|
||||
{
|
||||
$data = [
|
||||
'description' => 'Money for piggy bank "' . $reminder->remindersable->name . '"',
|
||||
'amount' => round($reminder->metadata->perReminder, 2),
|
||||
'account_to_id' => $reminder->remindersable->account_id,
|
||||
'piggy_bank_id' => $reminder->remindersable_id,
|
||||
'reminder_id' => $reminder->id,
|
||||
];
|
||||
Session::flash('_old_input', $data);
|
||||
|
||||
return Redirect::route('transactions.create', ['transfer']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function dismiss(Reminder $reminder)
|
||||
{
|
||||
$reminder->notnow = true;
|
||||
$reminder->save();
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReminderRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index(ReminderRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
|
||||
$active = $repository->getActiveReminders();
|
||||
$expired = $repository->getExpiredReminders();
|
||||
$inactive = $repository->getInactiveReminders();
|
||||
$dismissed = $repository->getDismissedReminders();
|
||||
|
||||
$title = 'Reminders';
|
||||
$mainTitleIcon = 'fa-clock-o';
|
||||
|
||||
return view('reminders.index', compact('dismissed', 'expired', 'inactive', 'active', 'title', 'mainTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show(Reminder $reminder)
|
||||
{
|
||||
$title = trans('firefly.reminder');
|
||||
$mainTitleIcon = 'fa-clock-o';
|
||||
if ($reminder->notnow === true) {
|
||||
$subTitle = trans('firefly.dismissed_reminder_for_piggy', ['name' => $reminder->remindersable->name]);
|
||||
} else {
|
||||
$subTitle = trans('firefly.reminder_for_piggy', ['name' => $reminder->remindersable->name]);
|
||||
}
|
||||
|
||||
return view('reminders.show', compact('reminder', 'title', 'subTitle', 'mainTitleIcon'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -180,12 +180,12 @@ class TagController extends Controller
|
||||
$helpHidden = $helpHiddenPref->data;
|
||||
|
||||
// group years.
|
||||
$types = ['nothing','balancingAct', 'advancePayment'];
|
||||
$types = ['nothing', 'balancingAct', 'advancePayment'];
|
||||
|
||||
// loop each types and get the tags, group them by year.
|
||||
$collection = [];
|
||||
foreach ($types as $type) {
|
||||
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date','ASC')->get();
|
||||
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get();
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
$year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year;
|
||||
@ -195,7 +195,7 @@ class TagController extends Controller
|
||||
}
|
||||
|
||||
|
||||
return view('tags.index', compact('title', 'mainTitleIcon','types', 'helpHidden', 'collection'));
|
||||
return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'helpHidden', 'collection'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -208,7 +208,7 @@ class TagController extends Controller
|
||||
$subTitle = $tag->tag;
|
||||
$subTitleIcon = 'fa-tag';
|
||||
|
||||
return view('tags.show', compact('tag', 'subTitle','types', 'subTitleIcon'));
|
||||
return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,20 +159,12 @@ class TransactionController extends Controller
|
||||
|
||||
if ($journal->transactionType->type == 'Withdrawal') {
|
||||
$preFilled['account_id'] = $journal->source_account->id;
|
||||
$preFilled['expense_account'] = $journal->destination_account->name;
|
||||
$preFilled['expense_account'] = $journal->destination_account->name_for_editform;
|
||||
} else {
|
||||
$preFilled['account_id'] = $journal->destination_account->id;
|
||||
$preFilled['revenue_account'] = $journal->source_account->name;
|
||||
$preFilled['revenue_account'] = $journal->source_account->name_for_editform;
|
||||
}
|
||||
|
||||
if ($journal->destination_account->accountType->type == 'Cash account') {
|
||||
$preFilled['expense_account'] = '';
|
||||
}
|
||||
if ($journal->source_account->accountType->type == 'Cash account') {
|
||||
$preFilled['revenue_account'] = '';
|
||||
}
|
||||
|
||||
|
||||
$preFilled['account_from_id'] = $journal->source_account->id;
|
||||
$preFilled['account_to_id'] = $journal->destination_account->id;
|
||||
|
||||
@ -296,8 +288,6 @@ class TransactionController extends Controller
|
||||
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
|
||||
}
|
||||
|
||||
$repository->deactivateReminder($request->get('reminder_id'));
|
||||
|
||||
Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
|
||||
Preferences::mark();
|
||||
|
||||
|
@ -37,7 +37,6 @@ class Kernel extends HttpKernel
|
||||
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
|
||||
'guest' => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated',
|
||||
'range' => 'FireflyIII\Http\Middleware\Range',
|
||||
'reminders' => 'FireflyIII\Http\Middleware\Reminders',
|
||||
|
||||
];
|
||||
|
||||
|
@ -1,96 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Middleware;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class Reminders
|
||||
*
|
||||
* @package FireflyIII\Http\Middleware
|
||||
*/
|
||||
class Reminders
|
||||
{
|
||||
/**
|
||||
* The Guard implementation.
|
||||
*
|
||||
* @var Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new filter instance.
|
||||
*
|
||||
* @param Guard $auth
|
||||
*
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
|
||||
|
||||
$user = $this->auth->user();
|
||||
if ($this->auth->check() && !$request->isXmlHttpRequest() && $user instanceof User) {
|
||||
// do reminders stuff.
|
||||
|
||||
// abuse CacheProperties to find out if we need to do this:
|
||||
$cache = new CacheProperties;
|
||||
|
||||
$cache->addProperty('reminders');
|
||||
if ($cache->has()) {
|
||||
$reminders = $cache->get();
|
||||
View::share('reminders', $reminders);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
$piggyBanks = $user->piggyBanks()->where('remind_me', 1)->get();
|
||||
|
||||
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */
|
||||
$helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
foreach ($piggyBanks as $piggyBank) {
|
||||
$helper->createReminders($piggyBank, new Carbon);
|
||||
}
|
||||
// delete invalid reminders
|
||||
// this is a construction SQLITE cannot handle :(
|
||||
if (env('DB_CONNECTION') != 'sqlite') {
|
||||
Reminder::whereUserId($user->id)->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->delete();
|
||||
}
|
||||
|
||||
// get and list active reminders:
|
||||
$reminders = $user->reminders()->today()->get();
|
||||
$reminders->each(
|
||||
function (Reminder $reminder) use ($helper) {
|
||||
$reminder->description = $helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
$cache->store($reminders);
|
||||
View::share('reminders', $reminders);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@ -61,7 +61,6 @@ class JournalFormRequest extends Request
|
||||
'what' => 'required|in:withdrawal,deposit,transfer',
|
||||
'amount' => 'numeric|required|min:0.01',
|
||||
'date' => 'required|date',
|
||||
'reminder_id' => 'numeric|exists:reminders,id',
|
||||
'amount_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
|
||||
];
|
||||
|
@ -42,9 +42,6 @@ class PiggyBankFormRequest extends Request
|
||||
'amount_currency_id' => 'exists:transaction_currencies,id',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => $targetDateRule,
|
||||
'reminder' => 'in:day,week,quarter,month,year',
|
||||
'reminder_skip' => 'integer|min:0|max:99',
|
||||
'remind_me' => 'boolean|piggyBankReminder',
|
||||
'order' => 'integer|min:1',
|
||||
|
||||
];
|
||||
|
@ -7,7 +7,6 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@ -286,25 +285,6 @@ Breadcrumbs::register(
|
||||
}
|
||||
);
|
||||
|
||||
// reminders
|
||||
Breadcrumbs::register(
|
||||
'reminders.index', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push(trans('breadcrumbs.reminders'), route('reminders.index'));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// reminders
|
||||
Breadcrumbs::register(
|
||||
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
|
||||
$breadcrumbs->parent('reminders.index');
|
||||
$breadcrumbs->push(trans('breadcrumbs.reminder', ['id' => e($reminder->id)]), route('reminders.show', [$reminder->id]));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// reports
|
||||
Breadcrumbs::register(
|
||||
'reports.index', function (Generator $breadcrumbs) {
|
||||
|
@ -5,7 +5,6 @@ use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
@ -81,19 +80,6 @@ Route::bind(
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'reminder', function ($value) {
|
||||
if (Auth::check()) {
|
||||
$object = Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
|
||||
if ($object) {
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'limitrepetition', function ($value) {
|
||||
if (Auth::check()) {
|
||||
@ -140,23 +126,6 @@ Route::bind(
|
||||
}
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnusedParameterInspection */
|
||||
Route::bind(
|
||||
'reminder', function ($value) {
|
||||
if (Auth::check()) {
|
||||
/** @var \FireflyIII\Models\Reminder $object */
|
||||
$object = Reminder::find($value);
|
||||
if ($object) {
|
||||
if ($object->remindersable->account->user_id == Auth::user()->id) {
|
||||
return $object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException;
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'tag', function ($value) {
|
||||
if (Auth::check()) {
|
||||
@ -185,7 +154,7 @@ Route::controllers(
|
||||
|
||||
|
||||
Route::group(
|
||||
['middleware' => ['auth', 'range', 'reminders']], function () {
|
||||
['middleware' => ['auth', 'range']], function () {
|
||||
|
||||
/**
|
||||
* Home Controller
|
||||
@ -355,14 +324,6 @@ Route::group(
|
||||
Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'delete-account-post']);
|
||||
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']);
|
||||
|
||||
/**
|
||||
* Reminder Controller
|
||||
*/
|
||||
Route::get('/reminders', ['uses' => 'ReminderController@index', 'as' => 'reminders.index']);
|
||||
Route::get('/reminder/dismiss/{reminder}', ['uses' => 'ReminderController@dismiss', 'as' => 'reminders.dismiss']);
|
||||
Route::get('/reminder/act/{reminder}', ['uses' => 'ReminderController@act', 'as' => 'reminders.act']);
|
||||
Route::get('/reminder/{reminder}', ['uses' => 'ReminderController@show', 'as' => 'reminders.show']);
|
||||
|
||||
/**
|
||||
* Report Controller
|
||||
*/
|
||||
|
@ -180,6 +180,20 @@ class Account extends Model
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameForEditformAttribute()
|
||||
{
|
||||
$name = $this->name;
|
||||
if ($this->accountType->type == 'Cash account') {
|
||||
$name = '';
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
|
@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* FireflyIII\Models\Bill
|
||||
*
|
||||
* @codeCoverageIgnore Class Bill
|
||||
* @package FireflyIII\Models
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
|
@ -19,15 +19,11 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @property string $targetamount_encrypted
|
||||
* @property \Carbon\Carbon $startdate
|
||||
* @property \Carbon\Carbon $targetdate
|
||||
* @property string $reminder
|
||||
* @property integer $reminder_skip
|
||||
* @property boolean $remind_me
|
||||
* @property integer $order
|
||||
* @property boolean $encrypted
|
||||
* @property-read \FireflyIII\Models\Account $account
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Reminder[] $reminders
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value)
|
||||
@ -38,9 +34,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamountEncrypted($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
|
||||
* @property PiggyBankRepetition currentRep
|
||||
@ -50,7 +43,7 @@ class PiggyBank extends Model
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable
|
||||
= ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
|
||||
= ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate', 'remind_me', 'reminder_skip'];
|
||||
protected $hidden = ['targetamount_encrypted', 'encrypted'];
|
||||
|
||||
/**
|
||||
@ -112,17 +105,6 @@ class PiggyBank extends Model
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getRemindMeAttribute($value)
|
||||
{
|
||||
return intval($value) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
@ -131,14 +113,6 @@ class PiggyBank extends Model
|
||||
return $this->hasMany('FireflyIII\Models\PiggyBankEvent');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||
*/
|
||||
public function reminders()
|
||||
{
|
||||
return $this->morphMany('FireflyIII\Models\Reminder', 'remindersable');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
|
@ -1,148 +0,0 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class Reminder
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
* @package FireflyIII\Models
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property integer $user_id
|
||||
* @property \Carbon\Carbon $startdate
|
||||
* @property \Carbon\Carbon $enddate
|
||||
* @property boolean $active
|
||||
* @property boolean $notnow
|
||||
* @property integer $remindersable_id
|
||||
* @property string $remindersable_type
|
||||
* @property string $metadata
|
||||
* @property boolean $encrypted
|
||||
* @property-read \ $remindersable
|
||||
* @property-read \FireflyIII\User $user
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereUpdatedAt($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereUserId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereStartdate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereEnddate($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereActive($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereNotnow($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereRemindersableId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereRemindersableType($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereMetadata($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereEncrypted($value)
|
||||
* @method static \FireflyIII\Models\Reminder onDates($start, $end)
|
||||
* @method static \FireflyIII\Models\Reminder today()
|
||||
* @property string description
|
||||
*/
|
||||
class Reminder extends Model
|
||||
{
|
||||
|
||||
|
||||
protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type',];
|
||||
protected $hidden = ['encrypted'];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getActiveAttribute($value)
|
||||
{
|
||||
return intval($value) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'startdate', 'enddate'];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadataAttribute($value)
|
||||
{
|
||||
if (intval($this->encrypted) == 1) {
|
||||
return json_decode(Crypt::decrypt($value));
|
||||
}
|
||||
|
||||
return json_decode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getNotnowAttribute($value)
|
||||
{
|
||||
return intval($value) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function remindersable()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param EloquentBuilder $query
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $end)
|
||||
{
|
||||
return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param EloquentBuilder $query
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function scopeToday(EloquentBuilder $query)
|
||||
{
|
||||
$today = new Carbon;
|
||||
|
||||
return $query->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))->where('active', 1)
|
||||
->where('notnow', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param $value
|
||||
*/
|
||||
public function setMetadataAttribute($value)
|
||||
{
|
||||
$this->attributes['encrypted'] = true;
|
||||
$this->attributes['metadata'] = Crypt::encrypt(json_encode($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
}
|
@ -159,12 +159,12 @@ class TransactionJournal extends Model
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->tag_count === 1) {
|
||||
if (intval($this->tag_count) === 1) {
|
||||
// get amount for single tag:
|
||||
$amount = $this->amountByTag($this->tags()->first(), $amount);
|
||||
}
|
||||
|
||||
if ($this->tag_count > 1) {
|
||||
if (intval($this->tag_count) > 1) {
|
||||
// get amount for either tag.
|
||||
$amount = $this->amountByTags($amount);
|
||||
|
||||
|
@ -5,7 +5,6 @@ use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
@ -53,8 +52,6 @@ class EventServiceProvider extends ServiceProvider
|
||||
$this->registerCreateEvents();
|
||||
BudgetLimit::saved(
|
||||
function (BudgetLimit $budgetLimit) {
|
||||
Log::debug('Saved!');
|
||||
|
||||
$end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0);
|
||||
$end->subDay();
|
||||
$set = $budgetLimit->limitrepetitions()
|
||||
@ -101,15 +98,6 @@ class EventServiceProvider extends ServiceProvider
|
||||
}
|
||||
}
|
||||
);
|
||||
PiggyBank::deleting(
|
||||
function (PiggyBank $piggyBank) {
|
||||
$reminders = $piggyBank->reminders()->get();
|
||||
/** @var Reminder $reminder */
|
||||
foreach ($reminders as $reminder) {
|
||||
$reminder->delete();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Account::deleted(
|
||||
function (Account $account) {
|
||||
|
@ -89,12 +89,19 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Reminder\ReminderRepositoryInterface', 'FireflyIII\Repositories\Reminder\ReminderRepository');
|
||||
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
|
||||
|
||||
// make charts:
|
||||
// alternative is Google instead of ChartJs
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Account\AccountChartGenerator', 'FireflyIII\Generator\Chart\Account\ChartJsAccountChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Bill\BillChartGenerator', 'FireflyIII\Generator\Chart\Bill\ChartJsBillChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator', 'FireflyIII\Generator\Chart\Budget\ChartJsBudgetChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Category\CategoryChartGenerator', 'FireflyIII\Generator\Chart\Category\ChartJsCategoryChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator', 'FireflyIII\Generator\Chart\PiggyBank\ChartJsPiggyBankChartGenerator');
|
||||
$this->app->bind('FireflyIII\Generator\Chart\Report\ReportChartGenerator', 'FireflyIII\Generator\Chart\Report\ChartJsReportChartGenerator');
|
||||
|
||||
|
||||
$this->app->bind('FireflyIII\Helpers\Help\HelpInterface', 'FireflyIII\Helpers\Help\Help');
|
||||
$this->app->bind('FireflyIII\Helpers\Reminders\ReminderHelperInterface', 'FireflyIII\Helpers\Reminders\ReminderHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery');
|
||||
|
||||
|
@ -225,6 +225,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']);
|
||||
$accounts = new Collection;
|
||||
|
||||
/** @var PiggyBank $id */
|
||||
foreach ($accountIds as $id) {
|
||||
$ids[] = intval($id->account_id);
|
||||
}
|
||||
@ -432,7 +433,6 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
$account->virtual_balance = $data['virtualBalance'];
|
||||
$account->save();
|
||||
|
||||
// update meta data:
|
||||
$this->updateMetadata($account, $data);
|
||||
$openingBalance = $this->openingBalanceTransaction($account);
|
||||
|
||||
|
@ -26,21 +26,6 @@ use Log;
|
||||
class JournalRepository implements JournalRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param int $reminderId
|
||||
*
|
||||
* @return boolean|null
|
||||
*/
|
||||
public function deactivateReminder($reminderId)
|
||||
{
|
||||
$reminder = Auth::user()->reminders()->find($reminderId);
|
||||
if ($reminder) {
|
||||
$reminder->active = 0;
|
||||
$reminder->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
|
@ -16,13 +16,6 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface JournalRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @param int $reminderId
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function deactivateReminder($reminderId);
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
|
@ -116,8 +116,10 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
*/
|
||||
public function store(array $data)
|
||||
{
|
||||
$data['remind_me'] = isset($data['remind_me']) && $data['remind_me'] == '1' ? true : false;
|
||||
$piggyBank = PiggyBank::create($data);
|
||||
$data['remind_me'] = false;
|
||||
$data['reminder_skip'] = 0;
|
||||
|
||||
$piggyBank = PiggyBank::create($data);
|
||||
|
||||
return $piggyBank;
|
||||
}
|
||||
@ -130,21 +132,12 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
*/
|
||||
public function update(PiggyBank $piggyBank, array $data)
|
||||
{
|
||||
/**
|
||||
* 'rep_length' => $request->get('rep_length'),
|
||||
* 'rep_every' => intval($request->get('rep_every')),
|
||||
* 'rep_times' => intval($request->get('rep_times')),
|
||||
* 'remind_me' => intval($request->get('remind_me')) == 1 ? true : false ,
|
||||
* 'reminder' => $request->get('reminder'),
|
||||
*/
|
||||
|
||||
$piggyBank->name = $data['name'];
|
||||
$piggyBank->account_id = intval($data['account_id']);
|
||||
$piggyBank->targetamount = floatval($data['targetamount']);
|
||||
$piggyBank->targetdate = $data['targetdate'];
|
||||
$piggyBank->reminder = $data['reminder'];
|
||||
$piggyBank->startdate = $data['startdate'];
|
||||
$piggyBank->remind_me = isset($data['remind_me']) && $data['remind_me'] == '1' ? 1 : 0;
|
||||
|
||||
$piggyBank->save();
|
||||
|
||||
|
@ -4,7 +4,6 @@ namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\Reminder;
|
||||
|
||||
/**
|
||||
* Class PiggyBankPart
|
||||
@ -20,8 +19,6 @@ class PiggyBankPart
|
||||
public $cumulativeAmount;
|
||||
/** @var float */
|
||||
public $currentamount;
|
||||
/** @var Reminder */
|
||||
public $reminder;
|
||||
|
||||
/** @var PiggyBankRepetition */
|
||||
public $repetition;
|
||||
@ -33,25 +30,19 @@ class PiggyBankPart
|
||||
public $targetdate;
|
||||
|
||||
/**
|
||||
* @return Reminder
|
||||
* @return PiggyBankRepetition
|
||||
*/
|
||||
public function getReminder()
|
||||
public function getRepetition()
|
||||
{
|
||||
if (is_null($this->reminder)) {
|
||||
$this->reminder = $this->repetition->piggyBank->reminders()->where('startdate', $this->getStartdate()->format('Y-m-d'))->where(
|
||||
'enddate', $this->getTargetdate()->format('Y-m-d')
|
||||
)->first();
|
||||
}
|
||||
|
||||
return $this->reminder;
|
||||
return $this->repetition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
* @param PiggyBankRepetition $repetition
|
||||
*/
|
||||
public function setReminder($reminder)
|
||||
public function setRepetition($repetition)
|
||||
{
|
||||
$this->reminder = $reminder;
|
||||
$this->repetition = $repetition;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,30 +77,6 @@ class PiggyBankPart
|
||||
$this->targetdate = $targetdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PiggyBankRepetition
|
||||
*/
|
||||
public function getRepetition()
|
||||
{
|
||||
return $this->repetition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBankRepetition $repetition
|
||||
*/
|
||||
public function setRepetition($repetition)
|
||||
{
|
||||
$this->repetition = $repetition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasReminder()
|
||||
{
|
||||
return !is_null($this->reminder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float|int
|
||||
*/
|
||||
|
@ -1,116 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Reminder;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class ReminderRepository
|
||||
*
|
||||
* @package FireflyIII\Repositories\Reminder
|
||||
*/
|
||||
class ReminderRepository implements ReminderRepositoryInterface
|
||||
{
|
||||
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface */
|
||||
protected $helper;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface helper */
|
||||
$this->helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveReminders()
|
||||
{
|
||||
$today = new Carbon;
|
||||
// active reminders:
|
||||
$active = Auth::user()->reminders()
|
||||
->where('notnow', 0)
|
||||
->where('active', 1)
|
||||
->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))
|
||||
->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))
|
||||
->get();
|
||||
|
||||
$active->each(
|
||||
function (Reminder $reminder) {
|
||||
$reminder->description = $this->helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
|
||||
return $active;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getDismissedReminders()
|
||||
{
|
||||
$dismissed = Auth::user()->reminders()
|
||||
->where('notnow', 1)
|
||||
->get();
|
||||
|
||||
$dismissed->each(
|
||||
function (Reminder $reminder) {
|
||||
$reminder->description = $this->helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
|
||||
return $dismissed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getExpiredReminders()
|
||||
{
|
||||
|
||||
$expired = Auth::user()->reminders()
|
||||
->where('notnow', 0)
|
||||
->where('active', 1)
|
||||
->where(
|
||||
function (Builder $q) {
|
||||
$today = new Carbon;
|
||||
$q->where('startdate', '>', $today->format('Y-m-d 00:00:00'));
|
||||
$q->orWhere('enddate', '<', $today->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
)->get();
|
||||
|
||||
$expired->each(
|
||||
function (Reminder $reminder) {
|
||||
$reminder->description = $this->helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
|
||||
return $expired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getInactiveReminders()
|
||||
{
|
||||
$inactive = Auth::user()->reminders()
|
||||
->where('active', 0)
|
||||
->get();
|
||||
|
||||
$inactive->each(
|
||||
function (Reminder $reminder) {
|
||||
$reminder->description = $this->helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
|
||||
return $inactive;
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Reminder;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Interface ReminderRepositoryInterface
|
||||
*
|
||||
* @package FireflyIII\Repositories\Reminder
|
||||
*/
|
||||
interface ReminderRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveReminders();
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getDismissedReminders();
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getExpiredReminders();
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getInactiveReminders();
|
||||
|
||||
}
|
@ -40,7 +40,7 @@ class ExpandedForm
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
$html = View::make('form.amount', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
$html = View::make('form.amount', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
@ -144,7 +144,7 @@ class ExpandedForm
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
unset($options['currency']);
|
||||
unset($options['placeholder']);
|
||||
$html = View::make('form.balance', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
$html = View::make('form.balance', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
@ -186,7 +186,7 @@ class ExpandedForm
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
unset($options['placeholder']);
|
||||
$html = View::make('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
$html = View::make('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
@ -323,7 +323,7 @@ class ExpandedForm
|
||||
$selected = $this->fillFieldValue($name, $selected);
|
||||
unset($options['autocomplete']);
|
||||
unset($options['placeholder']);
|
||||
$html = View::make('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
$html = View::make('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class Navigation
|
||||
$subDay = ['week', 'weekly', '1W', 'month', 'monthly', '1M', '3M', 'quarter', 'quarterly', '6M', 'half-year', 'year', 'yearly'];
|
||||
|
||||
if (!isset($functionMap[$repeatFreq])) {
|
||||
throw new FireflyException('Cannot do endOfPeriod for $repeat_freq ' . $repeatFreq);
|
||||
throw new FireflyException('Cannot do endOfPeriod for $repeat_freq "' . $repeatFreq.'"');
|
||||
}
|
||||
$function = $functionMap[$repeatFreq];
|
||||
if (isset($modifierMap[$repeatFreq])) {
|
||||
@ -119,7 +119,6 @@ class Navigation
|
||||
'year' => 'endOfYear',
|
||||
'yearly' => 'endOfYear',
|
||||
];
|
||||
$specials = ['mont', 'monthly'];
|
||||
|
||||
$currentEnd = clone $theCurrentEnd;
|
||||
|
||||
@ -128,12 +127,7 @@ class Navigation
|
||||
$currentEnd->$function();
|
||||
|
||||
}
|
||||
if (isset($specials[$repeatFreq])) {
|
||||
$currentEnd->endOfYear();
|
||||
if ($theCurrentEnd->month <= 6) {
|
||||
$currentEnd->subMonths(6);
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentEnd > $maxDate) {
|
||||
return clone $maxDate;
|
||||
}
|
||||
@ -142,7 +136,7 @@ class Navigation
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
* @param \Carbon\Carbon $date
|
||||
* @param $repeatFrequency
|
||||
*
|
||||
* @return string
|
||||
@ -210,7 +204,7 @@ class Navigation
|
||||
|
||||
return $date;
|
||||
}
|
||||
throw new FireflyException('Cannot do startOfPeriod for $repeat_freq ' . $repeatFreq);
|
||||
throw new FireflyException('Cannot do startOfPeriod for $repeat_freq "' . $repeatFreq.'"');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,7 +246,7 @@ class Navigation
|
||||
return $date;
|
||||
}
|
||||
|
||||
throw new FireflyException('Cannot do subtractPeriod for $repeat_freq ' . $repeatFreq);
|
||||
throw new FireflyException('Cannot do subtractPeriod for $repeat_freq "' . $repeatFreq.'"');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,7 +282,7 @@ class Navigation
|
||||
|
||||
return $end;
|
||||
}
|
||||
throw new FireflyException('updateEndDate cannot handle $range ' . $range);
|
||||
throw new FireflyException('updateEndDate cannot handle $range "' . $range.'"');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,7 +316,7 @@ class Navigation
|
||||
|
||||
return $start;
|
||||
}
|
||||
throw new FireflyException('updateStartDate cannot handle $range ' . $range);
|
||||
throw new FireflyException('updateStartDate cannot handle $range "' . $range.'"');
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ class Steam
|
||||
|
||||
bcscale(2);
|
||||
|
||||
$balance = $account->transactions()->leftJoin(
|
||||
$balance = $account->transactions()->leftJoin(
|
||||
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
|
||||
)->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount');
|
||||
|
||||
|
@ -9,6 +9,7 @@ use Twig_Extension;
|
||||
use Twig_SimpleFunction;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class Budget
|
||||
*
|
||||
* @package FireflyIII\Support\Twig
|
||||
|
@ -14,6 +14,8 @@ use Twig_SimpleFilter;
|
||||
use Twig_SimpleFunction;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class TwigSupport
|
||||
*
|
||||
* @package FireflyIII\Support
|
||||
@ -204,10 +206,10 @@ class General extends Twig_Extension
|
||||
$route = $args[0]; // name of the route.
|
||||
|
||||
if (Route::getCurrentRoute()->getName() == $route) {
|
||||
return 'active because-route-matches-strict';
|
||||
return 'active';
|
||||
}
|
||||
|
||||
return 'not-xxx-at-all';
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -225,10 +227,10 @@ class General extends Twig_Extension
|
||||
$args = func_get_args();
|
||||
$route = $args[0]; // name of the route.
|
||||
if (!(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
|
||||
return 'active because-route-matches-non-strict';
|
||||
return 'active';
|
||||
}
|
||||
|
||||
return 'not-xxx-at-all';
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -249,10 +251,10 @@ class General extends Twig_Extension
|
||||
$activeWhat = isset($context['what']) ? $context['what'] : false;
|
||||
|
||||
if ($what == $activeWhat && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
|
||||
return 'active because-route-matches-non-strict-what';
|
||||
return 'active';
|
||||
}
|
||||
|
||||
return 'not-xxx-at-all';
|
||||
return '';
|
||||
}, ['needs_context' => true]
|
||||
);
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ use Twig_SimpleFilter;
|
||||
use Twig_SimpleFunction;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class Journal
|
||||
*
|
||||
* @package FireflyIII\Support\Twig
|
||||
@ -71,16 +73,16 @@ class Journal extends Twig_Extension
|
||||
|
||||
switch ($type) {
|
||||
case 'Withdrawal':
|
||||
$txt = '<span class="glyphicon glyphicon-arrow-left" title="' . trans('firefly.withdrawal') . '"></span>';
|
||||
$txt = '<i class="fa fa-long-arrow-left fa-fw" title="' . trans('firefly.withdrawal') . '"></i>';
|
||||
break;
|
||||
case 'Deposit':
|
||||
$txt = '<span class="glyphicon glyphicon-arrow-right" title="' . trans('firefly.deposit') . '"></span>';
|
||||
$txt = '<i class="fa fa-long-arrow-right fa-fw" title="' . trans('firefly.deposit') . '"></i>';
|
||||
break;
|
||||
case 'Transfer':
|
||||
$txt = '<i class="fa fa-fw fa-exchange" title="' . trans('firefly.transfer') . '"></i>';
|
||||
break;
|
||||
case 'Opening balance':
|
||||
$txt = '<span class="glyphicon glyphicon-ban-circle" title="' . trans('firefly.openingBalance') . '"></span>';
|
||||
$txt = '<i class="fa-fw fa fa-ban" title="' . trans('firefly.openingBalance') . '"></i>';
|
||||
break;
|
||||
default:
|
||||
$txt = '';
|
||||
|
@ -7,6 +7,8 @@ use Twig_Extension;
|
||||
use Twig_SimpleFunction;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class PiggyBank
|
||||
*
|
||||
* @package FireflyIII\Support\Twig
|
||||
|
@ -6,6 +6,8 @@ use Twig_Extension;
|
||||
use Twig_SimpleFilter;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* Class Budget
|
||||
*
|
||||
* @package FireflyIII\Support\Twig
|
||||
|
11
app/User.php
11
app/User.php
@ -10,6 +10,8 @@ use Zizaco\Entrust\Traits\EntrustUserTrait;
|
||||
/**
|
||||
* Class User
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @package FireflyIII
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
@ -24,7 +26,6 @@ use Zizaco\Entrust\Traits\EntrustUserTrait;
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Preference[] $preferences
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Reminder[] $reminders
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereId($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereCreatedAt($value)
|
||||
@ -123,14 +124,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
||||
return $this->hasMany('FireflyIII\Models\Preference');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function reminders()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\Reminder');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
|
@ -3,16 +3,15 @@
|
||||
namespace FireflyIII\Validation;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use Crypt;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Validation\Validator;
|
||||
use Navigation;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
@ -55,35 +54,6 @@ class FireflyValidator extends Validator
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function validatePiggyBankReminder()
|
||||
{
|
||||
$array = $this->data;
|
||||
// no reminder? dont care.
|
||||
if (!isset($array['remind_me'])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// get or set start date & target date:
|
||||
$startDate = isset($array['startdate']) ? new Carbon($array['startdate']) : new Carbon;
|
||||
$targetDate = isset($array['targetdate']) && strlen($array['targetdate']) > 0 ? new Carbon($array['targetdate']) : null;
|
||||
|
||||
// target date is null? reminder period is always good.
|
||||
if ($array['remind_me'] == '1' && is_null($targetDate)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$nextReminder = Navigation::addPeriod($startDate, $array['reminder'], 0);
|
||||
// reminder is beyond target?
|
||||
if ($nextReminder > $targetDate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @param $value
|
||||
@ -105,6 +75,10 @@ class FireflyValidator extends Validator
|
||||
if (isset($this->data['account_type_id'])) {
|
||||
return $this->validateByAccountTypeId($value, $parameters);
|
||||
}
|
||||
if (isset($this->data['id'])) {
|
||||
return $this->validateByAccountId($value);
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -197,6 +171,33 @@ class FireflyValidator extends Validator
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param $parameters
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function validateByAccountId($value)
|
||||
{
|
||||
/** @var Account $existingAccount */
|
||||
$existingAccount = Account::find($this->data['id']);
|
||||
|
||||
$type = $existingAccount->accountType;
|
||||
$ignore = $existingAccount->id;
|
||||
$value = $this->tryDecrypt($value);
|
||||
|
||||
$set = Auth::user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
|
||||
/** @var Account $entry */
|
||||
foreach ($set as $entry) {
|
||||
if ($entry->name == $value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $attribute
|
||||
* @param $value
|
||||
@ -273,6 +274,7 @@ class FireflyValidator extends Validator
|
||||
}
|
||||
$set = $query->get(['piggy_banks.*']);
|
||||
|
||||
/** @var PiggyBank $entry */
|
||||
foreach ($set as $entry) {
|
||||
$fieldValue = $this->tryDecrypt($entry->name);
|
||||
if ($fieldValue == $value) {
|
||||
|
@ -28,7 +28,6 @@ $app = new Illuminate\Foundation\Application(
|
||||
*/
|
||||
|
||||
|
||||
|
||||
$app->singleton(
|
||||
'Illuminate\Contracts\Http\Kernel',
|
||||
'FireflyIII\Http\Kernel'
|
||||
@ -45,8 +44,6 @@ $app->singleton(
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Return The Application
|
||||
|
@ -14,7 +14,7 @@ define('LARAVEL_START', microtime(true));
|
||||
|
|
||||
*/
|
||||
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -27,9 +27,8 @@ require __DIR__.'/../vendor/autoload.php';
|
||||
|
|
||||
*/
|
||||
|
||||
$compiledPath = __DIR__.'/cache/compiled.php';
|
||||
$compiledPath = __DIR__ . '/cache/compiled.php';
|
||||
|
||||
if (file_exists($compiledPath))
|
||||
{
|
||||
require $compiledPath;
|
||||
if (file_exists($compiledPath)) {
|
||||
require $compiledPath;
|
||||
}
|
||||
|
110
config/auth.php
110
config/auth.php
@ -2,67 +2,67 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Authentication Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the authentication driver that will be utilized.
|
||||
| This driver manages the retrieval and authentication of the users
|
||||
| attempting to get access to protected areas of your application.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Authentication Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the authentication driver that will be utilized.
|
||||
| This driver manages the retrieval and authentication of the users
|
||||
| attempting to get access to protected areas of your application.
|
||||
|
|
||||
| Supported: "database", "eloquent"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'eloquent',
|
||||
'driver' => 'eloquent',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "Eloquent" authentication driver, we need to know which
|
||||
| Eloquent model should be used to retrieve your users. Of course, it
|
||||
| is often just the "User" model but you may use whatever you like.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Model
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "Eloquent" authentication driver, we need to know which
|
||||
| Eloquent model should be used to retrieve your users. Of course, it
|
||||
| is often just the "User" model but you may use whatever you like.
|
||||
|
|
||||
*/
|
||||
|
||||
'model' => 'FireflyIII\User',
|
||||
'model' => 'FireflyIII\User',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "Database" authentication driver, we need to know which
|
||||
| table should be used to retrieve your users. We have chosen a basic
|
||||
| default value but you may easily change it to any table you like.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Authentication Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "Database" authentication driver, we need to know which
|
||||
| table should be used to retrieve your users. We have chosen a basic
|
||||
| default value but you may easily change it to any table you like.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => 'users',
|
||||
'table' => 'users',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may set the options for resetting passwords including the view
|
||||
| that is your password reset e-mail. You can also set the name of the
|
||||
| table that maintains all of the reset tokens for your application.
|
||||
|
|
||||
| The expire time is the number of minutes that the reset token should be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Settings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may set the options for resetting passwords including the view
|
||||
| that is your password reset e-mail. You can also set the name of the
|
||||
| table that maintains all of the reset tokens for your application.
|
||||
|
|
||||
| The expire time is the number of minutes that the reset token should be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'password' => [
|
||||
'email' => 'emails.password',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
],
|
||||
'allow_register' => true
|
||||
'password' => [
|
||||
'email' => 'emails.password',
|
||||
'table' => 'password_resets',
|
||||
'expire' => 60,
|
||||
],
|
||||
'allow_register' => true
|
||||
|
||||
];
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
return [
|
||||
|
||||
'view' => 'breadcrumbs::bootstrap3',
|
||||
'view' => 'breadcrumbs::bootstrap3',
|
||||
|
||||
];
|
||||
|
122
config/cache.php
122
config/cache.php
@ -2,78 +2,78 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache connection that gets used while
|
||||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cache Store
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default cache connection that gets used while
|
||||
| using this caching library. This connection is used when another is
|
||||
| not explicitly specified when executing a given caching function.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('CACHE_DRIVER', 'file'),
|
||||
'default' => env('CACHE_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Stores
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may define all of the cache "stores" for your application as
|
||||
| well as their drivers. You may even define multiple stores for the
|
||||
| same cache driver to group types of items stored in your caches.
|
||||
|
|
||||
*/
|
||||
|
||||
'stores' => [
|
||||
'stores' => [
|
||||
|
||||
'apc' => [
|
||||
'driver' => 'apc'
|
||||
],
|
||||
'apc' => [
|
||||
'driver' => 'apc'
|
||||
],
|
||||
|
||||
'array' => [
|
||||
'driver' => 'array'
|
||||
],
|
||||
'array' => [
|
||||
'driver' => 'array'
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'cache',
|
||||
'connection' => null,
|
||||
],
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'cache',
|
||||
'connection' => null,
|
||||
],
|
||||
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path().'/framework/cache',
|
||||
],
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path() . '/framework/cache',
|
||||
],
|
||||
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'servers' => [
|
||||
[
|
||||
'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100
|
||||
],
|
||||
],
|
||||
],
|
||||
'memcached' => [
|
||||
'driver' => 'memcached',
|
||||
'servers' => [
|
||||
[
|
||||
'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100
|
||||
],
|
||||
],
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
],
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'connection' => 'default',
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing a RAM based store such as APC or Memcached, there might
|
||||
| be other applications utilizing the same cache. So, we'll specify a
|
||||
| value to get prefixed to all our keys so we can avoid collisions.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Key Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When utilizing a RAM based store such as APC or Memcached, there might
|
||||
| be other applications utilizing the same cache. So, we'll specify a
|
||||
| value to get prefixed to all our keys so we can avoid collisions.
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => 'laravel',
|
||||
'prefix' => 'laravel',
|
||||
|
||||
];
|
||||
|
@ -2,40 +2,40 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Additional Compiled Classes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify additional classes to include in the compiled file
|
||||
| generated by the `artisan optimize` command. These should be classes
|
||||
| that are included on basically every request into the application.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Additional Compiled Classes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify additional classes to include in the compiled file
|
||||
| generated by the `artisan optimize` command. These should be classes
|
||||
| that are included on basically every request into the application.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => [
|
||||
'files' => [
|
||||
|
||||
realpath(__DIR__.'/../app/Providers/AppServiceProvider.php'),
|
||||
realpath(__DIR__.'/../app/Providers/BusServiceProvider.php'),
|
||||
realpath(__DIR__.'/../app/Providers/ConfigServiceProvider.php'),
|
||||
realpath(__DIR__.'/../app/Providers/EventServiceProvider.php'),
|
||||
realpath(__DIR__.'/../app/Providers/RouteServiceProvider.php'),
|
||||
realpath(__DIR__ . '/../app/Providers/AppServiceProvider.php'),
|
||||
realpath(__DIR__ . '/../app/Providers/BusServiceProvider.php'),
|
||||
realpath(__DIR__ . '/../app/Providers/ConfigServiceProvider.php'),
|
||||
realpath(__DIR__ . '/../app/Providers/EventServiceProvider.php'),
|
||||
realpath(__DIR__ . '/../app/Providers/RouteServiceProvider.php'),
|
||||
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled File Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may list service providers which define a "compiles" function
|
||||
| that returns additional files that should be compiled, providing an
|
||||
| easy way to get common files from any packages you are utilizing.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled File Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may list service providers which define a "compiles" function
|
||||
| that returns additional files that should be compiled, providing an
|
||||
| easy way to get common files from any packages you are utilizing.
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
//
|
||||
],
|
||||
'providers' => [
|
||||
//
|
||||
],
|
||||
|
||||
];
|
||||
|
@ -48,7 +48,7 @@ return [
|
||||
|
||||
'sqlite' => [
|
||||
'driver' => 'sqlite',
|
||||
'database' => __DIR__.'/../storage/database/testing.db',
|
||||
'database' => __DIR__ . '/../storage/database/testing.db',
|
||||
'prefix' => '',
|
||||
],
|
||||
|
||||
|
@ -19,7 +19,7 @@ return [
|
||||
| the role if it is in a different namespace.
|
||||
|
|
||||
*/
|
||||
'role' => 'FireflyIII\Models\Role',
|
||||
'role' => 'FireflyIII\Models\Role',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -29,7 +29,7 @@ return [
|
||||
| This is the roles table used by Entrust to save roles to the database.
|
||||
|
|
||||
*/
|
||||
'roles_table' => 'roles',
|
||||
'roles_table' => 'roles',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -40,7 +40,7 @@ return [
|
||||
| Update the permission if it is in a different namespace.
|
||||
|
|
||||
*/
|
||||
'permission' => 'FireflyIII\Models\Permission',
|
||||
'permission' => 'FireflyIII\Models\Permission',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -51,7 +51,7 @@ return [
|
||||
| database.
|
||||
|
|
||||
*/
|
||||
'permissions_table' => 'permissions',
|
||||
'permissions_table' => 'permissions',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -73,6 +73,6 @@ return [
|
||||
| database.
|
||||
|
|
||||
*/
|
||||
'role_user_table' => 'role_user',
|
||||
'role_user_table' => 'role_user',
|
||||
|
||||
];
|
||||
|
@ -2,69 +2,69 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. A "local" driver, as well as a variety of cloud
|
||||
| based drivers are available for your choosing. Just store away!
|
||||
|
|
||||
| Supported: "local", "s3", "rackspace"
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the default filesystem disk that should be used
|
||||
| by the framework. A "local" driver, as well as a variety of cloud
|
||||
| based drivers are available for your choosing. Just store away!
|
||||
|
|
||||
| Supported: "local", "s3", "rackspace"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'local',
|
||||
'default' => 'local',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cloud Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Many applications store files both locally and in the cloud. For this
|
||||
| reason, you may specify a default "cloud" driver here. This driver
|
||||
| will be bound as the Cloud disk implementation in the container.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Cloud Filesystem Disk
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Many applications store files both locally and in the cloud. For this
|
||||
| reason, you may specify a default "cloud" driver here. This driver
|
||||
| will be bound as the Cloud disk implementation in the container.
|
||||
|
|
||||
*/
|
||||
|
||||
'cloud' => 's3',
|
||||
'cloud' => 's3',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Filesystem Disks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure as many filesystem "disks" as you wish, and you
|
||||
| may even configure multiple disks of the same driver. Defaults have
|
||||
| been setup for each driver as an example of the required options.
|
||||
|
|
||||
*/
|
||||
|
||||
'disks' => [
|
||||
'disks' => [
|
||||
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path().'/app',
|
||||
],
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path() . '/app',
|
||||
],
|
||||
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => 'your-key',
|
||||
'secret' => 'your-secret',
|
||||
'region' => 'your-region',
|
||||
'bucket' => 'your-bucket',
|
||||
],
|
||||
's3' => [
|
||||
'driver' => 's3',
|
||||
'key' => 'your-key',
|
||||
'secret' => 'your-secret',
|
||||
'region' => 'your-region',
|
||||
'bucket' => 'your-bucket',
|
||||
],
|
||||
|
||||
'rackspace' => [
|
||||
'driver' => 'rackspace',
|
||||
'username' => 'your-username',
|
||||
'key' => 'your-key',
|
||||
'container' => 'your-container',
|
||||
'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/',
|
||||
'region' => 'IAD',
|
||||
],
|
||||
'rackspace' => [
|
||||
'driver' => 'rackspace',
|
||||
'username' => 'your-username',
|
||||
'key' => 'your-key',
|
||||
'container' => 'your-container',
|
||||
'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/',
|
||||
'region' => 'IAD',
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
|
||||
];
|
||||
|
@ -1,7 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'version' => '3.4.5',
|
||||
'chart' => 'chartjs', // or 'chartjs'
|
||||
'version' => '3.4.6',
|
||||
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
|
||||
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
|
||||
'piggy_bank_periods' => [
|
||||
@ -57,7 +58,7 @@ return [
|
||||
'asset' => 'Asset accounts',
|
||||
'expense' => 'Expense accounts',
|
||||
'revenue' => 'Revenue accounts',
|
||||
'cash' => 'Cash accounts',
|
||||
'cash' => 'Cash accounts',
|
||||
],
|
||||
'subIconsByIdentifier' =>
|
||||
[
|
||||
|
148
config/queue.php
148
config/queue.php
@ -2,91 +2,91 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The Laravel queue API supports a variety of back-ends via an unified
|
||||
| API, giving you convenient access to each back-end using the same
|
||||
| syntax for each one. Here you may set the default queue driver.
|
||||
|
|
||||
| Supported: "null", "sync", "database", "beanstalkd",
|
||||
| "sqs", "iron", "redis"
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Queue Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The Laravel queue API supports a variety of back-ends via an unified
|
||||
| API, giving you convenient access to each back-end using the same
|
||||
| syntax for each one. Here you may set the default queue driver.
|
||||
|
|
||||
| Supported: "null", "sync", "database", "beanstalkd",
|
||||
| "sqs", "iron", "redis"
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_DRIVER', 'sync'),
|
||||
'default' => env('QUEUE_DRIVER', 'sync'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection information for each server that
|
||||
| is used by your application. A default configuration has been added
|
||||
| for each back-end shipped with Laravel. You are free to add more.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure the connection information for each server that
|
||||
| is used by your application. A default configuration has been added
|
||||
| for each back-end shipped with Laravel. You are free to add more.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => [
|
||||
'connections' => [
|
||||
|
||||
'sync' => [
|
||||
'driver' => 'sync',
|
||||
],
|
||||
'sync' => [
|
||||
'driver' => 'sync',
|
||||
],
|
||||
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'jobs',
|
||||
'queue' => 'default',
|
||||
'expire' => 60,
|
||||
],
|
||||
'database' => [
|
||||
'driver' => 'database',
|
||||
'table' => 'jobs',
|
||||
'queue' => 'default',
|
||||
'expire' => 60,
|
||||
],
|
||||
|
||||
'beanstalkd' => [
|
||||
'driver' => 'beanstalkd',
|
||||
'host' => 'localhost',
|
||||
'queue' => 'default',
|
||||
'ttr' => 60,
|
||||
],
|
||||
'beanstalkd' => [
|
||||
'driver' => 'beanstalkd',
|
||||
'host' => 'localhost',
|
||||
'queue' => 'default',
|
||||
'ttr' => 60,
|
||||
],
|
||||
|
||||
'sqs' => [
|
||||
'driver' => 'sqs',
|
||||
'key' => 'your-public-key',
|
||||
'secret' => 'your-secret-key',
|
||||
'queue' => 'your-queue-url',
|
||||
'region' => 'us-east-1',
|
||||
],
|
||||
'sqs' => [
|
||||
'driver' => 'sqs',
|
||||
'key' => 'your-public-key',
|
||||
'secret' => 'your-secret-key',
|
||||
'queue' => 'your-queue-url',
|
||||
'region' => 'us-east-1',
|
||||
],
|
||||
|
||||
'iron' => [
|
||||
'driver' => 'iron',
|
||||
'host' => 'mq-aws-us-east-1.iron.io',
|
||||
'token' => 'your-token',
|
||||
'project' => 'your-project-id',
|
||||
'queue' => 'your-queue-name',
|
||||
'encrypt' => true,
|
||||
],
|
||||
'iron' => [
|
||||
'driver' => 'iron',
|
||||
'host' => 'mq-aws-us-east-1.iron.io',
|
||||
'token' => 'your-token',
|
||||
'project' => 'your-project-id',
|
||||
'queue' => 'your-queue-name',
|
||||
'encrypt' => true,
|
||||
],
|
||||
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'queue' => 'default',
|
||||
'expire' => 60,
|
||||
],
|
||||
'redis' => [
|
||||
'driver' => 'redis',
|
||||
'queue' => 'default',
|
||||
'expire' => 60,
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control which database and table are used to store the jobs that
|
||||
| have failed. You may change them to any database / table you wish.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Failed Queue Jobs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These options configure the behavior of failed queue job logging so you
|
||||
| can control which database and table are used to store the jobs that
|
||||
| have failed. You may change them to any database / table you wish.
|
||||
|
|
||||
*/
|
||||
|
||||
'failed' => [
|
||||
'database' => 'mysql', 'table' => 'failed_jobs',
|
||||
],
|
||||
'failed' => [
|
||||
'database' => 'mysql', 'table' => 'failed_jobs',
|
||||
],
|
||||
|
||||
];
|
||||
|
@ -2,36 +2,36 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Stripe, Mailgun, Mandrill, and others. This file provides a sane
|
||||
| default location for this type of information, allowing packages
|
||||
| to have a conventional place to find your various credentials.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Third Party Services
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file is for storing the credentials for third party services such
|
||||
| as Stripe, Mailgun, Mandrill, and others. This file provides a sane
|
||||
| default location for this type of information, allowing packages
|
||||
| to have a conventional place to find your various credentials.
|
||||
|
|
||||
*/
|
||||
|
||||
'mailgun' => [
|
||||
'domain' => '',
|
||||
'secret' => '',
|
||||
],
|
||||
'mailgun' => [
|
||||
'domain' => '',
|
||||
'secret' => '',
|
||||
],
|
||||
|
||||
'mandrill' => [
|
||||
'secret' => '',
|
||||
],
|
||||
'mandrill' => [
|
||||
'secret' => '',
|
||||
],
|
||||
|
||||
'ses' => [
|
||||
'key' => '',
|
||||
'secret' => '',
|
||||
'region' => 'us-east-1',
|
||||
],
|
||||
'ses' => [
|
||||
'key' => '',
|
||||
'secret' => '',
|
||||
'region' => 'us-east-1',
|
||||
],
|
||||
|
||||
'stripe' => [
|
||||
'model' => 'User',
|
||||
'secret' => '',
|
||||
],
|
||||
'stripe' => [
|
||||
'model' => 'User',
|
||||
'secret' => '',
|
||||
],
|
||||
|
||||
];
|
||||
|
@ -2,152 +2,152 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default session "driver" that will be used on
|
||||
| requests. By default, we will use the lightweight native driver but
|
||||
| you may specify any of the other wonderful drivers provided here.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "apc",
|
||||
| "memcached", "redis", "array"
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Session Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default session "driver" that will be used on
|
||||
| requests. By default, we will use the lightweight native driver but
|
||||
| you may specify any of the other wonderful drivers provided here.
|
||||
|
|
||||
| Supported: "file", "cookie", "database", "apc",
|
||||
| "memcached", "redis", "array"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
'driver' => env('SESSION_DRIVER', 'file'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to immediately expire on the browser closing, set that option.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Lifetime
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify the number of minutes that you wish the session
|
||||
| to be allowed to remain idle before it expires. If you want them
|
||||
| to immediately expire on the browser closing, set that option.
|
||||
|
|
||||
*/
|
||||
|
||||
'lifetime' => 120,
|
||||
'lifetime' => 120,
|
||||
|
||||
'expire_on_close' => false,
|
||||
'expire_on_close' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it is stored. All encryption will be run
|
||||
| automatically by Laravel and you can use the Session like normal.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Encryption
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to easily specify that all of your session data
|
||||
| should be encrypted before it is stored. All encryption will be run
|
||||
| automatically by Laravel and you can use the Session like normal.
|
||||
|
|
||||
*/
|
||||
|
||||
'encrypt' => false,
|
||||
'encrypt' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the native session driver, we need a location where session
|
||||
| files may be stored. A default has been set for you but a different
|
||||
| location may be specified. This is only needed for file sessions.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session File Location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the native session driver, we need a location where session
|
||||
| files may be stored. A default has been set for you but a different
|
||||
| location may be specified. This is only needed for file sessions.
|
||||
|
|
||||
*/
|
||||
|
||||
'files' => storage_path().'/framework/sessions',
|
||||
'files' => storage_path() . '/framework/sessions',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" or "redis" session drivers, you may specify a
|
||||
| connection that should be used to manage these sessions. This should
|
||||
| correspond to a connection in your database configuration options.
|
||||
|
|
||||
*/
|
||||
|
||||
'connection' => null,
|
||||
'connection' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table we
|
||||
| should use to manage the sessions. Of course, a sensible default is
|
||||
| provided for you; however, you are free to change this as needed.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Database Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When using the "database" session driver, you may specify the table we
|
||||
| should use to manage the sessions. Of course, a sensible default is
|
||||
| provided for you; however, you are free to change this as needed.
|
||||
|
|
||||
*/
|
||||
|
||||
'table' => 'sessions',
|
||||
'table' => 'sessions',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Sweeping Lottery
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some session drivers must manually sweep their storage location to get
|
||||
| rid of old sessions from storage. Here are the chances that it will
|
||||
| happen on a given request. By default, the odds are 2 out of 100.
|
||||
|
|
||||
*/
|
||||
|
||||
'lottery' => [2, 100],
|
||||
'lottery' => [2, 100],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the cookie used to identify a session
|
||||
| instance by ID. The name specified here will get used every time a
|
||||
| new session cookie is created by the framework for every driver.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the name of the cookie used to identify a session
|
||||
| instance by ID. The name specified here will get used every time a
|
||||
| new session cookie is created by the framework for every driver.
|
||||
|
|
||||
*/
|
||||
|
||||
'cookie' => 'laravel_session',
|
||||
'cookie' => 'laravel_session',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application but you are free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The session cookie path determines the path for which the cookie will
|
||||
| be regarded as available. Typically, this will be the root path of
|
||||
| your application but you are free to change this when necessary.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => '/',
|
||||
'path' => '/',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the domain of the cookie used to identify a session
|
||||
| in your application. This will determine which domains the cookie is
|
||||
| available to in your application. A sensible default has been set.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Cookie Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may change the domain of the cookie used to identify a session
|
||||
| in your application. This will determine which domains the cookie is
|
||||
| available to in your application. A sensible default has been set.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => null,
|
||||
'domain' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you if it can not be done securely.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTTPS Only Cookies
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By setting this option to true, session cookies will only be sent back
|
||||
| to the server if the browser has a HTTPS connection. This will keep
|
||||
| the cookie from being sent to you if it can not be done securely.
|
||||
|
|
||||
*/
|
||||
|
||||
'secure' => false,
|
||||
'secure' => false,
|
||||
|
||||
];
|
||||
|
@ -2,32 +2,32 @@
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| View Storage Paths
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Most templating systems load templates from disk. Here you may specify
|
||||
| an array of paths that should be checked for your views. Of course
|
||||
| the usual Laravel view path has already been registered for you.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| View Storage Paths
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Most templating systems load templates from disk. Here you may specify
|
||||
| an array of paths that should be checked for your views. Of course
|
||||
| the usual Laravel view path has already been registered for you.
|
||||
|
|
||||
*/
|
||||
|
||||
'paths' => [
|
||||
realpath(base_path('resources/twig'))
|
||||
],
|
||||
'paths' => [
|
||||
realpath(base_path('resources/twig'))
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled View Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines where all the compiled Blade templates will be
|
||||
| stored for your application. Typically, this is within the storage
|
||||
| directory. However, as usual, you are free to change this value.
|
||||
|
|
||||
*/
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Compiled View Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option determines where all the compiled Blade templates will be
|
||||
| stored for your application. Typically, this is within the storage
|
||||
| directory. However, as usual, you are free to change this value.
|
||||
|
|
||||
*/
|
||||
|
||||
'compiled' => realpath(storage_path().'/framework/views'),
|
||||
'compiled' => realpath(storage_path() . '/framework/views'),
|
||||
|
||||
];
|
||||
|
@ -37,7 +37,7 @@ class CreateTransactionGroupsTable extends Migration
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->enum('relation', ['balance']);
|
||||
|
||||
// connect reminders to users
|
||||
// connect groups to users
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
|
@ -57,7 +57,7 @@ class ChangesForV3310 extends Migration
|
||||
$table->decimal('longitude', 18, 12)->nullable();
|
||||
$table->smallInteger('zoomLevel', false, true)->nullable();
|
||||
|
||||
// connect reminders to users
|
||||
// connect tags to users
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
|
@ -7,58 +7,6 @@ use Illuminate\Database\Schema\Blueprint;
|
||||
*/
|
||||
class EntrustSetupTables extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// Create table for storing roles
|
||||
Schema::create('roles', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->unique();
|
||||
$table->string('display_name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// Create table for associating roles to users (Many-to-Many)
|
||||
Schema::create('role_user', function (Blueprint $table) {
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->integer('role_id')->unsigned();
|
||||
|
||||
$table->foreign('user_id')->references('id')->on('users')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
$table->foreign('role_id')->references('id')->on('roles')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
|
||||
$table->primary(['user_id', 'role_id']);
|
||||
});
|
||||
|
||||
// Create table for storing permissions
|
||||
Schema::create('permissions', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->unique();
|
||||
$table->string('display_name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// Create table for associating permissions to roles (Many-to-Many)
|
||||
Schema::create('permission_role', function (Blueprint $table) {
|
||||
$table->integer('permission_id')->unsigned();
|
||||
$table->integer('role_id')->unsigned();
|
||||
|
||||
$table->foreign('permission_id')->references('id')->on('permissions')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
$table->foreign('role_id')->references('id')->on('roles')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
|
||||
$table->primary(['permission_id', 'role_id']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
@ -71,4 +19,64 @@ class EntrustSetupTables extends Migration
|
||||
Schema::drop('role_user');
|
||||
Schema::drop('roles');
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
// Create table for storing roles
|
||||
Schema::create(
|
||||
'roles', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->unique();
|
||||
$table->string('display_name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->timestamps();
|
||||
}
|
||||
);
|
||||
|
||||
// Create table for associating roles to users (Many-to-Many)
|
||||
Schema::create(
|
||||
'role_user', function (Blueprint $table) {
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->integer('role_id')->unsigned();
|
||||
|
||||
$table->foreign('user_id')->references('id')->on('users')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
$table->foreign('role_id')->references('id')->on('roles')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
|
||||
$table->primary(['user_id', 'role_id']);
|
||||
}
|
||||
);
|
||||
|
||||
// Create table for storing permissions
|
||||
Schema::create(
|
||||
'permissions', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->string('name')->unique();
|
||||
$table->string('display_name')->nullable();
|
||||
$table->string('description')->nullable();
|
||||
$table->timestamps();
|
||||
}
|
||||
);
|
||||
|
||||
// Create table for associating permissions to roles (Many-to-Many)
|
||||
Schema::create(
|
||||
'permission_role', function (Blueprint $table) {
|
||||
$table->integer('permission_id')->unsigned();
|
||||
$table->integer('role_id')->unsigned();
|
||||
|
||||
$table->foreign('permission_id')->references('id')->on('permissions')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
$table->foreign('role_id')->references('id')->on('roles')
|
||||
->onUpdate('cascade')->onDelete('cascade');
|
||||
|
||||
$table->primary(['permission_id', 'role_id']);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
33
database/migrations/2015_06_23_050233_changes_for_v3451.php
Normal file
33
database/migrations/2015_06_23_050233_changes_for_v3451.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
/**
|
||||
* Class ChangesForV3451
|
||||
*/
|
||||
class ChangesForV3451 extends Migration
|
||||
{
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//$table->smallInteger('reminder_skip')->unsigned();
|
||||
//$table->boolean('remind_me');
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ class PermissionSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$owner = new Role;
|
||||
$owner = new Role;
|
||||
$owner->name = 'owner';
|
||||
$owner->display_name = 'Site Owner';
|
||||
$owner->description = 'User runs this instance of FF3'; // optional
|
||||
|
@ -88,7 +88,6 @@ class TestDataSeeder extends Seeder
|
||||
$this->createBudgets();
|
||||
$this->createCategories();
|
||||
$this->createPiggyBanks();
|
||||
$this->createReminders();
|
||||
$this->createBills();
|
||||
$this->createExpenseAccounts();
|
||||
$this->createRevenueAccounts();
|
||||
@ -264,7 +263,6 @@ class TestDataSeeder extends Seeder
|
||||
'targetamount' => 2000,
|
||||
'startdate' => $this->som,
|
||||
'targetdate' => null,
|
||||
'reminder' => null,
|
||||
'reminder_skip' => 0,
|
||||
'remind_me' => 0,
|
||||
'order' => 0,
|
||||
@ -281,7 +279,6 @@ class TestDataSeeder extends Seeder
|
||||
'targetamount' => 2000,
|
||||
'startdate' => $this->som,
|
||||
'targetdate' => $end,
|
||||
'reminder' => null,
|
||||
'reminder_skip' => 0,
|
||||
'remind_me' => 0,
|
||||
'order' => 0,
|
||||
@ -292,7 +289,6 @@ class TestDataSeeder extends Seeder
|
||||
|
||||
/*
|
||||
* New: create no less than eight piggy banks that
|
||||
* create all sorts of reminders
|
||||
*/
|
||||
$list = ['week', 'quarter', 'month', 'year'];
|
||||
$nextYear = clone $this->_startOfMonth;
|
||||
@ -306,9 +302,8 @@ class TestDataSeeder extends Seeder
|
||||
'targetamount' => 1000,
|
||||
'startdate' => $this->som,
|
||||
'targetdate' => $nextYear,
|
||||
'reminder' => $entry,
|
||||
'reminder_skip' => 0,
|
||||
'remind_me' => 1,
|
||||
'remind_me' => 0,
|
||||
'order' => 0,
|
||||
]
|
||||
);
|
||||
@ -319,9 +314,8 @@ class TestDataSeeder extends Seeder
|
||||
'targetamount' => 1000,
|
||||
'startdate' => $this->som,
|
||||
'targetdate' => null,
|
||||
'reminder' => $entry,
|
||||
'reminder_skip' => 0,
|
||||
'remind_me' => 1,
|
||||
'remind_me' => 0,
|
||||
'order' => 0,
|
||||
]
|
||||
);
|
||||
@ -348,14 +342,6 @@ class TestDataSeeder extends Seeder
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function createReminders()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@ -444,7 +430,8 @@ class TestDataSeeder extends Seeder
|
||||
$user = User::whereEmail('thegrumpydictator@gmail.com')->first();
|
||||
|
||||
Tag::create(
|
||||
['tag' => 'TagOne', 'tagMode' => 'nothing', 'user_id' => $user->id]);
|
||||
['tag' => 'TagOne', 'tagMode' => 'nothing', 'user_id' => $user->id]
|
||||
);
|
||||
|
||||
Tag::create(['tag' => 'TagTwo', 'tagMode' => 'nothing', 'user_id' => $user->id]);
|
||||
Tag::create(['tag' => 'TagThree', 'tagMode' => 'nothing', 'user_id' => $user->id]);
|
||||
@ -541,9 +528,10 @@ class TestDataSeeder extends Seeder
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tag
|
||||
* @param $tagName
|
||||
*
|
||||
* @return Tag|null
|
||||
* @internal param $tag
|
||||
*/
|
||||
protected function findTag($tagName)
|
||||
{
|
||||
|
2
pu.sh
2
pu.sh
@ -10,7 +10,7 @@ then
|
||||
fi
|
||||
|
||||
# directories to look in:
|
||||
dirs=("controllers" "database" "factories" "helpers" "models" "middleware" "repositories" "support")
|
||||
dirs=("controllers" "database" "factories" "generators" "helpers" "models" "middleware" "repositories" "support")
|
||||
|
||||
if [ ! -z "$1" ]
|
||||
then
|
||||
|
13
public/bootstrap/css/bootstrap.min.css
vendored
Normal file → Executable file
13
public/bootstrap/css/bootstrap.min.css
vendored
Normal file → Executable file
File diff suppressed because one or more lines are too long
11
public/bootstrap/js/bootstrap.min.js
vendored
Normal file → Executable file
11
public/bootstrap/js/bootstrap.min.js
vendored
Normal file → Executable file
File diff suppressed because one or more lines are too long
@ -7,42 +7,42 @@
|
||||
* Built for http://www.improvely.com
|
||||
*/
|
||||
|
||||
.daterangepicker.dropdown-menu {
|
||||
max-width: none;
|
||||
z-index: 3000;
|
||||
.daterangepicker.dropdown-menu {
|
||||
max-width: none;
|
||||
z-index: 3000;
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {
|
||||
float: left;
|
||||
margin: 4px;
|
||||
float: left;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
|
||||
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
|
||||
float: right;
|
||||
margin: 4px;
|
||||
float: right;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.single .ranges, .daterangepicker.single .calendar {
|
||||
float: none;
|
||||
float: none;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges {
|
||||
width: 160px;
|
||||
text-align: left;
|
||||
width: 160px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges .range_inputs>div {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges .range_inputs>div:nth-child(2) {
|
||||
padding-left: 11px;
|
||||
padding-left: 11px;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar {
|
||||
display: none;
|
||||
max-width: 270px;
|
||||
display: none;
|
||||
max-width: 270px;
|
||||
}
|
||||
|
||||
.daterangepicker.show-calendar .calendar {
|
||||
@ -50,270 +50,286 @@
|
||||
}
|
||||
|
||||
.daterangepicker .calendar.single .calendar-date {
|
||||
border: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar th, .daterangepicker .calendar td {
|
||||
font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
min-width: 32px;
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
.daterangepicker .daterangepicker_start_input label,
|
||||
.daterangepicker .daterangepicker_end_input label {
|
||||
color: #333;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 2px;
|
||||
text-shadow: #fff 1px 1px 0px;
|
||||
text-transform: uppercase;
|
||||
width: 74px;
|
||||
color: #333;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
font-weight: normal;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-bottom: 2px;
|
||||
text-shadow: #fff 1px 1px 0px;
|
||||
text-transform: uppercase;
|
||||
width: 74px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges input {
|
||||
font-size: 11px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges .input-mini {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
color: #555;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
vertical-align: middle;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0 6px;
|
||||
width: 74px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
color: #555;
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
vertical-align: middle;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0 6px;
|
||||
width: 74px;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges li {
|
||||
font-size: 13px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #f5f5f5;
|
||||
color: #08c;
|
||||
padding: 3px 12px;
|
||||
margin-bottom: 8px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #f5f5f5;
|
||||
color: #08c;
|
||||
padding: 3px 12px;
|
||||
margin-bottom: 8px;
|
||||
-webkit-border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
|
||||
background: #08c;
|
||||
border: 1px solid #08c;
|
||||
color: #fff;
|
||||
background: #08c;
|
||||
border: 1px solid #08c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar-date {
|
||||
border: 1px solid #ddd;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker .calendar-time {
|
||||
text-align: center;
|
||||
margin: 8px auto 0 auto;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
margin: 8px auto 0 auto;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.daterangepicker {
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
top: 100px;
|
||||
left: 20px;
|
||||
padding: 4px;
|
||||
margin-top: 1px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
top: 100px;
|
||||
left: 20px;
|
||||
padding: 4px;
|
||||
margin-top: 1px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
right: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensleft:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.openscenter:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.openscenter:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensright:before {
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -7px;
|
||||
left: 9px;
|
||||
display: inline-block;
|
||||
border-right: 7px solid transparent;
|
||||
border-bottom: 7px solid #ccc;
|
||||
border-left: 7px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.opensright:after {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 10px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #fff;
|
||||
border-left: 6px solid transparent;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.daterangepicker.dropup{
|
||||
margin-top: -5px;
|
||||
}
|
||||
.daterangepicker.dropup:before{
|
||||
top: initial;
|
||||
bottom:-7px;
|
||||
border-bottom: initial;
|
||||
border-top: 7px solid #ccc;
|
||||
}
|
||||
.daterangepicker.dropup:after{
|
||||
top: initial;
|
||||
bottom:-6px;
|
||||
border-bottom: initial;
|
||||
border-top: 6px solid #fff;
|
||||
}
|
||||
|
||||
.daterangepicker table {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.daterangepicker td, .daterangepicker th {
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.daterangepicker td.off {
|
||||
color: #999;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.daterangepicker td.disabled, .daterangepicker option.disabled {
|
||||
color: #999;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.daterangepicker td.available:hover, .daterangepicker th.available:hover {
|
||||
background: #eee;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.daterangepicker td.in-range {
|
||||
background: #ebf4f8;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
background: #ebf4f8;
|
||||
-webkit-border-radius: 0;
|
||||
-moz-border-radius: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.daterangepicker td.start-date {
|
||||
-webkit-border-radius: 4px 0 0 4px;
|
||||
-moz-border-radius: 4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
-webkit-border-radius: 4px 0 0 4px;
|
||||
-moz-border-radius: 4px 0 0 4px;
|
||||
border-radius: 4px 0 0 4px;
|
||||
}
|
||||
|
||||
.daterangepicker td.end-date {
|
||||
-webkit-border-radius: 0 4px 4px 0;
|
||||
-moz-border-radius: 0 4px 4px 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
-webkit-border-radius: 0 4px 4px 0;
|
||||
-moz-border-radius: 0 4px 4px 0;
|
||||
border-radius: 0 4px 4px 0;
|
||||
}
|
||||
|
||||
.daterangepicker td.start-date.end-date {
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.daterangepicker td.active, .daterangepicker td.active:hover {
|
||||
background-color: #357ebd;
|
||||
border-color: #3071a9;
|
||||
color: #fff;
|
||||
background-color: #357ebd;
|
||||
border-color: #3071a9;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.daterangepicker td.week, .daterangepicker th.week {
|
||||
font-size: 80%;
|
||||
color: #ccc;
|
||||
font-size: 80%;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.daterangepicker select.monthselect, .daterangepicker select.yearselect {
|
||||
font-size: 12px;
|
||||
padding: 1px;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
cursor: default;
|
||||
font-size: 12px;
|
||||
padding: 1px;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.daterangepicker select.monthselect {
|
||||
margin-right: 2%;
|
||||
width: 56%;
|
||||
margin-right: 2%;
|
||||
width: 56%;
|
||||
}
|
||||
|
||||
.daterangepicker select.yearselect {
|
||||
width: 40%;
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
|
||||
width: 50px;
|
||||
margin-bottom: 0;
|
||||
width: 50px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.daterangepicker_start_input {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.daterangepicker_end_input {
|
||||
float: left;
|
||||
padding-left: 11px
|
||||
float: left;
|
||||
padding-left: 11px
|
||||
}
|
||||
|
||||
.daterangepicker th.month {
|
||||
width: auto;
|
||||
width: auto;
|
||||
}
|
556
public/js/Chart.StackedBar.js
Normal file
556
public/js/Chart.StackedBar.js
Normal file
@ -0,0 +1,556 @@
|
||||
(function (factory) {
|
||||
"use strict";
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['chart.js'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS
|
||||
module.exports = factory(require('chart.js'));
|
||||
} else {
|
||||
// Global browser
|
||||
factory(Chart);
|
||||
}
|
||||
}(function (Chart) {
|
||||
"use strict";
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
var defaultConfig = {
|
||||
scaleBeginAtZero : true,
|
||||
|
||||
//Boolean - Whether grid lines are shown across the chart
|
||||
scaleShowGridLines : true,
|
||||
|
||||
//String - Colour of the grid lines
|
||||
scaleGridLineColor : "rgba(0,0,0,.05)",
|
||||
|
||||
//Number - Width of the grid lines
|
||||
scaleGridLineWidth : 1,
|
||||
|
||||
//Boolean - Whether to show horizontal lines (except X axis)
|
||||
scaleShowHorizontalLines: true,
|
||||
|
||||
//Boolean - Whether to show vertical lines (except Y axis)
|
||||
scaleShowVerticalLines: true,
|
||||
|
||||
//Boolean - If there is a stroke on each bar
|
||||
barShowStroke : true,
|
||||
|
||||
//Number - Pixel width of the bar stroke
|
||||
barStrokeWidth : 2,
|
||||
|
||||
//Number - Spacing between each of the X value sets
|
||||
barValueSpacing : 5,
|
||||
|
||||
//Boolean - Whether bars should be rendered on a percentage base
|
||||
relativeBars : false,
|
||||
|
||||
//String - A legend template
|
||||
legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
|
||||
|
||||
//Boolean - Show total legend
|
||||
showTotal: false,
|
||||
|
||||
//String - Color of total legend
|
||||
totalColor: '#fff',
|
||||
|
||||
//String - Total Label
|
||||
totalLabel: 'Total',
|
||||
|
||||
//Boolean - Hide labels with value set to 0
|
||||
tooltipHideZero: false
|
||||
};
|
||||
|
||||
Chart.Type.extend({
|
||||
name: "StackedBar",
|
||||
defaults : defaultConfig,
|
||||
initialize: function(data){
|
||||
//Expose options as a scope variable here so we can access it in the ScaleClass
|
||||
var options = this.options;
|
||||
|
||||
// Save data as a source for updating of values & methods
|
||||
this.data = data;
|
||||
|
||||
this.ScaleClass = Chart.Scale.extend({
|
||||
offsetGridLines : true,
|
||||
calculateBarX : function(barIndex){
|
||||
return this.calculateX(barIndex);
|
||||
},
|
||||
calculateBarY : function(datasets, dsIndex, barIndex, value){
|
||||
var offset = 0,
|
||||
sum = 0;
|
||||
|
||||
for(var i = 0; i < datasets.length; i++) {
|
||||
sum += datasets[i].bars[barIndex].value;
|
||||
}
|
||||
for(i = dsIndex; i < datasets.length; i++) {
|
||||
if(i === dsIndex && value) {
|
||||
offset += value;
|
||||
} else {
|
||||
offset = +offset + +datasets[i].bars[barIndex].value;
|
||||
}
|
||||
}
|
||||
|
||||
if(options.relativeBars) {
|
||||
offset = offset / sum * 100;
|
||||
}
|
||||
|
||||
return this.calculateY(offset);
|
||||
},
|
||||
calculateBaseWidth : function(){
|
||||
return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing);
|
||||
},
|
||||
calculateBaseHeight : function(){
|
||||
return (this.calculateY(1) - this.calculateY(0));
|
||||
},
|
||||
calculateBarWidth : function(datasetCount){
|
||||
//The padding between datasets is to the right of each bar, providing that there are more than 1 dataset
|
||||
return this.calculateBaseWidth();
|
||||
},
|
||||
calculateBarHeight : function(datasets, dsIndex, barIndex, value) {
|
||||
var sum = 0;
|
||||
|
||||
for(var i = 0; i < datasets.length; i++) {
|
||||
sum += datasets[i].bars[barIndex].value;
|
||||
}
|
||||
|
||||
if(!value) {
|
||||
value = datasets[dsIndex].bars[barIndex].value;
|
||||
}
|
||||
|
||||
if(options.relativeBars) {
|
||||
value = value / sum * 100;
|
||||
}
|
||||
|
||||
return this.calculateY(value);
|
||||
}
|
||||
});
|
||||
|
||||
this.datasets = [];
|
||||
|
||||
//Set up tooltip events on the chart
|
||||
if (this.options.showTooltips){
|
||||
helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
|
||||
var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : [];
|
||||
|
||||
this.eachBars(function(bar){
|
||||
bar.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
helpers.each(activeBars, function(activeBar){
|
||||
activeBar.fillColor = activeBar.highlightFill;
|
||||
activeBar.strokeColor = activeBar.highlightStroke;
|
||||
});
|
||||
this.showTooltip(activeBars);
|
||||
});
|
||||
}
|
||||
|
||||
//Declare the extension of the default point, to cater for the options passed in to the constructor
|
||||
this.BarClass = Chart.Rectangle.extend({
|
||||
strokeWidth : this.options.barStrokeWidth,
|
||||
showStroke : this.options.barShowStroke,
|
||||
ctx : this.chart.ctx
|
||||
});
|
||||
|
||||
//Iterate through each of the datasets, and build this into a property of the chart
|
||||
helpers.each(data.datasets,function(dataset,datasetIndex){
|
||||
|
||||
var datasetObject = {
|
||||
label : dataset.label || null,
|
||||
fillColor : dataset.fillColor,
|
||||
strokeColor : dataset.strokeColor,
|
||||
bars : []
|
||||
};
|
||||
|
||||
this.datasets.push(datasetObject);
|
||||
|
||||
helpers.each(dataset.data,function(dataPoint,index){
|
||||
if(!helpers.isNumber(dataPoint)){
|
||||
dataPoint = 0;
|
||||
}
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
//Add 0 as value if !isNumber (e.g. empty values are useful when 0 values should be hidden in tooltip)
|
||||
datasetObject.bars.push(new this.BarClass({
|
||||
value : dataPoint,
|
||||
label : data.labels[index],
|
||||
datasetLabel: dataset.label,
|
||||
strokeColor : dataset.strokeColor,
|
||||
fillColor : dataset.fillColor,
|
||||
highlightFill : dataset.highlightFill || dataset.fillColor,
|
||||
highlightStroke : dataset.highlightStroke || dataset.strokeColor
|
||||
}));
|
||||
},this);
|
||||
|
||||
},this);
|
||||
|
||||
this.buildScale(data.labels);
|
||||
|
||||
this.eachBars(function(bar, index, datasetIndex){
|
||||
helpers.extend(bar, {
|
||||
base: this.scale.endPoint,
|
||||
height: 0,
|
||||
width : this.scale.calculateBarWidth(this.datasets.length),
|
||||
x: this.scale.calculateBarX(index),
|
||||
y: this.scale.endPoint
|
||||
});
|
||||
bar.save();
|
||||
}, this);
|
||||
|
||||
this.render();
|
||||
},
|
||||
showTooltip : function(ChartElements, forceRedraw){
|
||||
// Only redraw the chart if we've actually changed what we're hovering on.
|
||||
if (typeof this.activeElements === 'undefined') this.activeElements = [];
|
||||
|
||||
helpers = Chart.helpers;
|
||||
|
||||
var isChanged = (function(Elements){
|
||||
var changed = false;
|
||||
|
||||
if (Elements.length !== this.activeElements.length){
|
||||
changed = true;
|
||||
return changed;
|
||||
}
|
||||
|
||||
helpers.each(Elements, function(element, index){
|
||||
if (element !== this.activeElements[index]){
|
||||
changed = true;
|
||||
}
|
||||
}, this);
|
||||
return changed;
|
||||
}).call(this, ChartElements);
|
||||
|
||||
if (!isChanged && !forceRedraw){
|
||||
return;
|
||||
}
|
||||
else{
|
||||
this.activeElements = ChartElements;
|
||||
}
|
||||
this.draw();
|
||||
if(this.options.customTooltips){
|
||||
this.options.customTooltips(false);
|
||||
}
|
||||
if (ChartElements.length > 0){
|
||||
// If we have multiple datasets, show a MultiTooltip for all of the data points at that index
|
||||
if (this.datasets && this.datasets.length > 1) {
|
||||
var dataArray,
|
||||
dataIndex;
|
||||
|
||||
for (var i = this.datasets.length - 1; i >= 0; i--) {
|
||||
dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments;
|
||||
dataIndex = helpers.indexOf(dataArray, ChartElements[0]);
|
||||
if (dataIndex !== -1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
var tooltipLabels = [],
|
||||
tooltipColors = [],
|
||||
medianPosition = (function(index) {
|
||||
|
||||
// Get all the points at that particular index
|
||||
var Elements = [],
|
||||
dataCollection,
|
||||
xPositions = [],
|
||||
yPositions = [],
|
||||
xMax,
|
||||
yMax,
|
||||
xMin,
|
||||
yMin;
|
||||
helpers.each(this.datasets, function(dataset){
|
||||
dataCollection = dataset.points || dataset.bars || dataset.segments;
|
||||
if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){
|
||||
Elements.push(dataCollection[dataIndex]);
|
||||
}
|
||||
});
|
||||
|
||||
var total = {
|
||||
datasetLabel: this.options.totalLabel,
|
||||
value: 0,
|
||||
fillColor: this.options.totalColor,
|
||||
strokeColor: this.options.totalColor
|
||||
};
|
||||
|
||||
helpers.each(Elements, function(element) {
|
||||
if (this.options.tooltipHideZero && element.value === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
xPositions.push(element.x);
|
||||
yPositions.push(element.y);
|
||||
|
||||
total.value += element.value;
|
||||
|
||||
//Include any colour information about the element
|
||||
tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element));
|
||||
tooltipColors.push({
|
||||
fill: element._saved.fillColor || element.fillColor,
|
||||
stroke: element._saved.strokeColor || element.strokeColor
|
||||
});
|
||||
|
||||
}, this);
|
||||
|
||||
if (this.options.showTotal) {
|
||||
tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, total));
|
||||
tooltipColors.push({
|
||||
fill: total.fillColor,
|
||||
stroke: total.strokeColor
|
||||
});
|
||||
}
|
||||
|
||||
yMin = helpers.min(yPositions);
|
||||
yMax = helpers.max(yPositions);
|
||||
|
||||
xMin = helpers.min(xPositions);
|
||||
xMax = helpers.max(xPositions);
|
||||
|
||||
return {
|
||||
x: (xMin > this.chart.width/2) ? xMin : xMax,
|
||||
y: (yMin + yMax)/2
|
||||
};
|
||||
}).call(this, dataIndex);
|
||||
|
||||
new Chart.MultiTooltip({
|
||||
x: medianPosition.x,
|
||||
y: medianPosition.y,
|
||||
xPadding: this.options.tooltipXPadding,
|
||||
yPadding: this.options.tooltipYPadding,
|
||||
xOffset: this.options.tooltipXOffset,
|
||||
fillColor: this.options.tooltipFillColor,
|
||||
textColor: this.options.tooltipFontColor,
|
||||
fontFamily: this.options.tooltipFontFamily,
|
||||
fontStyle: this.options.tooltipFontStyle,
|
||||
fontSize: this.options.tooltipFontSize,
|
||||
titleTextColor: this.options.tooltipTitleFontColor,
|
||||
titleFontFamily: this.options.tooltipTitleFontFamily,
|
||||
titleFontStyle: this.options.tooltipTitleFontStyle,
|
||||
titleFontSize: this.options.tooltipTitleFontSize,
|
||||
cornerRadius: this.options.tooltipCornerRadius,
|
||||
labels: tooltipLabels,
|
||||
legendColors: tooltipColors,
|
||||
legendColorBackground : this.options.multiTooltipKeyBackground,
|
||||
title: ChartElements[0].label,
|
||||
chart: this.chart,
|
||||
ctx: this.chart.ctx,
|
||||
custom: this.options.customTooltips
|
||||
}).draw();
|
||||
|
||||
} else {
|
||||
helpers.each(ChartElements, function(Element) {
|
||||
var tooltipPosition = Element.tooltipPosition();
|
||||
new Chart.Tooltip({
|
||||
x: Math.round(tooltipPosition.x),
|
||||
y: Math.round(tooltipPosition.y),
|
||||
xPadding: this.options.tooltipXPadding,
|
||||
yPadding: this.options.tooltipYPadding,
|
||||
fillColor: this.options.tooltipFillColor,
|
||||
textColor: this.options.tooltipFontColor,
|
||||
fontFamily: this.options.tooltipFontFamily,
|
||||
fontStyle: this.options.tooltipFontStyle,
|
||||
fontSize: this.options.tooltipFontSize,
|
||||
caretHeight: this.options.tooltipCaretSize,
|
||||
cornerRadius: this.options.tooltipCornerRadius,
|
||||
text: helpers.template(this.options.tooltipTemplate, Element),
|
||||
chart: this.chart,
|
||||
custom: this.options.customTooltips
|
||||
}).draw();
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
update : function(){
|
||||
|
||||
//Iterate through each of the datasets, and build this into a property of the chart
|
||||
helpers.each(this.data.datasets,function(dataset,datasetIndex){
|
||||
|
||||
helpers.extend(this.datasets[datasetIndex], {
|
||||
label : dataset.label || null,
|
||||
fillColor : dataset.fillColor,
|
||||
strokeColor : dataset.strokeColor,
|
||||
});
|
||||
|
||||
helpers.each(dataset.data,function(dataPoint,index){
|
||||
helpers.extend(this.datasets[datasetIndex].bars[index], {
|
||||
value : dataPoint,
|
||||
label : this.data.labels[index],
|
||||
datasetLabel: dataset.label,
|
||||
strokeColor : dataset.strokeColor,
|
||||
fillColor : dataset.fillColor,
|
||||
highlightFill : dataset.highlightFill || dataset.fillColor,
|
||||
highlightStroke : dataset.highlightStroke || dataset.strokeColor
|
||||
});
|
||||
},this);
|
||||
|
||||
},this);
|
||||
|
||||
|
||||
this.scale.update();
|
||||
// Reset any highlight colours before updating.
|
||||
helpers.each(this.activeElements, function(activeElement){
|
||||
activeElement.restore(['fillColor', 'strokeColor']);
|
||||
});
|
||||
|
||||
this.eachBars(function(bar){
|
||||
bar.save();
|
||||
});
|
||||
this.render();
|
||||
},
|
||||
eachBars : function(callback){
|
||||
helpers.each(this.datasets,function(dataset, datasetIndex){
|
||||
helpers.each(dataset.bars, callback, this, datasetIndex);
|
||||
},this);
|
||||
},
|
||||
getBarsAtEvent : function(e){
|
||||
var barsArray = [],
|
||||
eventPosition = helpers.getRelativePosition(e),
|
||||
datasetIterator = function(dataset){
|
||||
barsArray.push(dataset.bars[barIndex]);
|
||||
},
|
||||
barIndex;
|
||||
|
||||
for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
|
||||
for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) {
|
||||
if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){
|
||||
helpers.each(this.datasets, datasetIterator);
|
||||
return barsArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return barsArray;
|
||||
},
|
||||
buildScale : function(labels){
|
||||
var self = this;
|
||||
|
||||
var dataTotal = function(){
|
||||
var values = [];
|
||||
helpers.each(self.datasets, function(dataset) {
|
||||
helpers.each(dataset.bars, function(bar, barIndex) {
|
||||
if(!values[barIndex]) values[barIndex] = 0;
|
||||
if(self.options.relativeBars) {
|
||||
values[barIndex] = 100;
|
||||
} else {
|
||||
values[barIndex] = +values[barIndex] + +bar.value;
|
||||
}
|
||||
});
|
||||
});
|
||||
return values;
|
||||
};
|
||||
|
||||
var scaleOptions = {
|
||||
templateString : this.options.scaleLabel,
|
||||
height : this.chart.height,
|
||||
width : this.chart.width,
|
||||
ctx : this.chart.ctx,
|
||||
textColor : this.options.scaleFontColor,
|
||||
fontSize : this.options.scaleFontSize,
|
||||
fontStyle : this.options.scaleFontStyle,
|
||||
fontFamily : this.options.scaleFontFamily,
|
||||
valuesCount : labels.length,
|
||||
beginAtZero : this.options.scaleBeginAtZero,
|
||||
integersOnly : this.options.scaleIntegersOnly,
|
||||
calculateYRange: function(currentHeight){
|
||||
var updatedRanges = helpers.calculateScaleRange(
|
||||
dataTotal(),
|
||||
currentHeight,
|
||||
this.fontSize,
|
||||
this.beginAtZero,
|
||||
this.integersOnly
|
||||
);
|
||||
helpers.extend(this, updatedRanges);
|
||||
},
|
||||
xLabels : this.options.xLabels || labels,
|
||||
font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily),
|
||||
lineWidth : this.options.scaleLineWidth,
|
||||
lineColor : this.options.scaleLineColor,
|
||||
gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0,
|
||||
gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)",
|
||||
showHorizontalLines : this.options.scaleShowHorizontalLines,
|
||||
showVerticalLines : this.options.scaleShowVerticalLines,
|
||||
padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0,
|
||||
showLabels : this.options.scaleShowLabels,
|
||||
display : this.options.showScale
|
||||
};
|
||||
|
||||
if (this.options.scaleOverride){
|
||||
helpers.extend(scaleOptions, {
|
||||
calculateYRange: helpers.noop,
|
||||
steps: this.options.scaleSteps,
|
||||
stepValue: this.options.scaleStepWidth,
|
||||
min: this.options.scaleStartValue,
|
||||
max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
|
||||
});
|
||||
}
|
||||
|
||||
this.scale = new this.ScaleClass(scaleOptions);
|
||||
},
|
||||
addData : function(valuesArray,label){
|
||||
//Map the values array for each of the datasets
|
||||
helpers.each(valuesArray,function(value,datasetIndex){
|
||||
if (helpers.isNumber(value)){
|
||||
//Add a new point for each piece of data, passing any required data to draw.
|
||||
//Add 0 as value if !isNumber (e.g. empty values are useful when 0 values should be hidden in tooltip)
|
||||
this.datasets[datasetIndex].bars.push(new this.BarClass({
|
||||
value : helpers.isNumber(value)?value:0,
|
||||
label : label,
|
||||
x: this.scale.calculateBarX(this.scale.valuesCount+1),
|
||||
y: this.scale.endPoint,
|
||||
width : this.scale.calculateBarWidth(this.datasets.length),
|
||||
base : this.scale.endPoint,
|
||||
strokeColor : this.datasets[datasetIndex].strokeColor,
|
||||
fillColor : this.datasets[datasetIndex].fillColor
|
||||
}));
|
||||
}
|
||||
},this);
|
||||
|
||||
this.scale.addXLabel(label);
|
||||
//Then re-render the chart.
|
||||
this.update();
|
||||
},
|
||||
removeData : function(){
|
||||
this.scale.removeXLabel();
|
||||
//Then re-render the chart.
|
||||
helpers.each(this.datasets,function(dataset){
|
||||
dataset.bars.shift();
|
||||
},this);
|
||||
this.update();
|
||||
},
|
||||
reflow : function(){
|
||||
helpers.extend(this.BarClass.prototype,{
|
||||
y: this.scale.endPoint,
|
||||
base : this.scale.endPoint
|
||||
});
|
||||
var newScaleProps = helpers.extend({
|
||||
height : this.chart.height,
|
||||
width : this.chart.width
|
||||
});
|
||||
this.scale.update(newScaleProps);
|
||||
},
|
||||
draw : function(ease){
|
||||
var easingDecimal = ease || 1;
|
||||
this.clear();
|
||||
|
||||
var ctx = this.chart.ctx;
|
||||
|
||||
this.scale.draw(easingDecimal);
|
||||
|
||||
//Draw all the bars for each dataset
|
||||
helpers.each(this.datasets,function(dataset,datasetIndex){
|
||||
helpers.each(dataset.bars,function(bar,index){
|
||||
var y = this.scale.calculateBarY(this.datasets, datasetIndex, index, bar.value),
|
||||
height = this.scale.calculateBarHeight(this.datasets, datasetIndex, index, bar.value);
|
||||
|
||||
//Transition then draw
|
||||
if(bar.value > 0) {
|
||||
bar.transition({
|
||||
base : this.scale.endPoint - (Math.abs(height) - Math.abs(y)),
|
||||
x : this.scale.calculateBarX(index),
|
||||
y : Math.abs(y),
|
||||
height : Math.abs(height),
|
||||
width : this.scale.calculateBarWidth(this.datasets.length)
|
||||
}, easingDecimal).draw();
|
||||
}
|
||||
},this);
|
||||
},this);
|
||||
}
|
||||
});
|
||||
}));
|
11
public/js/Chart.min.js
vendored
Normal file
11
public/js/Chart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
/* global $, googleLineChart, accountID, token */
|
||||
/* global $, lineChart, accountID, token */
|
||||
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
@ -12,8 +12,8 @@ var fixHelper = function (e, ui) {
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(googleLineChart) === "function" && typeof accountID !== 'undefined') {
|
||||
googleLineChart('chart/account/' + accountID, 'overview-chart');
|
||||
if (typeof(lineChart) === "function" && typeof accountID !== 'undefined') {
|
||||
lineChart('chart/account/' + accountID, 'overview-chart');
|
||||
}
|
||||
|
||||
// sortable!
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* global googleComboChart, billID */
|
||||
/* global comboChart, billID */
|
||||
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
if (typeof(googleComboChart) === 'function' && typeof(billID) !== 'undefined') {
|
||||
googleComboChart('chart/bill/' + billID, 'bill-overview');
|
||||
}
|
||||
}
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(comboChart) === 'function' && typeof(billID) !== 'undefined') {
|
||||
comboChart('chart/bill/' + billID, 'bill-overview');
|
||||
}
|
||||
}
|
||||
);
|
@ -1,4 +1,4 @@
|
||||
/* globals $, budgeted:true, currencySymbol, budgetIncomeTotal ,budgetedMuch, budgetedPercentage, token, budgetID, repetitionID, spent, googleLineChart */
|
||||
/* globals $, budgeted:true, currencySymbol, budgetIncomeTotal, columnChart, budgetedMuch, budgetedPercentage, token, budgetID, repetitionID, spent, lineChart */
|
||||
|
||||
function drawSpentBar() {
|
||||
"use strict";
|
||||
@ -95,104 +95,19 @@ $(function () {
|
||||
$('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') {
|
||||
googleColumnChart('chart/budget/' + budgetID, 'budgetOverview');
|
||||
columnChart('chart/budget/' + budgetID, 'budgetOverview');
|
||||
}
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID !== 'undefined') {
|
||||
googleLineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview');
|
||||
lineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
//function updateSingleRange(e) {
|
||||
// "use strict";
|
||||
// // get some values:
|
||||
// var input = $(e.target);
|
||||
// var id = input.data('id');
|
||||
// var value = parseInt(input.val());
|
||||
// var spent = parseFloat($('#spent-' + id).data('value'));
|
||||
//
|
||||
// // update small display:
|
||||
// if (value > 0) {
|
||||
// // show the input:
|
||||
// $('#budget-info-' + id + ' span').show();
|
||||
// $('#budget-info-' + id + ' input').show();
|
||||
//
|
||||
// // update the text:
|
||||
// $('#budget-description-' + id).text('Budgeted: ');
|
||||
// } else {
|
||||
// // hide the input:
|
||||
// $('#budget-info-' + id + ' span').hide();
|
||||
// $('#budget-info-' + id + ' input').hide();
|
||||
//
|
||||
// // 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));
|
||||
//
|
||||
// // 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:
|
||||
// $('#budget-link-' + id).attr('href', 'budgets/show/' + id + '/' + data.repetition);
|
||||
// });
|
||||
// if (input.attr('type') === 'number') {
|
||||
// // update the range-input:
|
||||
// $('#budget-range-' + id).val(value);
|
||||
// } else {
|
||||
// // update the number-input:
|
||||
// $('#budget-info-' + id + ' input').val(value);
|
||||
// }
|
||||
//
|
||||
// // update or hide the bar, whichever is necessary.
|
||||
// updateTotal();
|
||||
// return value;
|
||||
//}
|
||||
//
|
||||
//function updateTotal() {
|
||||
// "use strict";
|
||||
// var sum = 0;
|
||||
// $('input[type="range"]').each(function (i, v) {
|
||||
// // get some values:
|
||||
// sum += parseInt($(v).val());
|
||||
// });
|
||||
//
|
||||
// /**
|
||||
// * Update total sum:
|
||||
// */
|
||||
// var totalAmount = parseInt($('#totalAmount').data('value'));
|
||||
// var pct;
|
||||
// if (sum <= totalAmount) {
|
||||
// pct = sum / totalAmount * 100;
|
||||
// $('#progress-bar-default').css('width', pct + '%');
|
||||
// $('#progress-bar-warning').css('width', '0');
|
||||
// $('#progress-bar-danger').css('width', '0');
|
||||
// $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger');
|
||||
// } else {
|
||||
// // we gaan er X overheen,
|
||||
//
|
||||
// pct = totalAmount / sum * 100;
|
||||
// var danger = 100 - pct;
|
||||
// var err = 100 - danger;
|
||||
// $('#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');
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
function updateIncome(e) {
|
||||
function updateIncome() {
|
||||
"use strict";
|
||||
$('#defaultModal').empty().load('budgets/income', function () {
|
||||
$('#defaultModal').modal('show');
|
||||
@ -200,51 +115,3 @@ function updateIncome(e) {
|
||||
|
||||
return false;
|
||||
}
|
||||
//
|
||||
//function updateRanges() {
|
||||
// "use strict";
|
||||
//
|
||||
//
|
||||
// var sum = 0;
|
||||
// $('input[type="range"]').each(function (i, v) {
|
||||
// // get some values:
|
||||
// var input = $(v);
|
||||
// var id = input.data('id');
|
||||
// var value = parseInt(input.val());
|
||||
//
|
||||
// // calculate sum:
|
||||
// sum += value;
|
||||
//
|
||||
// // update small display:
|
||||
// $('#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});
|
||||
//
|
||||
// });
|
||||
//
|
||||
// /**
|
||||
// * Update total sum:
|
||||
// */
|
||||
// var totalAmount = parseInt($('#totalAmount').data('value'));
|
||||
// var pct;
|
||||
// if (sum <= totalAmount) {
|
||||
// pct = sum / totalAmount * 100;
|
||||
// $('#progress-bar-default').css('width', pct + '%');
|
||||
// $('#progress-bar-warning').css('width', '0');
|
||||
// $('#progress-bar-danger').css('width', '0');
|
||||
// $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger');
|
||||
// } else {
|
||||
// // we gaan er X overheen,
|
||||
//
|
||||
// pct = totalAmount / sum * 100;
|
||||
// var danger = 100 - pct;
|
||||
// var err = 100 - danger;
|
||||
// $('#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');
|
||||
// }
|
||||
//
|
||||
//
|
||||
//}
|
@ -1,9 +1,9 @@
|
||||
/* globals $, categoryID, googleColumnChart */
|
||||
/* globals $, categoryID, columnChart */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
googleColumnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
googleColumnChart('chart/category/' + categoryID + '/month', 'month');
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
columnChart('chart/category/' + categoryID + '/month', 'month');
|
||||
}
|
||||
|
||||
|
||||
|
294
public/js/charts.js
Normal file
294
public/js/charts.js
Normal file
@ -0,0 +1,294 @@
|
||||
/* globals $, Chart, currencySymbol */
|
||||
|
||||
/*
|
||||
Make some colours:
|
||||
*/
|
||||
/*
|
||||
#555299
|
||||
#4285f4
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
#", "#", "#", "#"],
|
||||
*/
|
||||
var colourSet = [
|
||||
[53, 124, 165],
|
||||
[0, 141, 76],
|
||||
[219, 139, 11],
|
||||
[202, 25, 90],
|
||||
[85, 82, 153],
|
||||
[66, 133, 244],
|
||||
[219, 68, 55],
|
||||
[244, 180, 0],
|
||||
[15, 157, 88],
|
||||
[171, 71, 188],
|
||||
[0, 172, 193],
|
||||
[255, 112, 67],
|
||||
[158, 157, 36],
|
||||
[92, 107, 192],
|
||||
[240, 98, 146],
|
||||
[0, 121, 107],
|
||||
[194, 24, 91],
|
||||
|
||||
];
|
||||
|
||||
var fillColors = [];
|
||||
var strokePointHighColors = [];
|
||||
|
||||
|
||||
for (var i = 0; i < colourSet.length; i++) {
|
||||
fillColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.2)");
|
||||
strokePointHighColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.9)");
|
||||
}
|
||||
|
||||
/*
|
||||
Set default options:
|
||||
*/
|
||||
var defaultAreaOptions = {
|
||||
scaleShowGridLines: false,
|
||||
pointDotRadius: 2,
|
||||
datasetStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: true,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
scaleLabel: " <%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
multiTooltipTemplate: "<%=datasetLabel%>: <%= '" + currencySymbol + " ' + Number(value).toFixed(2).replace('.', ',') %>"
|
||||
};
|
||||
|
||||
|
||||
var defaultPieOptions = {
|
||||
scaleShowGridLines: false,
|
||||
pointDotRadius: 2,
|
||||
datasetStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
tooltipTemplate: "<%if (label){%><%=label%>: <%}%>" + currencySymbol + " <%= value %>",
|
||||
|
||||
};
|
||||
|
||||
|
||||
var defaultLineOptions = {
|
||||
scaleShowGridLines: false,
|
||||
pointDotRadius: 2,
|
||||
datasetStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
tooltipTemplate: "<%if (label){%><%=label%>: <%}%>" + currencySymbol + " <%= value %>",
|
||||
};
|
||||
|
||||
var defaultColumnOptions = {
|
||||
scaleShowGridLines: false,
|
||||
pointDotRadius: 2,
|
||||
barStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
tooltipTemplate: "<%if (label){%><%=label%>: <%}%>" + currencySymbol + " <%= value %>",
|
||||
multiTooltipTemplate: "<%=datasetLabel%>: " + currencySymbol + " <%= Number(value).toFixed(2).replace('.', ',') %>"
|
||||
};
|
||||
|
||||
var defaultStackedColumnOptions = {
|
||||
scaleShowGridLines: false,
|
||||
pointDotRadius: 2,
|
||||
barStrokeWidth: 1,
|
||||
pointHitDetectionRadius: 5,
|
||||
datasetFill: false,
|
||||
scaleFontSize: 10,
|
||||
responsive: false,
|
||||
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
|
||||
tooltipFillColor: "rgba(0,0,0,0.5)",
|
||||
multiTooltipTemplate: "<%=datasetLabel%>: " + currencySymbol + " <%= Number(value).toFixed(2).replace('.', ',') %>"
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to draw a line chart:
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function lineChart(URL, container, options) {
|
||||
"use strict";
|
||||
options = options || defaultLineOptions;
|
||||
|
||||
$.getJSON(URL).success(function (data) {
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.fillColor = fillColors[i];
|
||||
dataset.strokeColor = strokePointHighColors[i];
|
||||
dataset.pointColor = strokePointHighColors[i];
|
||||
dataset.pointStrokeColor = "#fff";
|
||||
dataset.pointHighlightFill = "#fff";
|
||||
dataset.pointHighlightStroke = strokePointHighColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
new Chart(ctx).Line(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
});
|
||||
console.log('URL for line chart : ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to draw an area chart:
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function areaChart(URL, container, options) {
|
||||
"use strict";
|
||||
options = options || defaultAreaOptions;
|
||||
|
||||
$.getJSON(URL).success(function (data) {
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.fillColor = fillColors[i];
|
||||
dataset.strokeColor = strokePointHighColors[i];
|
||||
dataset.pointColor = strokePointHighColors[i];
|
||||
dataset.pointStrokeColor = "#fff";
|
||||
dataset.pointHighlightFill = "#fff";
|
||||
dataset.pointHighlightStroke = strokePointHighColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
new Chart(ctx).Line(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
});
|
||||
|
||||
console.log('URL for area chart: ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function columnChart(URL, container, options) {
|
||||
"use strict";
|
||||
options = options || defaultColumnOptions;
|
||||
|
||||
$.getJSON(URL).success(function (data) {
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.fillColor = fillColors[i];
|
||||
dataset.strokeColor = strokePointHighColors[i];
|
||||
dataset.pointColor = strokePointHighColors[i];
|
||||
dataset.pointStrokeColor = "#fff";
|
||||
dataset.pointHighlightFill = "#fff";
|
||||
dataset.pointHighlightStroke = strokePointHighColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
new Chart(ctx).Bar(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
});
|
||||
console.log('URL for column chart : ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function stackedColumnChart(URL, container, options) {
|
||||
"use strict";
|
||||
options = options || defaultStackedColumnOptions;
|
||||
|
||||
$.getJSON(URL).success(function (data) {
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.fillColor = fillColors[i];
|
||||
dataset.strokeColor = strokePointHighColors[i];
|
||||
dataset.pointColor = strokePointHighColors[i];
|
||||
dataset.pointStrokeColor = "#fff";
|
||||
dataset.pointHighlightFill = "#fff";
|
||||
dataset.pointHighlightStroke = strokePointHighColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
new Chart(ctx).StackedBar(newData, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
});
|
||||
console.log('URL for stacked column chart : ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function comboChart(URL, container, options) {
|
||||
"use strict";
|
||||
columnChart(URL, container, options);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function pieChart(URL, container, options) {
|
||||
"use strict";
|
||||
|
||||
options = options || defaultPieOptions;
|
||||
$.getJSON(URL).success(function (data) {
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
new Chart(ctx).Pie(data, options);
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('google-chart-error');
|
||||
});
|
||||
|
||||
|
||||
console.log('URL for pie chart : ' + URL);
|
||||
|
||||
}
|
@ -1,7 +1,221 @@
|
||||
/* globals currencyCode,defaultAreaChartOptions , language, defaultPieChartOptions, defaultLineChartOptions, defaultColumnChartOptions, defaultBarChartOptions, defaultStackedColumnChartOptions, defaultComboChartOptions */
|
||||
/* exported googleLineChart, googleBarChart, googleColumnChart, googleStackedColumnChart, googleComboChart, googlePieChart */
|
||||
/* globals currencyCode, language */
|
||||
/* exported lineChart, googleColumnChart, stackedColumnChart, comboChart, pieChart, defaultLineChartOptions, defaultAreaChartOptions, defaultBarChartOptions, defaultComboChartOptions, defaultColumnChartOptions, defaultStackedColumnChartOptions, defaultPieChartOptions */
|
||||
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});
|
||||
|
||||
|
||||
/* exported */
|
||||
|
||||
var defaultLineChartOptions = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
interpolateNulls: true,
|
||||
lineWidth: 1,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '95%',
|
||||
height: '90%'
|
||||
},
|
||||
height: 400,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
fontSize: 11,
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var defaultAreaChartOptions = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
interpolateNulls: true,
|
||||
lineWidth: 1,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '95%',
|
||||
height: '90%'
|
||||
},
|
||||
height: 400,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
fontSize: 11,
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var defaultBarChartOptions = {
|
||||
height: 400,
|
||||
bars: 'horizontal',
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
|
||||
},
|
||||
fontSize: 11,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
textPosition: 'in',
|
||||
gridlines: {
|
||||
|
||||
color: 'transparent'
|
||||
},
|
||||
baselineColor: '#aaaaaa'
|
||||
},
|
||||
chartArea: {
|
||||
left: 15,
|
||||
top: 10,
|
||||
width: '100%',
|
||||
height: '90%'
|
||||
},
|
||||
|
||||
legend: {
|
||||
position: 'none'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultComboChartOptions = {
|
||||
height: 300,
|
||||
chartArea: {
|
||||
left: 75,
|
||||
top: 10,
|
||||
width: '100%',
|
||||
height: '90%'
|
||||
},
|
||||
vAxis: {
|
||||
minValue: 0,
|
||||
format: '\u20AC #'
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
fontSize: 11,
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
series: {
|
||||
0: {type: 'line'},
|
||||
1: {type: 'line'},
|
||||
2: {type: 'bars'}
|
||||
},
|
||||
bar: {groupWidth: 20}
|
||||
};
|
||||
|
||||
var defaultColumnChartOptions = {
|
||||
height: 400,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '85%',
|
||||
height: '80%'
|
||||
},
|
||||
fontSize: 11,
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
},
|
||||
baselineColor: '#aaaaaa'
|
||||
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
},
|
||||
legend: {
|
||||
position: 'none'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultStackedColumnChartOptions = {
|
||||
height: 400,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '85%',
|
||||
height: '80%'
|
||||
},
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
fontSize: 11,
|
||||
isStacked: true,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
format: '\u20AC #'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultPieChartOptions = {
|
||||
chartArea: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
fontSize: 11,
|
||||
height: 200,
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
};
|
||||
|
||||
|
||||
function googleChart(chartType, URL, container, options) {
|
||||
"use strict";
|
||||
@ -33,7 +247,7 @@ function googleChart(chartType, URL, container, options) {
|
||||
chart = new google.visualization.LineChart(document.getElementById(container));
|
||||
options = options || defaultLineChartOptions;
|
||||
}
|
||||
if(chartType === 'area') {
|
||||
if (chartType === 'area') {
|
||||
chart = new google.visualization.AreaChart(document.getElementById(container));
|
||||
options = options || defaultAreaChartOptions;
|
||||
}
|
||||
@ -74,38 +288,32 @@ function googleChart(chartType, URL, container, options) {
|
||||
}
|
||||
|
||||
|
||||
function googleLineChart(URL, container, options) {
|
||||
function lineChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('line', URL, container, options);
|
||||
}
|
||||
|
||||
function googleAreaChart(URL, container, options) {
|
||||
function areaChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('area', URL, container, options);
|
||||
}
|
||||
|
||||
|
||||
function googleBarChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('bar', URL, container, options);
|
||||
}
|
||||
|
||||
function googleColumnChart(URL, container, options) {
|
||||
function columnChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('column', URL, container, options);
|
||||
}
|
||||
|
||||
function googleStackedColumnChart(URL, container, options) {
|
||||
function stackedColumnChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('stackedColumn', URL, container, options);
|
||||
}
|
||||
|
||||
function googleComboChart(URL, container, options) {
|
||||
function comboChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('combo', URL, container, options);
|
||||
}
|
||||
|
||||
function googlePieChart(URL, container, options) {
|
||||
function pieChart(URL, container, options) {
|
||||
"use strict";
|
||||
return googleChart('pie', URL, container, options);
|
||||
}
|
||||
|
@ -1,218 +0,0 @@
|
||||
/* exported defaultLineChartOptions, defaultAreaChartOptions, defaultBarChartOptions, defaultComboChartOptions, defaultColumnChartOptions, defaultStackedColumnChartOptions, defaultPieChartOptions */
|
||||
|
||||
var defaultLineChartOptions = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
interpolateNulls: true,
|
||||
lineWidth: 1,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '95%',
|
||||
height: '90%'
|
||||
},
|
||||
height: 400,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var defaultAreaChartOptions = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
interpolateNulls: true,
|
||||
lineWidth: 1,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '95%',
|
||||
height: '90%'
|
||||
},
|
||||
height: 400,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
var defaultBarChartOptions = {
|
||||
height: 400,
|
||||
bars: 'horizontal',
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
colors: ["#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
textPosition: 'in',
|
||||
gridlines: {
|
||||
|
||||
color: 'transparent'
|
||||
},
|
||||
baselineColor: '#aaaaaa'
|
||||
},
|
||||
chartArea: {
|
||||
left: 15,
|
||||
top: 10,
|
||||
width: '100%',
|
||||
height: '90%'
|
||||
},
|
||||
|
||||
legend: {
|
||||
position: 'none'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultComboChartOptions = {
|
||||
height: 300,
|
||||
chartArea: {
|
||||
left: 75,
|
||||
top: 10,
|
||||
width: '100%',
|
||||
height: '90%'
|
||||
},
|
||||
vAxis: {
|
||||
minValue: 0,
|
||||
format: '\u20AC #'
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
series: {
|
||||
0: {type: 'line'},
|
||||
1: {type: 'line'},
|
||||
2: {type: 'bars'}
|
||||
},
|
||||
bar: {groupWidth: 20}
|
||||
};
|
||||
|
||||
var defaultColumnChartOptions = {
|
||||
height: 400,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '85%',
|
||||
height: '80%'
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
},
|
||||
baselineColor: '#aaaaaa'
|
||||
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383'
|
||||
},
|
||||
baselineColor: '#aaaaaa',
|
||||
format: '\u20AC #'
|
||||
},
|
||||
legend: {
|
||||
position: 'none'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultStackedColumnChartOptions = {
|
||||
height: 400,
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '85%',
|
||||
height: '80%'
|
||||
},
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
isStacked: true,
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
hAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
gridlines: {
|
||||
color: 'transparent'
|
||||
}
|
||||
},
|
||||
vAxis: {
|
||||
textStyle: {
|
||||
color: '#838383',
|
||||
},
|
||||
format: '\u20AC #'
|
||||
}
|
||||
};
|
||||
|
||||
var defaultPieChartOptions = {
|
||||
chartArea: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: '100%',
|
||||
height: '100%'
|
||||
},
|
||||
fontName: 'Roboto',
|
||||
fontSize: 11,
|
||||
height: 200,
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
|
||||
};
|
||||
|
@ -1,13 +1,22 @@
|
||||
/* globals $, googleColumnChart, google, googleLineChart, googlePieChart, googleStackedColumnChart */
|
||||
google.setOnLoadCallback(drawChart);
|
||||
/* globals $, columnChart, google, lineChart, pieChart, stackedColumnChart, areaChart */
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof google !== 'undefined') {
|
||||
// do google charts:
|
||||
google.setOnLoadCallback(drawChart);
|
||||
} else {
|
||||
// do chart JS stuff.
|
||||
drawChart();
|
||||
}
|
||||
});
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
googleAreaChart('chart/account/frontpage', 'accounts-chart');
|
||||
googlePieChart('chart/bill/frontpage', 'bills-chart');
|
||||
googleStackedColumnChart('chart/budget/frontpage', 'budgets-chart');
|
||||
googleColumnChart('chart/category/frontpage', 'categories-chart');
|
||||
areaChart('chart/account/frontpage', 'accounts-chart');
|
||||
pieChart('chart/bill/frontpage', 'bills-chart');
|
||||
stackedColumnChart('chart/budget/frontpage', 'budgets-chart');
|
||||
columnChart('chart/category/frontpage', 'categories-chart');
|
||||
|
||||
|
||||
getBoxAmounts();
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* globals $, googleLineChart, token, piggyBankID */
|
||||
/* globals $, lineChart, token, piggyBankID */
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, tr) {
|
||||
@ -17,8 +17,8 @@ $(function () {
|
||||
$('.addMoney').on('click', addMoney);
|
||||
$('.removeMoney').on('click', removeMoney);
|
||||
|
||||
if (typeof(googleLineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
|
||||
googleLineChart('chart/piggyBank/' + piggyBankID, 'piggy-bank-history');
|
||||
if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
|
||||
lineChart('chart/piggyBank/' + piggyBankID, 'piggy-bank-history');
|
||||
}
|
||||
|
||||
$('#sortable tbody').sortable(
|
||||
|
@ -1,22 +1,31 @@
|
||||
/* globals google, expenseRestShow:true, incomeRestShow:true, year, shared, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, googleColumnChart, googleLineChart, googleStackedColumnChart */
|
||||
if (typeof(google) !== 'undefined') {
|
||||
google.setOnLoadCallback(drawChart);
|
||||
}
|
||||
/* globals google, expenseRestShow:true, incomeRestShow:true, year, shared, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(google) !== 'undefined') {
|
||||
google.setOnLoadCallback(drawChart);
|
||||
} else {
|
||||
drawChart();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
googleColumnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart');
|
||||
googleColumnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart');
|
||||
|
||||
googleStackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
|
||||
googleStackedColumnChart('chart/category/year/' + year + shared, 'categories');
|
||||
|
||||
googleLineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
|
||||
if (typeof columnChart !== undefined) {
|
||||
columnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart');
|
||||
columnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart');
|
||||
}
|
||||
if (typeof stackedColumnChart !== undefined) {
|
||||
stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
|
||||
stackedColumnChart('chart/category/year/' + year + shared, 'categories');
|
||||
}
|
||||
if (typeof lineChart !== undefined && typeof month !== 'undefined') {
|
||||
lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function openModal(e) {
|
||||
"use strict";
|
||||
var target = $(e.target).parent();
|
||||
|
@ -33,10 +33,6 @@ return [
|
||||
'edit_bill' => 'Edit bill ":name"',
|
||||
'delete_bill' => 'Delete bill ":name"',
|
||||
|
||||
// reminders
|
||||
'reminders' => 'Reminders',
|
||||
'reminder' => 'Reminder #:id',
|
||||
|
||||
// reports
|
||||
'reports' => 'Reports',
|
||||
'monthly_report' => 'Montly report for :date',
|
||||
|
@ -147,8 +147,6 @@ return [
|
||||
|
||||
// menu and titles, should be recycled as often as possible:
|
||||
'toggleNavigation' => 'Toggle navigation',
|
||||
'seeAllReminders' => 'See all reminders',
|
||||
'reminders' => 'Reminders',
|
||||
'currency' => 'Currency',
|
||||
'preferences' => 'Preferences',
|
||||
'logout' => 'Logout',
|
||||
@ -272,10 +270,6 @@ return [
|
||||
'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.',
|
||||
@ -293,9 +287,5 @@ return [
|
||||
'tag_title_balancingAct' => 'Balancing act tags',
|
||||
'tag_title_advancePayment' => 'Advance payment tags',
|
||||
|
||||
// reminders
|
||||
'reminder_for_piggy' => 'Reminder for piggy bank ":name"',
|
||||
'dismissed_reminder_for_piggy' => 'Dismissed reminder for piggy bank ":name"',
|
||||
|
||||
|
||||
];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user