Merge branch 'feature/twig' into develop

This commit is contained in:
James Cole 2015-05-02 21:16:21 +02:00
commit b2fd346ef8
119 changed files with 6201 additions and 51 deletions

18
.env.backup Executable file
View File

@ -0,0 +1,18 @@
APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
CACHE_DRIVER=file
SESSION_DRIVER=file
EMAIL_SMTP=
EMAIL_DRIVER=smtp
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=

18
.env.local Executable file
View File

@ -0,0 +1,18 @@
APP_ENV=local
APP_DEBUG=true
APP_KEY=SomeRandomString
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
CACHE_DRIVER=file
SESSION_DRIVER=file
EMAIL_SMTP=
EMAIL_DRIVER=smtp
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=

View File

@ -8,6 +8,7 @@ use Illuminate\Http\Request;
use Illuminate\Mail\Message;
use Mail;
use Session;
use Twig;
/**
* Class AuthController
@ -47,6 +48,16 @@ class AuthController extends Controller
$this->middleware('guest', ['except' => 'getLogout']);
}
/**
* Show the application login form.
*
* @return \Illuminate\Http\Response
*/
public function getLogin()
{
return Twig::render('auth.login');
}
/**
* Handle a registration request for the application.
*

View File

@ -8,6 +8,7 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Input;
use Preferences;
use Redirect;
@ -190,6 +191,9 @@ class BudgetController extends Controller
$journals = $repository->getJournals($budget, $repetition);
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget);
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
if (!$journals instanceof Collection) {
$journals->setPath('/budgets/show/' . $budget->id);
}
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
}

View File

@ -47,50 +47,51 @@ class ReportController extends Controller
*/
public function budget($year = '2014', $month = '1')
{
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date');
}
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Budget report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
$start->subDay();
// should show shared reports?
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$accountAmounts = []; // array with sums of spent amounts on each account.
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports); // all accounts and some data.
foreach ($accounts as $account) {
$dayEarly = clone $date;
$subTitle = 'Budget report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$dayEarly = $dayEarly->subDay();
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports);
$start->addDay();
$accounts->each(
function (Account $account) use ($start, $end) {
$budgets = $this->query->getBudgetSummary($account, $start, $end);
$budgets = $this->query->getBudgetSummary($account, $start, $end);// get budget summary for this account:
$balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end);
$accountAmounts[$account->id] = $balancedAmount;
// balance out the transactions (see transaction groups & tags) ^^
// array with budget information for each account:
$array = [];
// should always hide account
$hide = true;
// loop all budgets
foreach ($budgets as $budget) {
$id = intval($budget->id);
$data = $budget->toArray();
$array[$id] = $data;
// no longer hide account if any budget has money in it.
if (floatval($data['queryAmount']) != 0) {
$hide = false;
}
$accountAmounts[$account->id] += $data['queryAmount'];
}
$account->hide = $hide;
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
}
);
/**
* Start getBudgetsForMonth DONE
@ -101,7 +102,7 @@ class ReportController extends Controller
* End getBudgetsForMonth DONE
*/
return view('reports.budget', compact('subTitle', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly'));
return view('reports.budget', compact('subTitle', 'accountAmounts', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets'));
}

View File

@ -23,6 +23,14 @@ Breadcrumbs::register(
}
);
Breadcrumbs::register(
'index',
function (Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
}
);
// accounts
Breadcrumbs::register(
'accounts.index', function (Generator $breadcrumbs, $what) {

View File

@ -35,6 +35,7 @@ class AppServiceProvider extends ServiceProvider
'Illuminate\Contracts\Auth\Registrar',
'FireflyIII\Services\Registrar'
);
}
}

View File

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

View File

@ -2,13 +2,21 @@
namespace FireflyIII\Providers;
use App;
use FireflyIII\Models\Account;
use FireflyIII\Support\Amount;
use FireflyIII\Support\ExpandedForm;
use FireflyIII\Support\Navigation;
use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam;
use FireflyIII\Support\Twig\Budget;
use FireflyIII\Support\Twig\General;
use FireflyIII\Support\Twig\Journal;
use FireflyIII\Support\Twig\PiggyBank;
use FireflyIII\Validation\FireflyValidator;
use Illuminate\Support\ServiceProvider;
use Twig;
use TwigBridge\Extension\Loader\Functions;
use Validator;
/**
@ -25,10 +33,22 @@ class FireflyServiceProvider extends ServiceProvider
return new FireflyValidator($translator, $data, $rules, $messages);
}
);
/*
* Default Twig configuration:
*/
$config = App::make('config');
Twig::addExtension(new Functions($config));
Twig::addExtension(new PiggyBank);
Twig::addExtension(new General);
Twig::addExtension(new Journal);
Twig::addExtension(new Budget);
}
public function register()
{
$this->app->bind(
'preferences', function () {
return new Preferences;
@ -72,6 +92,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper');
$this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery');
}
}

View File

@ -160,14 +160,17 @@ class Amount
$currencyPreference = Prefs::get('currencyPreference', 'EUR');
$currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
if ($currency) {
\Cache::forever('FFCURRENCYCODE', $currency->code);
Cache::forever('FFCURRENCYCODE', $currency->code);
define('FFCURRENCYCODE', $currency->code);
return $currency->code;
}
return 'EUR';
}
public function getDefaultCurrency()
{
$currencyPreference = Prefs::get('currencyPreference', 'EUR');

View File

@ -0,0 +1,53 @@
<?php
namespace FireflyIII\Support\Twig;
use Auth;
use DB;
use FireflyIII\Models\LimitRepetition;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Class Budget
*
* @package FireflyIII\Support\Twig
*/
class Budget extends Twig_Extension
{
/**
* {@inheritDoc}
*/
public function getFunctions()
{
$functions[] = new Twig_SimpleFunction(
'spentInRepetition', function (LimitRepetition $repetition) {
$sum = DB::table('transactions')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->where('transaction_journals.date', '>=', $repetition->startdate->format('Y-m-d'))
->where('transaction_journals.date', '<=', $repetition->enddate->format('Y-m-d'))
->where('transaction_journals.user_id', Auth::user()->id)
->whereNull('transactions.deleted_at')
->where('transactions.amount', '>', 0)
->where('limit_repetitions.id', '=', $repetition->id)
->sum('transactions.amount');
return floatval($sum);
}
);
return $functions;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'FireflyIII\Support\Twig\Budget';
}
}

View File

@ -0,0 +1,146 @@
<?php
namespace FireflyIII\Support\Twig;
use App;
use Config;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use Route;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Class TwigSupport
*
* @package FireflyIII\Support
*/
class General extends Twig_Extension
{
/**
* @return array
*/
public function getFilters()
{
$filters = [];
$filters[] = new Twig_SimpleFilter(
'formatAmount', function ($string) {
return App::make('amount')->format($string);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatTransaction', function (Transaction $transaction) {
return App::make('amount')->formatTransaction($transaction);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatAmountPlain', function ($string) {
return App::make('amount')->format($string, false);
}
);
$filters[] = new Twig_SimpleFilter(
'formatJournal', function ($journal) {
return App::make('amount')->formatJournal($journal);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'balance', function (Account $account = null) {
if (is_null($account)) {
return 'NULL';
}
return App::make('steam')->balance($account);
}
);
// should be a function but OK
$filters[] = new Twig_SimpleFilter(
'getAccountRole', function ($name) {
return Config::get('firefly.accountRoles.' . $name);
}
);
return $filters;
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'getCurrencyCode', function () {
return App::make('amount')->getCurrencyCode();
}
);
$functions[] = new Twig_SimpleFunction(
'getCurrencySymbol', function () {
return App::make('amount')->getCurrencySymbol();
}
);
$functions[] = new Twig_SimpleFunction(
'phpdate', function ($str) {
return date($str);
}
);
$functions[] = new Twig_SimpleFunction(
'env', function ($name, $default) {
return env($name, $default);
}
);
$functions[] = new Twig_SimpleFunction(
'activeRoute', function ($context) {
$args = func_get_args();
$route = $args[1];
$what = isset($args[2]) ? $args[2] : false;
$strict = isset($args[3]) ? $args[3] : false;
$activeWhat = isset($context['what']) ? $context['what'] : false;
// activeRoute
if (!($what === false)) {
if ($what == $activeWhat && Route::getCurrentRoute()->getName() == $route) {
return 'active because-active-what';
}
} else {
if (!$strict && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
return 'active because-route-matches-non-strict';
} else {
if ($strict && Route::getCurrentRoute()->getName() == $route) {
return 'active because-route-matches-strict';
}
}
}
return 'not-xxx-at-all';
}, ['needs_context' => true]
);
return $functions;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'FireflyIII\Support\Twig\General';
}
}

View File

@ -0,0 +1,78 @@
<?php
namespace FireflyIII\Support\Twig;
use FireflyIII\Models\TransactionJournal;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Class Journal
*
* @package FireflyIII\Support\Twig
*/
class Journal extends Twig_Extension
{
public function getFilters()
{
$filters = [];
$filters[] = new Twig_SimpleFilter(
'typeIcon', function (TransactionJournal $journal) {
$type = $journal->transactionType->type;
if ($type == 'Withdrawal') {
return '<span class="glyphicon glyphicon-arrow-left" title="Withdrawal"></span>';
}
if ($type == 'Deposit') {
return '<span class="glyphicon glyphicon-arrow-right" title="Deposit"></span>';
}
if ($type == 'Transfer') {
return '<i class="fa fa-fw fa-exchange" title="Transfer"></i>';
}
if ($type == 'Opening balance') {
return '<span class="glyphicon glyphicon-ban-circle" title="Opening balance"></span>';
}
}, ['is_safe' => ['html']]
);
return $filters;
}
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'invalidJournal', function (TransactionJournal $journal) {
if (!isset($journal->transactions[1]) || !isset($journal->transactions[0])) {
return true;
}
return false;
}
);
$functions[] = new Twig_SimpleFunction(
'relevantTags', function (TransactionJournal $journal) {
return 'TODO'.$journal->amount;
}
);
return $functions;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'FireflyIII\Support\Twig\Journals';
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace FireflyIII\Support\Twig;
use Twig_Extension;
use Twig_SimpleFunction;
use FireflyIII\Models\PiggyBank as PB;
/**
* Class PiggyBank
*
* @package FireflyIII\Support\Twig
*/
class PiggyBank extends Twig_Extension
{
/**
*
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'currentRelevantRepAmount', function (PB $piggyBank) {
return $piggyBank->currentRelevantRep()->currentamount;
}
);
return $functions;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'FireflyIII\Support\Twig\PiggyBank';
}
}

View File

@ -13,6 +13,7 @@ use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Validation\Validator;
use Log;
use Navigation;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Class FireflyValidator
@ -22,6 +23,18 @@ use Navigation;
class FireflyValidator extends Validator
{
/**
* @param TranslatorInterface $translator
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
*/
public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
{
parent::__construct($translator, $data, $rules, $messages);
}
/**
* @param $attribute
* @param $value

View File

@ -11,6 +11,7 @@
|
*/
$app = new Illuminate\Foundation\Application(
realpath(__DIR__ . '/../')
);
@ -26,6 +27,8 @@ $app = new Illuminate\Foundation\Application(
|
*/
$app->singleton(
'Illuminate\Contracts\Http\Kernel',
'FireflyIII\Http\Kernel'
@ -41,6 +44,9 @@ $app->singleton(
'FireflyIII\Exceptions\Handler'
);
/*
|--------------------------------------------------------------------------
| Return The Application

View File

@ -26,7 +26,9 @@
"watson/validating": "~1.0",
"doctrine/dbal": "~2.5",
"illuminate/html": "~5.0",
"league/commonmark": "0.7.*"
"league/commonmark": "0.7.*",
"rcrowe/twigbridge": "0.7.x@dev",
"twig/extensions": "~1.2"
},
"require-dev": {
"barryvdh/laravel-debugbar": "@stable",

176
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "0d43c4c85607c5cdc901cde2d18b75d5",
"hash": "e3e90dd365b74f4878cf3b5b4a1c4007",
"packages": [
{
"name": "classpreloader/classpreloader",
@ -1527,6 +1527,70 @@
],
"time": "2015-03-26 18:43:54"
},
{
"name": "rcrowe/twigbridge",
"version": "0.7.x-dev",
"source": {
"type": "git",
"url": "https://github.com/rcrowe/TwigBridge.git",
"reference": "ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026",
"reference": "ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026",
"shasum": ""
},
"require": {
"illuminate/support": "5.0.*",
"illuminate/view": "5.0.*",
"php": ">=5.4.0",
"twig/twig": "~1.15"
},
"require-dev": {
"laravel/framework": "5.0.*",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "~0.6",
"squizlabs/php_codesniffer": "~1.5"
},
"suggest": {
"laravelcollective/html": "For bringing back html/form in Laravel 5.x",
"twig/extensions": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.7-dev"
}
},
"autoload": {
"psr-4": {
"TwigBridge\\": "src",
"TwigBridge\\Tests\\": "tests"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
},
{
"name": "Rob Crowe",
"email": "hello@vivalacrowe.com"
}
],
"description": "Adds the power of Twig to Laravel",
"keywords": [
"laravel",
"twig"
],
"time": "2015-04-22 09:19:03"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.0",
@ -2291,6 +2355,115 @@
],
"time": "2015-03-31 08:12:29"
},
{
"name": "twig/extensions",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig-extensions.git",
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
"shasum": ""
},
"require": {
"twig/twig": "~1.12"
},
"require-dev": {
"symfony/translation": "~2.3"
},
"suggest": {
"symfony/translation": "Allow the time_diff output to be translated"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Twig_Extensions_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Common additional features for Twig that do not directly belong in core",
"homepage": "http://twig.sensiolabs.org/doc/extensions/index.html",
"keywords": [
"i18n",
"text"
],
"time": "2014-10-30 14:30:03"
},
{
"name": "twig/twig",
"version": "v1.18.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.18-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2015-04-19 08:30:27"
},
{
"name": "vlucas/phpdotenv",
"version": "v1.1.0",
@ -4179,6 +4352,7 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"rcrowe/twigbridge": 20,
"barryvdh/laravel-debugbar": 0
},
"prefer-stable": false,

View File

@ -136,11 +136,12 @@ return [
'Illuminate\Validation\ValidationServiceProvider',
'Illuminate\View\ViewServiceProvider',
'Illuminate\Html\HtmlServiceProvider',
'TwigBridge\ServiceProvider',
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
'Barryvdh\Debugbar\ServiceProvider',
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
/*
* Application Service Providers...
*/
@ -152,6 +153,7 @@ return [
'FireflyIII\Providers\FireflyServiceProvider',
'FireflyIII\Providers\TestingServiceProvider',
],
/*
@ -202,12 +204,13 @@ return [
'Form' => 'Illuminate\Html\FormFacade',
'Html' => 'Illuminate\Html\HtmlFacade',
'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
'Preferences' => 'FireflyIII\Support\Facades\Preferences',
'Navigation' => 'FireflyIII\Support\Facades\Navigation',
'Amount' => 'FireflyIII\Support\Facades\Amount',
'Steam' => 'FireflyIII\Support\Facades\Steam',
'ExpandedForm' => 'FireflyIII\Support\Facades\ExpandedForm',
'Twig' => 'TwigBridge\Facade\Twig',
],

View File

@ -14,7 +14,7 @@ return [
*/
'paths' => [
realpath(base_path('resources/views'))
realpath(base_path('resources/twig'))
],
/*

View File

@ -7,7 +7,7 @@
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
stopOnFailure="true"
syntaxCheck="false">
<testsuites>
<testsuite name="Application Test Suite">
@ -24,6 +24,7 @@
<logging>
<log type="coverage-clover" target="./storage/coverage/clover.xml" charset="UTF-8" />
</logging>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>

View File

@ -29,8 +29,8 @@ $(function() {
var url = window.location;
var element = $('ul.nav a').filter(function() {
return this.href == url || url.href.indexOf(this.href) == 0;
}).addClass('active').parent().parent().addClass('in').parent();
}).parent().parent().addClass('in').parent();/*addClass('active')*/
if (element.is('li')) {
element.addClass('active');
//element.addClass('active');
}
});

View File

@ -0,0 +1,61 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, what) }}
<form action="{{ route('accounts.store') }}" method="post" id="store" class="form-horizontal">
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<input type="hidden" name="what" value="{{ what }}" />
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{ subTitleIcon }}"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
{% if what == 'asset' %}
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{{ ExpandedForm.balance('openingBalance') }}
{{ ExpandedForm.date('openingBalanceDate', phpdate('Y-m-d')) }}
{{ ExpandedForm.select('accountRole', Config.get('firefly.accountRoles'),null,{'helpText' : 'Any extra options resulting from your choice can be set later.'}) }}
{{ ExpandedForm.balance('virtualBalance') }}
</div>
</div>
{% endif %}
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','account') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new {{ what }} account
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,36 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute().getName(), account) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('accounts.destroy',account.id)}) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete account "{{ account.name }}"
</div>
<div class="panel-body">
<p>
Are you sure that you want to delete the {{account.accountType.type|lower}} "{{account.name}}"?
</p>
{% if account.transactions|length > 0 %}
<p class="text-danger">
{{account.accountType.type|capitalize}} "{{ account.name }}" still has {{ account.transactions|length }} transaction(s) associated to it. These will be deleted as well.
</p>
{% endif %}
{% if account.piggyBanks|length > 0 %}
<p class="text-danger">
{{account.accountType.type|capitalize}} "{{ account.name }}" still has {{ account.piggyBanks|length }} piggy bank(s) associated to it. These will be deleted as well.
</p>
{% endif %}
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{URL.previous()}}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,71 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute().getName(), account) }}
{{ Form.model(account, {'class' : 'form-horizontal','id' : 'update','url' : route('accounts.update',account.id) } ) }}
<input type="hidden" name="id" value="{{account.id}}" />
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{ subTitleIcon }}"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{% if account.accounttype.type == 'Default account' or account.accounttype.type == 'Asset account' %}
{{ ExpandedForm.balance('openingBalance',null, {'currency' : openingBalance ? openingBalance.transactionCurrency : null}) }}
{{ ExpandedForm.date('openingBalanceDate') }}
{{ ExpandedForm.select('accountRole',Config.get('firefly.accountRoles')) }}
{{ ExpandedForm.balance('virtualBalance',null) }}
{% endif %}
{{ ExpandedForm.checkbox('active','1') }}
</div>
</div>
<!-- panel for credit card options -->
{% if Session.get('preFilled').accountRole == 'ccAsset' %}
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-credit-card"></i> Credit card options
</div>
<div class="panel-body">
{{ ExpandedForm.select('ccType',Config.get('firefly.ccTypes')) }}
{{ ExpandedForm.date('ccMonthlyPaymentDate',null,{'helpText' : 'Select any year and any month, it will be ignored anway. Only the day of the month is relevant.'}) }}
</div>
</div>
{% endif %}
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('update','account') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
Update account
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,46 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, what) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa {{ subTitleIcon }}"></i> {{ subTitle}}
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{route('accounts.create', what)}}"><i class="fa fa-plus fa-fw"></i> New {{ what }} account</a></li>
</ul>
</div>
</div>
</div>
{% include 'list/accounts.twig' %}
</div>
</div>
</div>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="css/bootstrap-sortable.css" type="text/css" media="all" />
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var what = '{{ what }}';
</script>
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/bootstrap-sortable.js"></script>
<script type="text/javascript" src="js/accounts.js"></script>
{% endblock %}

View File

@ -0,0 +1,60 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, account) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw {{ subTitleIcon }} fa-fw"></i> {{ account.name }}
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{route('accounts.edit', account.id)}}"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
<li><a href="{{route('accounts.delete', account.id)}}"><i class="fa fa-trash fa-fw"></i> Delete</a></li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
<div id="overview-chart"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-repeat fa-fw"></i> Transactions
</div>
<div class="panel-body">
{% include 'list/journals.twig' with {sorting:true} %}
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var accountID = {{ account.id }};
</script>
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script src="js/jquery-ui.min.js" type="text/javascript"></script>
<script src="js/accounts.js" type="text/javascript"></script>
{% endblock %}

View File

@ -0,0 +1,57 @@
{% extends "./layout/guest.twig" %}
{% block content %}
{% if errors.has('email') %}
<div class="row">
<div class="col-lg-12">
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<strong>Error!</strong> {{ errors.get('email')[0] }}
</div>
</div>
</div>
{% endif %}
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Firefly III &mdash; Sign In</h3>
</div>
<div class="panel-body">
<form role="form" method="POST" id="login" action="/auth/login">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label class="control-label">E-Mail</label>
<input type="email" class="form-control" id="inputEmail" name="email" placeholder="E-Mail">
</div>
<div class="form-group">
<label class="control-label">Password</label>
<input type="password" class="form-control" id="inputPassword" name="password" placeholder="Password">
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="remember" value="1"> Remember me
</label>
</div>
<p>
<button type="submit" class="btn btn-lg btn-success btn-block">Login</button>
</p>
<div class="btn-group btn-group-justified btn-group-sm">
{% if Config.get('auth.allow_register') %}
<a href="{{ route('register') }}" class="btn btn-default">Register</a>
{% endif %}
<a href="/password/email" class="btn btn-default">Forgot your password?</a>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% extends "./layout/guest.twig" %}
{% block content %}
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Firefly III &mdash; Reset Password</h3>
</div>
<div class="panel-body">
{% if session.status %}
<div class="alert alert-success">
{{ session.status }}
</div>
{% endif %}
{% if errors|length > 0 %}
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
{% for error in errors.all %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form role="form" method="POST" action="/password/email">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label class="control-label">E-Mail</label>
<input type="email" class="form-control" placeholder="E-Mail" name="email" value="{{ old.email }}">
</div>
<p>
<button type="submit" class="btn btn-lg btn-success btn-block">Send Password Reset</button>
</p>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,58 @@
{% extends "./layout/guest.twig" %}
{% block content %}
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="login-panel panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Firefly III &mdash; Register</h3>
</div>
<div class="panel-body">
<p>
Registering an account on Firefly requires an e-mail address.
</p>
{% if errors|length > 0 %}
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
{% for error in errors.all %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
<form role="form" id="register" method="POST" action="/auth/register">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label class="control-label">E-Mail</label>
<input type="email" class="form-control" placeholder="E-Mail" name="email" value="{{ old.email }}">
</div>
<div class="form-group">
<label class="control-label">Password</label>
<input type="password" placeholder="Password" class="form-control" name="password">
</div>
<div class="form-group">
<label class="control-label">Confirm Password</label>
<input type="password" placeholder="Confirm Password" class="form-control" name="password_confirmation">
</div>
<p>
<button type="submit" class="btn btn-lg btn-success btn-block">Register</button>
</p>
<div class="btn-group btn-group-justified btn-group-sm">
<a href="/auth/login" class="btn btn-default">Login</a>
<a href="/password/email" class="btn btn-default">Forgot your password?</a>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,69 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, piggyBank) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'store','url' : route('bills.store')}) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<!-- panel for mandatory fields -->
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-exclamation-circle"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
{{ ExpandedForm.tags('match') }}
{{ ExpandedForm.amount('amount_min') }}
{{ ExpandedForm.amount('amount_max') }}
{{ ExpandedForm.date('date',phpdate('Y-m-d')) }}
{{ ExpandedForm.select('repeat_freq',periods,'monthly') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-12 col-sm-6">
<!-- panel for optional fields -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{{ ExpandedForm.integer('skip',0) }}
{{ ExpandedForm.checkbox('automatch',1,true) }}
{{ ExpandedForm.checkbox('active',1,true) }}
</div>
</div>
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','bill') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new bill
</button>
</p>
</div>
</div>
</form>
{% endblock %}
{% block styles %}
<link href="css/bootstrap-tagsinput.css" type="text/css" rel="stylesheet" media="all">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="js/bootstrap-tagsinput.min.js"></script>
{% endblock %}

View File

@ -0,0 +1,32 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, bill) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('bills.destroy',bill.id)}) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete bill "{{ bill.name }}"
</div>
<div class="panel-body">
<p>
Are you sure that you want to delete bill "{{ bill.name }}"?
</p>
{% if bill.transactionjournals|length > 0 %}
<p class="text-info">
Bill "{{ bill.name }}" still has {{ bill.transactionjournals|length }} transactions connected
to it. These will <strong>not</strong> be removed but will lose their connection to this bill.
</p>
{% endif %}
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{ URL.previous() }}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,66 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, bill) }}
{{ Form.model(bill, {'class' : 'form-horizontal','id' : 'update','url' : route('bills.update', bill.id)}) }}
<input type="hidden" name="id" value="{{bill.id}}" />
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-exclamation-circle"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
{{ ExpandedForm.tags('match') }}
{{ ExpandedForm.amount('amount_min') }}
{{ ExpandedForm.amount('amount_max') }}
{{ ExpandedForm.date('date',bill.date.format('Y-m-d')) }}
{{ ExpandedForm.select('repeat_freq',periods) }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-12 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{{ ExpandedForm.integer('skip') }}
{{ ExpandedForm.checkbox('automatch',1) }}
{{ ExpandedForm.checkbox('active',1) }}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('update','bill') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Update bill
</button>
</p>
</div>
</div>
</form>
{% endblock %}
{% block styles %}
<link href="css/bootstrap-tagsinput.css" type="text/css" rel="stylesheet" media="all">
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="js/bootstrap-tagsinput.min.js"></script>
{% endblock %}

View File

@ -0,0 +1,27 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, piggyBank) }}
<div class="row">
<div class="col-lg-12 col-sm-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa {{ mainTitleIcon }}"></i> {{ title }}
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{route('bills.create')}}"><i class="fa fa-plus fa-fw"></i> New bill</a></li>
</ul>
</div>
</div>
</div>
{% include 'list/bills.twig' %}
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,113 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, bill) }}
<div class="row">
<div class="col-lg-6 col-sm-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-rotate-right"></i> {{ bill.name }}
{% if bill.active %}
<i class="fa fa-check fa-fw" title="Active"></i>
{% else %}
<i class="fa fa-times fa-fw" title="Inactive"></i>
{% endif %}
{% if bill.automatch %}
<i class="fa fa-check fa-fw" title="Automatically matched by Firefly"></i>
{% else %}
<i class="fa fa-times fa-fw" title="Not automatically matched by Firefly"></i>
{% endif %}
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{route('bills.edit',bill.id)}}"><i class="fa fa-fw fa-pencil"></i> edit</a></li>
<li><a href="{{route('bills.delete',bill.id)}}"><i class="fa fa-fw fa-trash-o"></i> delete</a></li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
<table class="table">
<tr>
<td colspan="2">
Matching on
{% for word in bill.match|split(',') %}
<span class="label label-info">{{ word }}</span>
{% endfor %}
between {{ bill.amount_min|formatAmount }} and {{ bill.amount_max|formatAmount }}.
Repeats {{ bill.repeat_freq }}.</td>
</tr>
<tr>
<td>Next expected match</td>
<td>
{% if bill.nextExpectedMatch %}
{{bill.nextExpectedMatch.format('j F Y')}}
{% else %}
<em>Unknown</em>
{% endif %}
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="col-lg-6 col-sm-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
More
</div>
<div class="panel-body">
<p>
<a href="{{route('bills.rescan',bill.id)}}" class="btn btn-default">Rescan old transactions</a>
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-sm-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
Chart
</div>
<div class="panel-body">
<div id="bill-overview"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-sm-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
Connected transaction journals
</div>
<div class="panel-body">
{% include 'list/journals' %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var billID = {{ bill.id }};
</script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/bills.js"></script>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'store','url' : route('budgets.store')}) }}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-exclamation"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','budget') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new budget
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,43 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, budget) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('budgets.destroy',budget.id) }) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete budget "{{ budget.name}}"
</div>
<div class="panel-body">
<p>
Are you sure that you want to delete budget "{{ budget.name }}"?
</p>
{% if budget.transactionjournals|length > 0 %}
<p class="text-info">
Budget "{{ budget.name }}" still has {{ budget.transactionjournals|length }} transactions connected
to it. These will <strong>not</strong> be removed but will lose their connection to this budget.
</p>
{% endif %}
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{URL.previous()}}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<div class="col-sm-8">
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,49 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, budget) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<p class="lead">Use budgets to organize and limit your expenses.</p>
</div>
</div>
{{ Form.model(budget, {'class' : 'form-horizontal','id' : 'update','url' : route('budgets.update',budget.id) } ) }}
<input type="hidden" name="id" value="{{budget.id}}" />
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-fw fa-exclamation"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.checkbox('active') }}
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-12 col-sm-6">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('update','budget') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-pencil"></i> Update budget
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,22 @@
<form style="display: inline;" id="income" action="{{route('budgets.postIncome')}}" method="POST">
<input type="hidden" name="_token" value="{{ csrf_token() }}"
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Update (expected) available amount for {{Session.get('start').format('F Y')}}</h4>
</div>
<div class="modal-body">
<div class="input-group">
<div class="input-group-addon">{{ getCurrencySymbol() }}</div>
<input step="any" class="form-control" id="amount" value="{{ amount.data }}" autocomplete="off" name="amount" type="number">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update</button>
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,192 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-9 col-sm-8 col-md-8">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar fa-fw"></i>
{{ Session.get('start').format('F Y') }}
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-6 col-md-4 col-sm-3">
<small>Budgeted: <span id="budgetedAmount" data-value="300"></span></small>
</div>
<div class="col-lg-6 col-md-4 col-sm-3" style="text-align:right;">
<small>Available in {{ Session.get('start').format('F Y') }}:
<a href="#" class="updateIncome"><span id="totalAmount" data-value="{{ amount }}">{{ amount|formatAmount }}</span></a></small>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="progress progress-striped">
<div class="progress-bar progress-bar-info" id="progress-bar-default" role="progressbar" aria-valuenow="0" aria-valuemin="0"
aria-valuemax="100" style="width: 0;"></div>
<div class="progress-bar progress-bar-danger" id="progress-bar-danger" role="progressbar" aria-valuenow="0" aria-valuemin="0"
aria-valuemax="100" style="width: 0;"></div>
<div class="progress-bar progress-bar-warning" id="progress-bar-warning" role="progressbar" aria-valuenow="10" aria-valuemin="0"
aria-valuemax="100" style="width: 0;"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-4 col-sm-3">
<small>Spent: {{ spent|formatAmount }}</small>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="progress progress-striped">
{% if overspent %}
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="{{ spentPCT }}" aria-valuemin="0"
aria-valuemax="100" style="width: {{ spentPCT }}%;"></div>
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="{{ 100-spentPCT }}" aria-valuemin="0"
aria-valuemax="100" style="width: {{ 100-spentPCT }}%;"></div>
{% else %}
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="{{ spentPCT }}" aria-valuemin="0"
aria-valuemax="100" style="width: {{ spentPCT }}%;"></div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-3 col-sm-4 col-md-4">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-tags"></i>
Transactions without a budget
</div>
<div class="panel-body">
<p>
<a href="{{ route('budgets.noBudget') }}">Transactions without a budget in
{{ Session.get('start').format('F Y') }}.</a>
</p>
</div>
</div>
</div>
</div>
<div class="row">
{% for budget in budgets %}
<div class="col-lg-3 col-sm-4 col-md-6" style="height:180px;">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-tasks"></i>
{% if budget.currentRep %}
<a href="{{ route('budgets.show', [budget.id, budget.currentRep.id]) }}" id="budget-link-{{ budget.id }}">{{ budget.name }}</a>
{% else %}
<a href="{{ route('budgets.show',budget.id) }}" id="budget-link-{{ budget.id }}">{{ budget.name }}</a>
{% endif %}
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{ route('budgets.edit',budget.id) }}"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
<li><a href="{{ route('budgets.delete',budget.id) }}"><i class="fa fa-trash fa-fw"></i> Delete</a></li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
<!-- the range in which the budget can be set -->
<p>
{% if budget.currentRep %}
<input type="range" data-id="{{ budget.id }}" data-spent="{{ budget.spent }}" id="budget-range-{{ budget.id }}"
max="{{ budgetMaximum }}" min="0" value="{{ budget.currentRep.amount }}"/>
{% else %}
<input type="range" data-id="{{ budget.id }}" data-spent="{{ budget.spent }}" id="budget-range-{{ budget.id }}"
max="{{ budgetMaximum }}" min="0" value="0"/>
{% endif %}
</p>
<!-- some textual info about the budget. Updates dynamically. -->
<p>
<!-- budget-holder-X holds all the elements -->
<span id="budget-holder-{{ budget.id }}">
{% if budget.currentRep %}
<!-- budget-description-X holds the description. -->
<span id="budget-description-{{ budget.id }}">Budgeted: </span>
<!-- budget-info-X holds the input and the euro-sign: -->
<span id="budget-info-{{ budget.id }}">
{% if budget.currentRep.amount > budget.spent %}
<span class="text-success">{{ getCurrencySymbol() }}</span> <input type="number" min="0" max="{{ budgetMaximum }}" data-id="{{ budget.id }}"
step="1" value="{{ budget.currentRep.amount }}"
style="width:90px;color:#3c763d;"/>
{% else %}
<span class="text-danger">{{ getCurrencySymbol() }}</span> <input type="number" min="0" max="{{ budgetMaximum }}" data-id="{{ budget.id }}"
step="1" value="{{ budget.currentRep.amount }}"
style="width:90px;color:#a94442;"/>
{% endif %}
</span>
{% else %}
<span id="budget-description-{{ budget.id }}"><em>No budget</em></span>
<span id="budget-info-{{ budget.id }}">
<span class="text-success" style="display:none;">{{ Amount.getCurrencySymbol() }}</span> <input data-id="{{ budget.id }}" type="number"
min="0" max="{{ budgetMaximum }}" step="1"
value="0"
style="width:50px;color:#3c763d;display:none;"/>
</span>
{% endif %}
</span>
</p>
<p>
<span id="spent-{{ budget.id }}" data-value="{{ budget.spent }}">Spent: {{ budget.spent|formatAmount }}</span>
</p>
</div>
</div>
</div>
{% endfor %}
<div class="col-lg-3 col-sm-4 col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-plus-circle"></i>
Create budget
</div>
<div class="panel-body">
<a href="{{ route('budgets.create') }}" class="btn btn-success"><i class="fa fa-fw fa-plus"></i> Create new budget</a>
</div>
</div>
</div>
{% if inactive|length > 0 %}
<div class="col-lg-3 col-sm-4 col-md-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-minus-circle"></i>
Inactive budgets
</div>
<div class="panel-body">
{% for index,budget in inactive %}
{% if index != inactive|length-1 %}
<a href="{{ route('budgets.show',budget.id) }}">{{ budget.name }}</a>,
{% else %}
<a href="{{ route('budgets.show',budget.id) }}">{{ budget.name }}</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
<!-- DIALOG -->
<div class="modal fade" id="monthlyBudgetModal">
</div><!-- /.modal -->
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="js/budgets.js"></script>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, subTitle) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
{{ subTitle }}
</div>
<div class="panel-body">
{% include 'list/journals.twig' with {'journals': list} %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,107 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName,budget, repetition) }}
<div class="row">
<div class="col-lg-9 col-md-9 col-sm-7">
<div class="panel panel-default">
<div class="panel-heading">
Overview
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{ route('budgets.edit',budget.id) }}"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
<li><a href="{{ route('budgets.delete',budget.id) }}"><i class="fa fa-trash fa-fw"></i> Delete</a></li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
<div id="budgetOverview"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
Transactions
</div>
{% include 'list/journals.twig' %}
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-5">
{% if limits|length == 1 %}
<p class="small text-center"><a href="{{ route('budgets.show',budget.id) }}">Show everything</a></p>
{% endif %}
{% for limit in limits %}
{% for rep in limit.limitRepetitions %}
<div class="panel panel-default">
<div class="panel-heading">
<a href="{{route('budgets.show',[budget.id,rep.id])}}">{{rep.startdate.format('F Y')}}</a>
</div>
<div class="panel-body">
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6">
Amount: {{ rep.amount|formatAmount }}
</div>
<div class="col-lg-6 col-md-6 col-sm-6">
Spent: {{ spentInRepetition(rep)|formatAmount }}
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
{% set overspent = spentInRepetition(rep) > rep.amount %}
{% if overspent %}
{% set spent = spentInRepetition(rep) %}
{% set pct = (spent != 0 ? (rep.amount / spent)*100 : 0) %}
<div class="progress progress-striped">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="{{pct|round}}" aria-valuemin="0" aria-valuemax="100" style="width: {{pct|round}}%;"></div>
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="{{(100-pct)|round}}" aria-valuemin="0" aria-valuemax="100" style="width: {{(100-pct)|round}}%;"></div>
</div>
{% else %}
{% set amount = rep.amount %}
{% set pct = (amount != 0 ? (spentInRepetition(rep) / amount)*100 : 0) %}
<div class="progress progress-striped">
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="{{pct|round}}" aria-valuemin="0" aria-valuemax="100" style="width: {{pct|round}}%;"></div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
{% endfor %}
{% if limits|length == 1 %}
<p class="small text-center"><a href="{{route('budgets.show',budget.id)}}">Show everything</a></p>
{% endif %}
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var budgetID = {{budget.id}};
{% if repetition.id %}
var repetitionID = {{repetition.id}};
var year = {{repetition.startdate.format('Y')}};
{% else %}
var year = {{Session.get('start').format('Y')}};
{% endif %}
</script>
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/budgets.js"></script>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'store','url' : route('categories.store')}) }}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-exclamation"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','category') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new category
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,33 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, category) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('categories.destroy',category.id)}) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete category "{{ category.name }}"
</div>
<div class="panel-body">
<p>
Are you sure that you want to delete category "{{ category.name }}"?
</p>
{% if category.transactionjournals|length > 0 %}
<p class="text-info">
Category "{{ category.name }}" still has {{ category.transactionjournals|length }} transactions connected
to it. These will <strong>not</strong> be removed but will lose their connection to this category.
</p>
{% endif %}
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{ URL.previous() }}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,44 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, category) }}
{{ Form.model(category, {'class' : 'form-horizontal','id' : 'update','url' : route('categories.update',category.id)}) }}
<input type="hidden" name="id" value="{{ category.id }}" />
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-exclamation"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('update','category') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
Update category
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,40 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa {{ mainTitleIcon }}"></i> Categories
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{ route('categories.create') }}"><i class="fa fa-plus fa-fw"></i> New category</a></li>
</ul>
</div>
</div>
</div>
{% include 'list/categories.twig' %}
</div>
</div>
</div>
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="css/bootstrap-sortable.css" type="text/css" media="all" />
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/bootstrap-sortable.js"></script>
<script type="text/javascript" src="js/categories.js"></script>
{% endblock %}

View File

@ -0,0 +1,18 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, subTitle) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
{{ subTitle }}
</div>
<div class="panel-body">
{% include 'list/journals.twig' with {'journals': list} %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,54 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, category) }}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar fa-fw"></i>
Overview
</div>
<div class="panel-body">
<div id="periodOverview"></div>
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar-o fa-fw"></i>
Overview
</div>
<div class="panel-body">
<div id="componentOverview"></div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-repeat fa-fw"></i>
Transactions
</div>
<div class="panel-body">
{% include 'list/journals' %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var categoryID = {{ category.id }};
</script>
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/categories.js"></script>
{% endblock %}

View File

@ -0,0 +1,44 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'store','route' : 'currency.store'}) }}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{ subTitleIcon }}"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name',null,{'maxlength' : 48}) }}
{{ ExpandedForm.text('symbol',null,{'maxlength': 8}) }}
{{ ExpandedForm.text('code',null,{'maxlength' : 3}) }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','currency') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new currency
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, currency) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('currency.destroy',currency.id)}) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete currency "{{ currency.name }}"
</div>
<div class="panel-body">
<p>
Are you sure that you want to delete currency "{{ currency.name }}"?
</p>
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{ URL.previous }}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, currency) }}
{{ Form.model(currency, {'class' : 'form-horizontal','id' : 'update','url' : route('currency.update',currency.id)}) }}
<input type="hidden" name="id" value="{{currency.id}}" />
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{ subTitleIcon }}"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name',null,{'maxlength' : 48}) }}
{{ ExpandedForm.text('symbol',null,{'maxlength' : 8}) }}
{{ ExpandedForm.text('code',null,{'maxlength' : 3}) }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('update','currency') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Update currency
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,49 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-12 col-sm-12 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
Currencies
</div>
<div class="panel-body">
<p class="text-info">
Firefly III supports various currencies which you can set and enable here.
</p>
<ul>
{% if currencies|length > 0 %}
<table class="table table-striped table-bordered">
<tr>
<th>&nbsp;</th>
<th colspan="2">Currency</th>
</tr>
{% for currency in currencies %}
<tr>
<td>
<div class="btn-group btn-group-xs">
<a class="btn btn-default" href="{{route('currency.edit',currency.id)}}"><i class="fa fa-fw fa-pencil"></i></a>
<a class="btn btn-default" href="{{route('currency.delete',currency.id)}}"><i class="fa fa-fw fa-trash"></i></a>
</div>
</td>
<td>{{ currency.name }} ({{ currency.code }}) ({{ currency.symbol|raw }})</td>
<td>
{% if currency.id == defaultCurrency.id %}
<span class="label label-success">default</span>
{% else %}
<a class="btn btn-info btn-xs" href="{{route('currency.default',currency.id)}}">make default</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% endif %}
<p><a class="btn btn-success" href="{{route('currency.create')}}"><i class="fa fa-fw fa-plus-circle"></i> Add another currency</a></p>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1 @@
Click here to reset your password: {{ url('password/reset/' . token) }}

View File

@ -0,0 +1,5 @@
Hey there!
Welkome to Firefly III. Your registration has made it, and this email is here to confirm it.
Thanks for using Firefly!

18
resources/twig/error.twig Normal file
View File

@ -0,0 +1,18 @@
{% extends "./layout/guest.twig" %}
{% block content %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<h1 class="text-danger">Firefly<br/>
<small>Error</small>
</h1>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
{{ message |default('General unknown errror') }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,41 @@
<html>
<head>
<link href='https://fonts.googleapis.com/css?family=Lato:100' rel='stylesheet' type='text/css'>
<style>
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
color: #B0BEC5;
display: table;
font-weight: 100;
font-family: 'Lato';
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 72px;
margin-bottom: 40px;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
<div class="title">Be right back.</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,23 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle amountCurrencyDropdown" data-toggle="dropdown" aria-expanded="false">
<span id="amountCurrentSymbol">{{ defaultCurrency.symbol|raw }}</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
{% for currency in currencies %}
<li><a href="#" class="currencySelect" data-id="{{ currency.id }}" data-field="amount" data-currency="{{ currency.code }}" data-symbol="{{ currency.symbol|raw }}">{{ currency.name }}</a></li>
{% endfor %}
</ul>
</div>
{{ Form.input('number', name, value, options) }}
</div>
{% include 'form/feedback.twig' %}
</div>
<input type="hidden" name="amount_currency_id" value="{{ defaultCurrency.id }}" />
</div>

View File

@ -0,0 +1,22 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
<div class="input-group">
<div class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle balanceCurrencyDropdown" data-toggle="dropdown" aria-expanded="false">
<span id="balanceCurrentSymbol">{{ defaultCurrency.symbol|raw }}</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
{% for currency in currencies %}
<li><a href="#" class="currencySelect" data-id="{{ currency.id }}" data-field="balance" data-currency="{{ currency.code }}" data-symbol="{{ currency.symbol }}">{{ currency.name }}</a></li>
{% endfor %}
</ul>
</div>
{{ Form.input('number', name, value, options) }}
</div>
{% include 'form/feedback.twig' %}
</div>
<input type="hidden" name="balance_currency_id" value="{{ defaultCurrency.id }}" />
</div>

View File

@ -0,0 +1,11 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
{{ Form.checkbox(name, value, options.checked, options) }}
</label>
</div>
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,8 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
{{ Form.input('date', name, value, options) }}
{% include 'form/help.twig' %}
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,4 @@
{% if errors.has(name) %}
<span class="form-control-feedback"><i class="fa fa-fw fa-remove"></i></span>
<p class="text-danger">{{ errors.first(name) }}</p>
{% endif %}

View File

@ -0,0 +1,3 @@
{% if options.helpText %}
<p class="help-block">{{ options.helpText }}</p>
{% endif %}

View File

@ -0,0 +1,9 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
<div class="input-group">
{{ Form.input('number', name, value, options) }}
{% include 'form/feedback.twig' %}
</div>
</div>
</div>

View File

@ -0,0 +1,14 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
<div id="map-canvas" style="width:100%;height:300px;"></div>
<p class="help-block">Right-click to set the tag's location.
<a href="#" id="clearLocation">Clear location</a>
</p>
<input type="hidden" name="latitude" value="" />
<input type="hidden" name="longitude" value="" />
<input type="hidden" name="zoomLevel" value="6" />
<input type="hidden" name="setTag" value="" />
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,16 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
{% for value,description in list %}
<div class="radio">
<label>
{{ Form.radio(name, value, (selected == value), options) }}
{{ description }}
</label>
</div>
{% endfor %}
{% include 'form/help.twig' %}
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,30 @@
{% if type == 'create' %}
<div class="form-group">
<label for="{{ name }}_return_to_form" class="col-sm-4 control-label">
Return here
</label>
<div class="col-sm-8">
<div class="radio">
<label>
{{ Form.checkbox('create_another', '1') }}
After storing, return here to create another one.
</label>
</div>
</div>
</div>
{% endif %}
{% if type == 'update' %}
<div class="form-group">
<label for="{{ name }}_return_to_edit" class="col-sm-4 control-label">
Return here
</label>
<div class="col-sm-8">
<div class="radio"><label>
{{ Form.checkbox('return_to_edit', '1', Input.old('return_to_edit') == '1') }}
After updating, return here.
</label>
</div>
</div>
</div>
{% endif %}

View File

@ -0,0 +1,9 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
{{ Form.select(name, list, selected , options ) }}
{% include 'form/help.twig' %}
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,7 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
{{ Form.input('text', name, value, options) }}
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,7 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
{{ Form.input('text', name, value, options) }}
{% include 'form/feedback.twig' %}
</div>
</div>

View File

@ -0,0 +1,7 @@
<div class="{{ classes }}">
<label for="{{ options.id }}" class="col-sm-4 control-label">{{ label }}</label>
<div class="col-sm-8">
{{ Form.textarea(name, value, options) }}
{% include 'form/feedback.twig' %}
</div>
</div>

212
resources/twig/index.twig Normal file
View File

@ -0,0 +1,212 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists }}
{% if count == 0 %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<p class="lead">Welcome to Firefly III.</p>
<p>
Create a new asset account to get started.
</p>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<h2><a href="{{route('accounts.create','asset')}}">Start from scratch</a></h2>
</div>
{% else %}
<!-- fancy new boxes -->
{% include 'partials/boxes.twig' %}
<div class="row">
<div class="col-lg-8 col-md-12 col-sm-12">
<!-- ACCOUNTS -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-credit-card fa-fw"></i> <a href="#">Your accounts</a>
</div>
<div class="panel-body">
<div id="accounts-chart"></div>
</div>
</div>
<!-- BUDGETS -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-tasks fa-fw"></i> <a href="{{route('budgets.index')}}">Budgets and spending</a>
</div>
<div class="panel-body">
<div id="budgets-chart"></div>
</div>
</div>
<!-- CATEGORIES -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bar-chart fa-fw"></i> <a href="{{route('categories.index')}}">Categories</a>
</div>
<div class="panel-body">
<div id="categories-chart"></div>
</div>
</div>
<!-- SAVINGS -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-line-chart"></i> Savings
<span class="pull-right">{{ savingsTotal|formatAmount }}</span>
</div>
<div class="panel-body">
{% if savings|length == 0 %}
<p class="small"><em>Mark your asset accounts as "Savings account" to fill this panel.</em></p>
{% else %}
{% for account in savings %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h5><a href="{{ route('accounts.show') }}">{{ account.name }}</a></h5></div>
</div>
<div class="row">
<!-- start -->
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.startBalance|formatAmount }}</div>
<!-- bar -->
<div class="col-lg-8 col-md-8 col-sm-6 col-xs-4">
{% if account.difference < 0 %}
<!-- green (100-pct), then red (pct) -->
<div class="progress">
<div class="progress-bar progress-bar-success progress-bar-striped" style="width: {{ 100 - account.percentage }}%">
{% if account.percentage <= 50 %}
{{account.difference|formatAmount}}
{% endif %}
</div>
<div class="progress-bar progress-bar-danger progress-bar-striped" style="width: {{ account.percentage }}%">
{% if account.percentage > 50 %}
{{account.difference|formatAmount}}
{% endif %}
</div>
</div>
{% else %}
<!-- green (pct), then blue (100-pct) -->
<div class="progress">
<div class="progress-bar progress-bar-success progress-bar-striped" style="width: {{account.percentage}}%">
{% if account.percentage <= 50 %}
{{account.difference|formatAmount}}
{{account.difference|formatAmount}}
{% endif %}
</div>
<div class="progress-bar progress-bar-info progress-bar-striped" style="width: {{100 - account.percentage}}%">
{% if account.percentage > 50 %}
{{account.difference|formatAmount}}
{% endif %}
</div>
</div>
{% endif %}
</div>
<!-- end -->
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.endBalance|formatAmount }}</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
<!-- PIGGY BANKS -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-sort-amount-asc fa-fw"></i> Piggy banks
</div>
<div class="panel-body">
{% if piggyBankAccounts|length == 0%}
<p class="small"><em>Create piggy banks to fill this panel.</em></p>
{% else %}
{% for account in piggyBankAccounts %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"><h5><a href="{{route('accounts.show')}}">{{account.name}}</a></h5></div>
</div>
<div class="row">
<!-- start -->
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.startBalance|formatAmount }}</div>
<!-- bar -->
<div class="col-lg-8 col-md-8 col-sm-6 col-xs-4">
<div class="progress">
<div class="progress-bar progress-bar-info progress-bar-striped" style="width: {{100 - account.percentage}}%">
{% if account.percentage <= 50 %}
{{account.piggyBalance|formatAmount}} divided
{% endif %}
</div>
<div class="progress-bar progress-bar-success progress-bar-striped" style="width: {{account.percentage}}%">
{% if account.percentage > 50 %}
{{account.difference|formatAmount}} left to divide
{% endif %}
</div>
</div>
</div>
<!-- end -->
<div class="col-lg-2 col-md-2 col-sm-3 col-xs-4">{{ account.piggyBalance|formatAmount }}</div>
</div>
{% endfor %}
{% endif %}
</div>
</div>
</div>
<div class="col-lg-4 col-md-6 col-sm-12">
<!-- REMINDERS -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar-o"></i> <a href="{{route('bills.index')}}">Bills</a>
</div>
<div class="panel-body">
<div id="bills-chart"></div>
</div>
</div>
<!-- TRANSACTIONS -->
{% for data in transactions %}
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-money fa-fw"></i>
<a href="{{route('accounts.show',data[1].id)}}">{{data[1].name}}</a> ({{ data[1]|balance }})
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{route('transactions.create','withdrawal')}}?account_id={{data[1].id}}"><i class="fa fa-long-arrow-left fa-fw"></i> New withdrawal</a></li>
<li><a href="{{route('transactions.create','deposit')}}?account_id={{data[1].id}}"><i class="fa fa-long-arrow-right fa-fw"></i> New deposit</a></li>
<li><a href="{{route('transactions.create','transfer')}}?account_from_id={{data[1].id}}"><i class="fa fa-fw fa-exchange"></i> New transfer</a></li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
{% include 'list/journals-tiny.twig' with {'transactions': data[0],'account': data[1]} %}
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endblock %}
{% block scripts %}
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/index.js"></script>
{% endblock %}

View File

@ -0,0 +1,168 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="{{ route('index') }}/">
<title>Firefly
{% if title != "Firefly" %}
// {{ title }}
{% endif %}
{% if subTitle %}
// {{ subTitle }}
{% endif %}
</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,700,300italic" type="ext/css" media="all"/>
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap-theme.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="css/metisMenu.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="css/sb-admin-2.css" type="text/css" media="all"/>
<!-- date range -->
<link rel="stylesheet" href="css/daterangepicker-bs3.css" type="text/css" media="all"/>
<link rel="stylesheet" href="css/firefly.css" type="text/css" media="all"/>
{% block styles %}{% endblock %}
<!-- favicons -->
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png?v=Lb54KlrQnz">
<link rel="icon" type="image/png" href="/favicon-32x32.png?v=Lb54KlrQnz" sizes="32x32">
<link rel="icon" type="image/png" href="/android-chrome-192x192.png?v=Lb54KlrQnz" sizes="192x192">
<link rel="icon" type="image/png" href="/favicon-96x96.png?v=Lb54KlrQnz" sizes="96x96">
<link rel="icon" type="image/png" href="/favicon-16x16.png?v=Lb54KlrQnz" sizes="16x16">
<link rel="manifest" href="/manifest.json?v=Lb54KlrQnz">
<link rel="shortcut icon" href="/favicon.ico?v=Lb54KlrQnz">
<meta name="msapplication-TileColor" content="#2d89ef">
<meta name="msapplication-TileImage" content="/mstile-144x144.png?v=Lb54KlrQnz">
<meta name="theme-color" content="#ffffff">
</head>
<body>
<div id="wrapper">
{% include 'partials/menu.twig' %}
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">
{% if mainTitleIcon %}
<i class="fa {{ mainTitleIcon }}"></i>
{% endif %}
{{ title }}
{% if subTitle %}
<small>
{% if subTitleIcon %}
<i class="fa {{ subTitleIcon }}"></i>
{% endif %}
{{ subTitle }}
</small>
{% endif %}
<small class="pull-right"><a href="#" id="help" data-route="{{ Route.getCurrentRoute.getName }}"><i
data-route="{{ Route.getCurrentRoute.getName }}" class="fa fa-question-circle"></i></a></small>
</h1>
</div>
<!-- /.col-lg-12 -->
</div>
{% include('partials/flashes.twig') %}
{% block content %}{% endblock %}
<!-- this modal will contain the help-text -->
<div class="modal fade" id="helpModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="helpTitle">Please hold...</h4>
</div>
<div class="modal-body" id="helpBody">
<i class="fa fa-refresh fa-spin"></i>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- /.modal -->
</div>
</div>
<!-- modal to relate transactions to each other -->
<div class="modal fade" id="relationModal">
</div>
<!-- default modal -->
<div class="modal fade" id="defaultModal">
</div>
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/metisMenu.min.js"></script>
<script type="text/javascript" src="js/sb-admin-2.js"></script>
<script type="text/javascript" src="js/help.js"></script>
<!-- date range stuff -->
<script type="text/javascript" src="js/moment.min.js"></script>
<script type="text/javascript" src="js/daterangepicker.js"></script>
<script type="text/javascript">
var start = "{{Session.get('start').format('d-m-Y')}}";
var end = "{{Session.get('end').format('d-m-Y')}}";
var titleString = "{{Session.get('start').format('j M Y')}} - {{Session.get('end').format('j M Y')}}";
var dateRangeURL = "{{route('daterange')}}";
var token = "{{csrf_token()}}";
var firstDate = moment("{{Session.get('first').format('Y-m-d')}}");
var currentMonthName = "{{ currentMonthName }}";
var previousMonthName = "{{ previousMonthName }}";
var nextMonthName = "{{ nextMonthName }}";
var currencyCode = '{{getCurrencyCode() }}';
$('#daterange span').text(titleString);
</script>
<script type="text/javascript" src="js/firefly.js"></script>
{% block scripts %}{% endblock %}
<script>
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
ga('create', '{{ env('ANALYTICS_ID', 'XXX-XX-X') }}', 'auto');
ga('send', 'pageview');
// send an event if relevant:
{% if Session.has('gaEventCategory') and Session.has('gaEventAction') %}
ga('send', 'event', '{{Session.get('gaEventCategory')}}', '{{Session.get('gaEventAction')}}');
{% endif %}
</script>
</body>
</html>

View File

@ -0,0 +1,62 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="{{ route('index') }}/">
<title>Firefly III</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" type="text/css" media="all" />
<!-- <link rel="stylesheet" href="css/metisMenu.min.css" type="text/css" media="all" /> -->
<!-- new css for SB admin -->
<link rel="stylesheet" href="css/metisMenu.min.css" type="text/css" media="all" />
<link rel="stylesheet" href="css/sb-admin-2.css" type="text/css" media="all" />
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css" type="text/css" media="all" />
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- favicons -->
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png?v=Lb54KlrQnz">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png?v=Lb54KlrQnz">
<link rel="icon" type="image/png" href="/favicon-32x32.png?v=Lb54KlrQnz" sizes="32x32">
<link rel="icon" type="image/png" href="/android-chrome-192x192.png?v=Lb54KlrQnz" sizes="192x192">
<link rel="icon" type="image/png" href="/favicon-96x96.png?v=Lb54KlrQnz" sizes="96x96">
<link rel="icon" type="image/png" href="/favicon-16x16.png?v=Lb54KlrQnz" sizes="16x16">
<link rel="manifest" href="/manifest.json?v=Lb54KlrQnz">
<link rel="shortcut icon" href="/favicon.ico?v=Lb54KlrQnz">
<meta name="msapplication-TileColor" content="#2d89ef">
<meta name="msapplication-TileImage" content="/mstile-144x144.png?v=Lb54KlrQnz">
<meta name="theme-color" content="#ffffff">
</head>
<body>
<div class="container">
<!-- include "partials/flashes.twig" -->
{% block content %}{% endblock %}
</div>
<script type="text/javascript" src="js/jquery-2.1.3.min.js"></script>
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
<!-- new js for sb admin -->
<script type="text/javascript" src="js/metisMenu.min.js"></script>
<script type="text/javascript" src="js/sb-admin-2.js"></script>
</body>
</html>

View File

@ -0,0 +1,59 @@
<table class="table table-striped table-bordered sortable">
<thead>
<tr>
<th data-defaultsort="disabled">&nbsp;</th>
<th>Name</th>
{% if what == 'asset' %}
<th>Role</th>
{% endif %}
<th>Current balance</th>
<th>Active</th>
<th>Last activity</th>
<th>Balance difference between {{ Session.get('start').format('jS F Y') }} and {{ Session.get('end').format('jS F Y') }}</th>
</tr>
</thead>
<tbody>
{% for account in accounts %}
<tr>
<td>
<div class="btn-group btn-group-xs">
<a class="btn btn-default btn-xs" href="{{route('accounts.edit',account.id)}}"><i class="fa fa-fw fa-pencil"></i></a>
<a class="btn btn-danger btn-xs" href="{{route('accounts.delete',account.id)}}"><i class="fa fa-fw fa-trash-o"></i></a>
</div>
</td>
<td><a href="{{route('accounts.show',account.id)}}">{{ account.name }}</a></td>
{% if what == "asset" %}
<td>
{% for entry in account.accountmeta %}
{% if entry.name == 'accountRole' %}
{{ entry.data|getAccountRole }}
{% endif %}
{% endfor %}
</td>
{% endif %}
<td data-value="{{ account|balance }}">{{ account|balance|formatAmount }}</td>
<td data-value="{{account.active}}">
{% if account.active %}
<i class="fa fa-fw fa-check"></i>
{% else %}
<i class="fa fa-fw fa-ban"></i>
{% endif %}
</td>
{% if account.lastActivityDate %}
<td data-value="{{ account.lastActivityDate.format('U') }} ">
{{ account.lastActivityDate.format('j F Y') }}
</td>
{% else %}
<td data-value="0">
<em>Never</em>
</td>
{% endif %}
<td data-value="{{account.endBalance - account.startBalance}}">
{{ (account.endBalance - account.startBalance)|formatAmount }}
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,78 @@
<table class="table table-bordered table-striped">
<tr>
<th>&nbsp;</th>
<th>Name</th>
<th>Matches on</th>
<th colspan="2">Matching amount</th>
<th>Last seen match</th>
<th>Next expected match</th>
<th>Is active</th>
<th>Will be automatched</th>
<th>Repeats every</th>
<th>&nbsp;</th>
</tr>
{% for entry in bills %}
<tr>
<td>
<div class="btn-group btn-group-xs">
<a href="{{route('bills.edit',entry.id)}}" class="btn btn-default btn-xs"><i class="fa fa-fw fa-pencil"></i></a>
<a href="{{route('bills.delete',entry.id)}}" class="btn btn-danger btn-xs"><i class="fa fa-fw fa-trash-o"></i></a>
</div>
</td>
<td>
<a href="{{route('bills.show',entry.id)}}" title="{{ entry.name }}">{{ entry.name }}</a>
</td>
<td>
{% for match in entry.match|split(',') %}
<span class="label label-info">{{ match }}</span>
{% endfor %}
</td>
<td>
{{ entry.amount_min|formatAmount }}
</td>
<td>
{{ entry.amount_max|formatAmount }}
</td>
<td>
{% if entry.lastFoundMatch %}
{{entry.lastFoundMatch.format('j F Y')}}
{% else %}
<em>Unknown</em>
{% endif %}
</td>
<td>
{% if entry.nextExpectedMatch%}
{{entry.nextExpectedMatch.format('j F Y')}}
{% else %}
<em>Unknown</em>
{% endif %}
</td>
<td>
{% if entry.active %}
<i class="fa fa-fw fa-check"></i>
{% else %}
<i class="fa fa-fw fa-ban"></i>
{% endif %}
</td>
<td>
{% if entry.automatch %}
<i class="fa fa-fw fa-check"></i>
{% else %}
<i class="fa fa-fw fa-ban"></i>
{% endif %}
</td>
<td>
{{ entry.repeat_freq }}
{% if entry.skip > 0 %}
skips over {{entry.skip}}
{% endif %}
</td>
<td>
{% if entry.active %}
<a href="{{route('bills.add',entry.id)}}" class="btn btn-success btn-xs"><i class="fa fa-fw fa-plus-circle"></i></a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>

View File

@ -0,0 +1,38 @@
<table class="table table-striped table-bordered sortable">
<thead>
<tr>
<th data-defaultsort="disabled">&nbsp;</th>
<th>Name</th>
<th>Last activity</th>
</tr>
</thead>
<tbody>
<tr>
<td>&nbsp;</td>
<td><a href="{{ route('categories.noCategory') }}"><em>Without a category</em></a></td>
<td>&nbsp;</td>
</tr>
{% for category in categories %}
<tr>
<td>
<div class="btn-group btn-group-xs">
<a href="{{ route('categories.edit', category.id) }}" class="btn btn-default btn-xs"><i class="fa fa-fw fa-pencil"></i></a>
<a href="{{ route('categories.delete', category.id) }}" class="btn btn-danger btn-xs"><i class="fa fa-fw fa-trash-o"></i></a>
</div>
</td>
<td>
<a href="{{ route('categories.show', category.id) }}" title="{{ category.name }}">{{ category.name }}</a>
</td>
{% if category.lastActivity %}
<td data-value="{{ category.lastActivity.format('U') }}">
{{category.lastActivity.format('jS F Y') }}
</td>
{% else %}
<td data-value="0">
<em>Never</em>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,37 @@
<div class="list-group">
{% for journal in transactions %}
<a class="list-group-item" title="{{journal.date.format('jS M Y')}}" href="{{route('transactions.show',journal.id)}}">
{% if not journal.type %}
{% if journal.transactiontype.type == 'Withdrawal' %}
<i class="fa fa-long-arrow-left fa-fw" title="Withdrawal"></i>
{% endif %}
{% if journal.transactiontype.type == 'Deposit' %}
<i class="fa fa-long-arrow-right fa-fw" title="Deposit"></i>
{% endif %}
{% if journal.transactiontype.type == 'Transfer' %}
<i class="fa fa-fw fa-exchange" title="Transfer"></i>
{% endif %}
{% else %}
{% if journal.type == 'Withdrawal' %}
<i class="fa fa-long-arrow-left fa-fw" title="Withdrawal"></i>
{% endif %}
{% if journal.type == 'Deposit' %}
<i class="fa fa-long-arrow-right fa-fw" title="Deposit"></i>
{% endif %}
{% if journal.type == 'Transfer' %}
<i class="fa fa-fw fa-exchange" title="Transfer"></i>
{% endif %}
{% endif %}
{{ journal.description }}
<span class="pull-right small">
{{ journal|formatJournal }}
</span>
</a>
{% endfor %}
</div>

View File

@ -0,0 +1,113 @@
{{ journals.render|raw }}
<table class="table table-striped table-bordered sortable-table">
<tr class="ignore">
<th colspan="2">&nbsp;</th>
<th>Description</th>
<th>Amount</th>
<th>Date</th>
<th>From</th>
<th>To</th>
<!-- Hide budgets? -->
{% if not hideBudgets %}
<th><i class="fa fa-tasks fa-fw" title="Budget"></i></th>
{% endif %}
<!-- Hide categories? -->
{% if not hideCategories %}
<th><i class="fa fa-bar-chart fa-fw" title="Category"></i></th>
{% endif %}
<!-- Hide bills? -->
{% if not hideBills %}
<th><i class="fa fa-fw fa-rotate-right" title="Bill"></i></th>
{% endif %}
</tr>
{% for journal in journals %}
{% if invalidJournal(journal) %}
<tr class="ignore">
<td>
<div class="btn-group btn-group-xs">
<a href="{{ route("transactions.delete",journal.id) }}" class="btn btn-xs btn-danger"><i class="fa fa-fw fa-trash-o"></i></a>
</div>
</td>
<td>&nbsp;</td>
<td>{{ journal.description }}</td>
<td colspan="7"><em>Invalid journal: Found {{journal.transactions|length }} transaction(s)</em></td>
</tr>
{% else %}
<tr class="drag" data-date="{{journal.date.format('Y-m-d')}}" data-id="{{journal.id}}">
<td>
<div class="btn-group btn-group-xs">
{% if sorting %}
<a href="#" class="handle btn btn-default btn-xs"><i class="fa fa-fw fa-arrows-v"></i></a>
{% endif %}
<a href="{{ route('transactions.edit',journal.id)}}" class="btn btn-xs btn-default"><i class="fa fa-fw fa-pencil"></i></a>
<a href="{{ route('transactions.delete',journal.id)}}" class="btn btn-xs btn-danger"><i class="fa fa-fw fa-trash-o"></i></a>
</div>
</td>
<td>
{{ journal|typeIcon }}
</td>
<td>
<a href="{{route('transactions.show',journal.id)}}" title="{{journal.description}}">{{journal.description}}</a>
</td>
<td>
{% if not hideTags %}
{{ relevantTags(journal) }}
{% else %}
{{ journal|formatJournal }}
{% endif %}
</td>
<td>
{{journal.date.format('j F Y')}}
</td>
<td>
{% if journal.transactions[0].account.accountType.type == 'Cash account' %}
<span class="text-success">(cash)</span>
{% else %}
<a href="{{route('accounts.show',journal.transactions[0].account_id)}}">{{journal.transactions[0].account.name}}</a>
{% endif %}
</td>
<td>
{% if journal.transactions[1].account.accountType.type == 'Cash account' %}
<span class="text-success">(cash)</span>
{% else %}
<a href="{{route('accounts.show',journal.transactions[1].account_id)}}">{{journal.transactions[1].account.name}}</a>
{% endif %}
</td>
<!-- Do NOT hide the budget? -->
{% if not hideBudgets %}
<td>
{% if journal.budgets[0] %}
<a href="{{route('budgets.show',journal.budgets[0].id)}}">{{journal.budgets[0].name}}</a>
{% endif %}
</td>
{% endif %}
<!-- Do NOT hide the category? -->
{% if not hideCategories %}
<td>
{% if journal.categories[0] %}
<a href="{{route('categories.show',journal.categories[0].id)}}">{{journal.categories[0].name}}</a>
{% endif %}
</td>
{% endif %}
<!-- Do NOT hide the bill? -->
{% if not hideBills %}
<td>
{% if journal.bill %}
<a href="{{ route('bills.show',journal.bill_id) }}">{{journal.bill.name}}</a>
{% endif %}
</td>
{% endif %}
</tr>
{% endif %}
{% endfor %}
</table>
{{ journals.render|raw }}

View File

@ -0,0 +1,33 @@
<table class="table table-bordered table-striped">
<tr>
{% if showPiggyBank %}
<th>Piggy bank</th>
{% endif %}
<th>Date</th>
<th>Amount</th>
</tr>
{% for event in events %}
<tr>
{% if showPiggyBank %}
<td>
<a href="{{ route('piggyBanks.show',event.piggyBank_id) }}">{{ event.piggyBank.name }}</a>
</td>
{% endif %}
<td>
{% if event.transaction_journal_id %}
<a href="{{ route('transactions.show',event.transaction_journal_id) }}" title="{{ event.transactionJournal.description }}">{{ event.date.format('j F Y') }}</a>
{% else %}
{{ event.date.format('j F Y') }}
{% endif %}
</td>
<td>
{% if event.amount < 0 %}
<span class="text-danger">Removed {{ event.amount*-1|formatAmountPlain }}</span>
{% else %}
<span class="text-success">Added {{ event.amount|formatAmountPlain }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
</table>

View File

@ -0,0 +1,56 @@
<table class="table table-striped" id="sortable">
<tbody>
{% for piggyBank in piggyBanks %}
<tr data-id="{{ piggyBank.id }}">
<td style="width:60px;">
<i class="fa fa-fw fa-bars handle"></i>
<i class="loadSpin"></i>
</td>
<td style="width:100px;">
<div class="btn-group btn-group-xs">
<a href="{{ route('piggy-banks.edit', piggyBank.id)}}" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
<a href="{{ route('piggy-banks.delete', piggyBank.id)}}" class="btn btn-default btn-xs"><i class="fa fa-trash fa-fw"></i></a>
</div>
</td>
<td>
<a href="{{ route('piggy-banks.show', piggyBank.id) }}" title="{{ piggyBank.order }}">{{ piggyBank.name }}</a>
</td>
<td>
<span title="Saved so far">{{piggyBank.savedSoFar|formatAmountPlain }}</span>
</td>
<td style="text-align:right;width:40px;">
{% if piggyBank.savedSoFar > 0 %}
<a href="{{route('piggy-banks.removeMoney', piggyBank.id)}}" class="btn btn-default btn-xs removeMoney" data-id="{{ piggyBank.id }}"><span data-id="{{ piggyBank.id }}" class="glyphicon glyphicon-minus"></span></a>
{% endif %}
</td>
<td>
<div class="progress progress-striped" style="margin-bottom:0;">
<div
{% if piggyBank.percentage == 100 %}
class="progress-bar progress-bar-success"
{% else %}
class="progress-bar progress-bar-info"
{% endif %}
role="progressbar" aria-valuenow="{{ piggyBank.percentage }}" aria-valuemin="0" aria-valuemax="100" style="min-width: 40px;width: {{ piggyBank.percentage }}%;">
{{ piggyBank.percentage }}%
</div>
</div>
</td>
<td style="width:40px;">
{% if piggyBank.leftToSave > 0 %}
<a href="{{ route('piggy-banks.addMoney', piggyBank.id) }}" class="btn btn-default btn-xs addMoney" data-id="{{ piggyBank.id }}"><span data-id="{{ piggyBank.id }}" class="glyphicon glyphicon-plus"></span></a>
{% endif %}
</td>
<td style="width:200px;">
<span title="Target amount">{{ piggyBank.targetamount|formatAmount }}</span>
{% if piggyBank.leftToSave > 0 %}
<span title="Left to save">({{ piggyBank.leftToSave|formatAmount }})</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,45 @@
<div class="row">
{% if reminders|length > 0 %}
{% for reminder in reminders %}
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">
<a href="{{ route('reminders.show',reminder.id) }}">
{% if reminder.notnow %}
Dismissed reminder
{% else %}
Reminder
{% endif %}
for piggy bank "{{reminder.remindersable.name}}"
</a>
</div>
<div class="panel-body">
<p>
This reminder is active between {{reminder.startdate.format('jS F Y')}}
and {{reminder.enddate.format('jS F Y')}}.
</p>
{% if reminder.description %}
<p>{{ reminder.description|raw }}</p>
{% endif %}
</div>
<div class="panel-footer">
<div class="btn-group">
{% if not reminder.notnow %}
<a class="btn btn-warning" href="{{route('reminders.dismiss',reminder.id)}}">Dismiss</a>
{% endif %}
{% if reminder.active %}
<a class="btn btn-success" href="{{route('reminders.act',reminder.id)}}">Act</a>
{% endif %}
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<p class="small">
(No reminders)
</p>
</div>
{% endif %}
</div>

View File

@ -0,0 +1,92 @@
<!-- /.row -->
<div class="row">
<div class="hidden-xs col-lg-3 col-md-6">
<div class="panel panel-red">
<div class="panel-heading">
<div class="row">
<div class="col-xs-3">
<i class="fa fa-upload fa-3x"></i>
</div>
<div class="col-xs-9 text-right">
<div id="box-out" class="large"></div>
<div>Money out</div>
</div>
</div>
</div>
<a href="{{route('transactions.index','withdrawal')}}">
<div class="panel-footer">
<span class="pull-left">View Details</span>
<span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
<div class="clearfix"></div>
</div>
</a>
</div>
</div>
<div class="hidden-xs col-lg-3 col-md-6">
<div class="panel panel-green">
<div class="panel-heading">
<div class="row">
<div class="col-xs-3">
<i class="fa fa-download fa-3x"></i>
</div>
<div class="col-xs-9 text-right">
<div id="box-in" class="large"></div>
<div>Money in</div>
</div>
</div>
</div>
<a href="{{route('transactions.index','deposit')}}">
<div class="panel-footer">
<span class="pull-left">View Details</span>
<span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
<div class="clearfix"></div>
</div>
</a>
</div>
</div>
<div class="hidden-xs col-lg-3 col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<div class="row">
<div class="col-xs-3">
<i class="fa fa-calendar fa-3x"></i>
</div>
<div class="col-xs-9 text-right">
<div id="box-bills-unpaid" class="large"></div>
<div>Bills to pay</div>
</div>
</div>
</div>
<a href="{{route('bills.index')}}">
<div class="panel-footer">
<span class="pull-left">View Details</span>
<span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
<div class="clearfix"></div>
</div>
</a>
</div>
</div>
<div class="hidden-xs col-lg-3 col-md-6">
<div class="panel panel-green">
<div class="panel-heading">
<div class="row">
<div class="col-xs-3">
<i class="fa fa-line-chart fa-3x"></i>
</div>
<div class="col-xs-9 text-right">
<div id="box-bills-paid" class="large"></div>
<div>Bills paid</div>
</div>
</div>
</div>
<a href="{{route('bills.index')}}">
<div class="panel-footer">
<span class="pull-left">View Details</span>
<span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
<div class="clearfix"></div>
</div>
</a>
</div>
</div>
</div>
<!-- /.row -->

View File

@ -0,0 +1,27 @@
{% if Session.has('success') %}
<div class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<strong>Success!</strong> {{Session.get('success')}}
</div>
{% endif %}
{% if Session.has('info') %}
<div class="alert alert-info alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<strong>Info:</strong> {{Session.get('info')}}
</div>
{% endif %}
{% if Session.has('warning') %}
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<strong>Warning!</strong> {{Session.get('warning')}}
</div>
{% endif %}
{% if Session.has('error') %}
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<strong>Error!</strong> {{Session.get('error')}}
</div>
{% endif %}

View File

@ -0,0 +1,182 @@
<!-- Navigation -->
<nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{{ route('index') }}">Firefly</a>
</div>
<!-- /.navbar-header -->
<ul class="nav navbar-top-links navbar-right">
<!-- reminders -->
{% if reminders|length > 0 %}
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="false">
<i class="fa fa-envelope fa-fw"></i> <i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-messages">
{% for reminder in reminders %}
<li>
<a href="{{ route('reminders.show',reminder.id) }}">
<div>
<strong>
{{ reminder.remindersable.name }}
</strong>
<span class="pull-right text-muted">
<em>{{ reminder.startdate.diffForHumans }}</em>
</span>
</div>
<div>{{ reminder.description|raw }}</div>
</a>
</li>
<li class="divider"></li>
{% endfor %}
<li>
<a class="text-center" href="{{ route('reminders.index') }}">
<strong>See all reminders</strong>
<i class="fa fa-angle-right"></i>
</a>
</li>
</ul>
<!-- /.dropdown-messages -->
</li>
{% endif %}
<!-- menu -->
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i>
</a>
<ul class="dropdown-menu dropdown-user">
<li><a href="{{ route('profile') }}"><i class="fa fa-user fa-fw"></i> {{ Auth.user.email }}</a></li>
<li><a href="{{ route('preferences') }}"><i class="fa fa-gear fa-fw"></i> Preferences</a></li>
<li><a href="{{ route('currency.index') }}"><i class="fa fa-usd fa-fw"></i> Currency</a></li>
<li><a href="{{ route('reminders.index') }}"><i class="fa fa-clock-o fa-fw"></i> Reminders</a></li>
<li class="divider"></li>
<li><a href="{{ route('logout') }}"><i class="fa fa-sign-out fa-fw"></i> Logout</a></li>
</ul>
<!-- /.dropdown-user -->
</li>
<!-- /.dropdown -->
</ul>
<p class="navbar-text navbar-right" id="daterange"><span>&nbsp;</span> <b class="caret"></b></p>
<!-- /.navbar-top-links -->
<div class="navbar-default sidebar" role="navigation">
<div class="sidebar-nav navbar-collapse">
<ul class="nav" id="side-menu">
<li class="sidebar-search">
<form action="{{ route('search') }}" method="GET" class="form-inline">
<div class="input-group custom-search-form">
<input type="text" name="q" class="form-control" value="{% if Input.get('q') %}{{ Input.get('q') }}{% endif %}"
placeholder="Search...">
<span class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="fa fa-search"></i></button>
</span>
</div>
</form>
<!-- /input-group -->
</li>
<li>
<a class="{{ activeRoute('index',null,true) }}" href="{{ route('index') }}"><i class="fa fa-dashboard fa-fw"></i> Dashboard</a>
</li>
<li class="{{ activeRoute('accounts.index') }}">
<a href="#"><i class="fa fa-credit-card fa-fw"></i> Accounts <span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a class="{{ activeRoute('accounts.index', 'asset') }}" href="{{ route('accounts.index','asset') }}"><i class="fa fa-money fa-fw"></i> Asset
accounts</a>
</li>
<li>
<a class="{{ activeRoute('accounts.index', 'expense') }}" href="{{ route('accounts.index','expense') }}"><i
class="fa fa-shopping-cart fa-fw"></i> Expense accounts</a>
</li>
<li>
<a class="{{ activeRoute('accounts.index', 'revenue') }}" href="{{ route('accounts.index','revenue') }}"><i class="fa fa-download fa-fw"></i>
Revenue accounts</a>
</li>
</ul>
<!-- /.nav-second-level -->
</li>
<li>
<a class="{{ activeRoute('budgets') }}" href="{{ route('budgets.index') }}"><i class="fa fa-tasks fa-fw"></i> Budgets</a>
</li>
<li>
<a class="{{ activeRoute('categories') }}" href="{{ route('categories.index') }}"><i class="fa fa-bar-chart fa-fw"></i> Categories</a>
</li>
<li>
<a class="{{ activeRoute('tags') }}" href="{{ route('tags.index') }}"><i class="fa fa-tags fa-fw"></i> Tags</a>
</li>
<li>
<a class="{{ activeRoute('reports') }}" href="{{ route('reports.index') }}"><i class="fa fa-line-chart fa-fw"></i> Reports</a>
</li>
<li class="{{ activeRoute('transactions') }}">
<a href="#"><i class="fa fa-repeat fa-fw"></i> Transactions<span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a class="{{ activeRoute('transactions','withdrawal') }}" href="{{ route('transactions.index','withdrawal') }}"><i
class="fa fa-long-arrow-left fa-fw"></i> Expenses</a>
</li>
<li>
<a class="{{ activeRoute('transactions','deposit') }}" href="{{ route('transactions.index','deposit') }}"><i
class="fa fa-long-arrow-right fa-fw"></i> Revenue / income</a>
</li>
<li>
<a class="{{ activeRoute('transactions','transfers') }}" href="{{ route('transactions.index','transfers') }}"><i class="fa fa-fw fa-exchange"
title="Transfer"></i> Transfers</a>
</li>
</ul>
</li>
<li class="{{ activeRoute('piggy-banks') }}">
<a href="#"><i class="fa fa-euro fa-fw"></i> Money management<span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a class="{{ activeRoute('piggy-banks') }}" href="{{ route('piggy-banks.index') }}"><i class="fa fa-sort-amount-asc fa-fw"></i> Piggy
banks</a>
</li>
<li>
<a class="{{ activeRoute('bills') }}" href="{{ route('bills.index') }}"><i class="fa fa-calendar-o fa-fw"></i> Bills</a>
</li>
</ul>
<!-- /.nav-second-level -->
</li>
<li class="{{ activeRoute('transactions.create') }}">
<a href="#"><i class="fa fa-plus fa-fw"></i> Create new<span class="fa arrow"></span></a>
<ul class="nav nav-second-level">
<li>
<a class="{{ activeRoute('transactions.create','withdrawal') }}" href="{{ route('transactions.create','withdrawal') }}"><i
class="fa fa-long-arrow-left fa-fw"></i> Withdrawal</a>
</li>
<li>
<a class="{{ activeRoute('transactions.create','deposit') }}" href="{{ route('transactions.create','deposit') }}"><i
class="fa fa-long-arrow-right fa-fw"></i> Deposit</a>
</li>
<li>
<a class="{{ activeRoute('transactions.create','transfer') }}" href="{{ route('transactions.create','transfer') }}"><i class="fa fa-fw fa-exchange"
title="Transfer"></i> Transfer</a>
</li>
<li>
<a class="{{ activeRoute('bills.create') }}" href="{{ route('bills.create') }}"><i class="fa fa-calendar-o fa-fw"></i> Bill</a>
</li>
</ul>
<!-- /.nav-second-level -->
</li>
</ul>
</div>
<!-- /.sidebar-collapse -->
</div>
<!-- /.navbar-static-side -->
</nav>

View File

@ -0,0 +1,27 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Add money to {{ piggyBank.name }}</h4>
</div>
<form style="display: inline;" id="add" action="{{ route('piggy-banks.add', piggyBank.id) }}" method="POST">
<div class="modal-body">
<p>
The maximum amount you can add is {{ maxAmount|formatAmount }}.
</p>
<div class="input-group">
<div class="input-group-addon">{{ getCurrencySymbol() }}</div>
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<input step="any" class="form-control" id="amount" autocomplete="off" name="amount" max="{{ maxAmount|round(2) }}" type="number" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Add</button>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,57 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'store','url' : route('piggy-banks.store')}) }}
<input type="hidden" name="repeats" value="0" />
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-fw fa-exclamation"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
{{ ExpandedForm.select('account_id',accounts,null,{'label' : 'Save on account'}) }}
{{ ExpandedForm.amount('targetamount') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-12 col-sm-12">
<!-- panel for optional fields -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{{ ExpandedForm.date('targetdate') }}
{{ ExpandedForm.checkbox('remind_me','1',false,{'label' : 'Remind me'}) }}
{{ ExpandedForm.select('reminder',periods,'month',{'label' : 'Remind every'}) }}
</div>
</div>
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('create','piggy bank') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new piggy bank
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,26 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, piggyBank) }}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('piggy-banks.destroy',piggyBank.id)}) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete piggy bank "{{ piggyBank.name }}"
</div>
<div class="panel-body">
<p>
Are you sure?
</p>
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{ URL.previous() }}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,61 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, piggyBank) }}
{{ Form.model(piggyBank, {'class' : 'form-horizontal','id' : 'update','url' : route('piggy-banks.update',piggyBank.id)}) }}
<input type="hidden" name="repeats" value="0" />
<input type="hidden" name="id" value="{{ piggyBank.id }}" />
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa fa-fw fa-exclamation"></i> Mandatory fields
</div>
<div class="panel-body">
{{ ExpandedForm.text('name') }}
{{ ExpandedForm.select('account_id',accounts,null,{'label' : 'Save on account'}) }}
{{ ExpandedForm.amount('targetamount') }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-12 col-sm-12">
<!-- panel for optional fields -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields
</div>
<div class="panel-body">
{{ ExpandedForm.date('targetdate') }}
{{ ExpandedForm.checkbox('remind_me','1',preFilled.remind_me,{'label' : 'Remind me'}) }}
{{ ExpandedForm.select('reminder',periods,preFilled.reminder,{'label' : 'Remind every'}) }}
</div>
</div>
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{ ExpandedForm.optionsList('update','piggy bank') }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-pencil"></i> Update piggy bank
</button>
</p>
</div>
</div>
</form>
{% endblock %}

View File

@ -0,0 +1,62 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<p>
<a href="{{ route('piggy-banks.create') }}" class="btn btn-success"><i class="fa fa-sort-amount-asc fa-fw"></i> Create new piggy bank</a>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">Piggy banks</div>
{% include 'list/piggy-banks.twig' %}
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-money"></i> Account status
</div>
<table class="table table-striped">
<tr>
<th>Account</th>
<th>Balance</th>
<th>Left for piggy banks</th>
<th>Sum of piggy banks</th>
<th>Saved so far</th>
<th>Left to save</th>
</tr>
{% for id,info in accounts %}
<tr>
<td><a href="{{ route('accounts.show',id) }}">{{ info.name }}</a></td>
<td>{{ info.balance|formatAmount }}</td>
<td>{{ info.leftForPiggyBanks|formatAmount }}</td>
<td>{{ info.sumOfTargets|formatAmount }}</td>
<td>{{ info.sumOfSaved|formatAmount }}</td>
<td>{{ info.leftToSave|formatAmount }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
<!-- this is the modal for the add/remove money routine: -->
<div class="modal fade" id="moneyManagementModal">
</div><!-- /.modal -->
{% endblock %}
{% block scripts %}
<script src="js/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript" src="js/piggy-banks.js"></script>
{% endblock %}

View File

@ -0,0 +1,26 @@
<div class="modal-dialog">
<div class="modal-content">
<form style="display: inline;" id="remove" action="{{ route('piggy-banks.remove', piggyBank.id) }}" method="POST">
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">Remove money from {{ piggyBank.name }}</h4>
</div>
<div class="modal-body">
<p>
The maximum amount you can remove is {{ currentRelevantRepAmount(piggyBank)|formatAmount }}
</p>
<div class="input-group">
<div class="input-group-addon">{{ getCurrencySymbol() }}</div>
<input step="any" class="form-control" id="amount" autocomplete="off" name="amount" max="{{ currentRelevantRepAmount(piggyBank)|round(2) }}" type="number">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Remove</button>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,120 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, piggyBank) }}
<div class="row">
<div class="col-lg-8 col-md-8 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-clock-o"></i> Events
</div>
<div class="panel-body">
<div id="piggy-bank-history"></div>
</div>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-info-circle"></i> Details
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Actions
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
<li><a href="{{ route('piggy-banks.edit', piggyBank.id) }}"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
<li><a href="{{ route('piggy-banks.delete', piggyBank.id) }}"><i class="fa fa-trash fa-fw"></i> Delete</a></li>
</ul>
</div>
</div>
</div>
<table class="table table-bordered table-striped">
<tr>
<td>Account</td>
<td><a href="{{ route('accounts.show', piggyBank.account_id) }}">{{ piggyBank.account.name }}</a></td>
</tr>
<tr>
<td>Target amount</td>
<td>{{ piggyBank.targetAmount|formatAmount }}</td>
</tr>
<tr>
<td>Saved so far</td>
<td>{{ currentRelevantRepAmount(piggyBank)|formatAmount }}</td>
</tr>
<tr>
<td>Left to save</td>
<td>{{ piggyBank.targetamount - currentRelevantRepAmount(piggyBank)|formatAmount }}</td>
</tr>
<tr>
<td>Start date</td>
<td>
{% if piggyBank.startdate %}
{{ piggyBank.startdate.format('jS F Y')}}
{% else %}
<em>No start date</em>
{% endif %}
</td>
</tr>
<tr>
<td>Target date</td>
<td>
{% if piggyBank.targetdate %}
{{ piggyBank.targetdate.format('jS F Y') }}
{% else %}
<em>No start date</em>
{% endif %}
</td>
</tr>
{% if piggyBank.reminder %}
<tr>
<td>Reminder</td>
<td>
{% if piggyBank.remind_me == 0 %}
<em>(no reminder)</em>
{% else %}
Every
{% if piggyBank.reminder_skip != 0 %}
{{ piggyBank.reminder_skip }}
{% else %}
{{ piggyBank.reminder }}(s)
{% endif %}
{% endif %}
</td>
</tr>
{% endif %}
<tr>
<td>Reminders left</td>
<td>(in progress...)</td>
</tr>
<tr>
<td>Expected amount per reminder</td>
<td>(in progress...)</td>
</tr>
</table>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-clock-o"></i> Table
</div>
{% include 'list/piggy-bank-events' %}
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var piggyBankID = {{ piggyBank.id }};
</script>
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="js/gcharts.options.js"></script>
<script type="text/javascript" src="js/gcharts.js"></script>
<script type="text/javascript" src="js/piggy-banks.js"></script>
{% endblock %}

View File

@ -0,0 +1,102 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, piggyBank) }}
<!-- form -->
{{ Form.open({'class' : 'form-horizontal','id' : 'preferences'}) }}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-credit-card fa-fw"></i> Home screen accounts
</div>
<div class="panel-body">
<p class="text-info">Which accounts should be displayed on the home page?</p>
{% for account in accounts %}
<div class="form-group">
<div class="col-sm-10">
<div class="checkbox">
<label>
{% if account.id in frontPageAccounts.data or frontPageAccounts.data|length == 0 %}
<input type="checkbox" name="frontPageAccounts[]" value="{{ account.id }}" checked> {{ account.name }}
{% else %}
<input type="checkbox" name="frontPageAccounts[]" value="{{ account.id }}"> {{ account.name }}
{% endif %}
</label>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-credit-card fa-fw"></i> Budget settings
</div>
<div class="panel-body">
<p class="text-info">
What's the maximum amount of money a budget envelope may contain?
</p>
{{ ExpandedForm.amount('budgetMaximum',budgetMaximum,{'label' : 'Budget maximum'}) }}
</div>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-6">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-clock-o fa-fw"></i> View range
</div>
<div class="panel-body">
<p class="text-info">Some charts are automatically grouped in periods. What period would you prefer?</p>
<div class="radio">
<label>
<input type="radio" name="viewRange" value="1D" {% if viewRange == '1D' %} checked {% endif %}>
One day
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="viewRange" value="1W" {% if viewRange == '1W' %} checked {% endif %}>
One week
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="viewRange" value="1M" {% if viewRange == '1M' %} checked {% endif %}>
One month
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="viewRange" value="3M" {% if viewRange == '3M' %} checked {% endif %}>
Three months
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="viewRange" value="6M" {% if viewRange == '6M' %} checked {% endif %}>
Six months
</label>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="form-group">
<div class="col-sm-12">
<button type="submit" class="btn btn-success btn-lg">Save settings</button>
</div>
</div>
</div>
</div>
<!-- form close -->
</form>
{% endblock %}

View File

@ -0,0 +1,55 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
Change your password
</div>
<div class="panel-body">
{% if errors|length > 0 %}
<ul>
<ul>
{% for error in errors.all %}
<li class="text-danger">{{ error }}</li>
{% endfor %}
</ul>
</ul>
{% endif %}
{{ Form.open({'class' : 'form-horizontal','id' : 'change-password'}) }}
<div class="form-group">
<label for="inputOldPassword" class="col-sm-4 control-label">Old password</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="inputOldPassword" placeholder="Old password" name="current_password">
</div>
</div>
<div class="form-group">
<label for="inputNewPassword1" class="col-sm-4 control-label">New password</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="inputNewPassword1" placeholder="New password" name="new_password">
</div>
</div>
<div class="form-group">
<label for="inputNewPassword2" class="col-sm-4 control-label">New password (again)</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="inputNewPassword2" placeholder="New password (again)" name="new_password_confirmation">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-10">
<button type="submit" class="btn btn-success">Change your password</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,49 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete your account
</div>
<div class="panel-body">
<p class="text-danger">
Deleting your account will also delete any accounts, transactions, <em>anything</em>
you might have saved into Firefly III. It'll be GONE.
</p>
<p class="text-danger">
Enter your password to continue.
</p>
{% if errors|length > 0 %}
<ul>
<ul>
{% for error in errors.all %}
<li class="text-danger">{{ error }}</li>
{% endfor %}
</ul>
</ul>
{% endif %}
{{ Form.open({'class' : 'form-horizontal','id' : 'change-password'}) }}
<div class="form-group">
<label for="password" class="col-sm-4 control-label">Password</label>
<div class="col-sm-8">
<input type="password" class="form-control" id="password" placeholder="Password" name="password">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-10">
<button type="submit" onclick="confirm('Are you sure? You cannot undo this.')" class="btn btn-danger">DELETE your account</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
Options
</div>
<div class="panel-body">
<ul>
<li><a href="{{route('change-password')}}">Change your password</a></li>
<li><a class="text-danger" href="{{route('delete-account')}}">Delete account</a></li>
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,37 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h3>Active reminders</h3>
</div>
</div>
{% include 'list/reminders.twig' with {'reminders': active} %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h3>Dismissed reminders</h3>
</div>
</div>
{% include 'list/reminders.twig' with {'reminders': dismissed} %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h3>Expired reminders</h3>
</div>
</div>
{% include 'list/reminders.twig' with {'reminders': expired} %}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h3>Inactive reminders</h3>
</div>
</div>
{% include 'list/reminders.twig' with {'reminders': inactive} %}
{% endblock %}

View File

@ -0,0 +1,40 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, reminder) }}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">
<a href="{{route('reminders.show',reminder.id)}}">
{% if reminder.notnow %}
Dismissed reminder
{% else %}
Reminder
{% endif %}
for piggy bank "{{reminder.remindersable.name}}"
</a>
</div>
<div class="panel-body">
<p>
Active between {{reminder.startdate.format('jS F Y')}}
and {{reminder.enddate.format('jS F Y')}}.
</p>
{% if reminder.description %}
<p>{!! reminder.description !!}</p>
{% endif %}
</div>
<div class="panel-footer">
<div class="btn-group">
{% if not reminder.notnow %}
<a class="btn btn-warning" href="{{route('reminders.dismiss',reminder.id)}}">Dismiss</a>
{% endif %}
{% if reminder.active %}
<a class="btn btn-success" href="{{route('reminders.act',reminder.id)}}">Act</a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,159 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, date) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<a href="#" class="btn btn-default" id="includeShared" style="display:none;">
<i class="state-icon glyphicon glyphicon-unchecked"></i>
Include shared asset accounts</a>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-credit-card"></i>
Accounts
</div>
<table class="table table-bordered table-striped">
<tr>
<th>Account</th>
<th>Start of month</th>
<th>Current balance</th>
<th>Spent</th>
<th>Earned</th>
</tr>
{% for account in accounts %}
<tr>
<td><a href="{{route('accounts.show',account.id)}}">{{ account.name }}</a></td>
<td>{{ account.startBalance|formatAmount }}</td>
<td>{{ account.endBalance|formatAmount }}</td>
<td>
{% if account.startBalance - account.endBalance > 0 %}
<span class="text-danger">{{ (account.startBalance - account.endBalance)|formatAmountPlain }}</span>
{% endif %}
</td>
<td>
{% if account.startBalance - account.endBalance < 0 %}
<span class="text-success">{{ ((account.startBalance - account.endBalance)*-1)|formatAmountPlain }}</span>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-tasks fa-fw"></i>
Budgets
</div>
<table class="table table-bordered table-striped">
<tr>
<th colspan="2">Budgets</th>
{% for account in accounts %}
{% if not account.hide %}
<th><a href="{{route('accounts.show',account.id)}}">{{ account.name }}</a></th>
{% endif %}
{% endfor %}
<th colspan="2">
Left in budget
</th>
</tr>
{% for id,budget in budgets %}
<tr>
<td>{{ budget.name }}</td>
<td>{{ budget.queryAmount|formatAmount }}</td>
{% set spent = 0 %}
{% for account in accounts %}
{% if not account.hide %}
{% if account.budgetInformation[id] %}
<td>
{% if id == 0 %}
<a href="{{route('reports.no-budget',[account, year, month])}}" class="openModal">
{{ account.budgetInformation[id].queryAmount|formatAmount }}
</a>
{% else %}
{{ account.budgetInformation[id].queryAmount|formatAmount }}
{% endif %}
</td>
{% set spent = spent + account.budgetInformation[id].queryAmount %}
{% else %}
<td>{{ 0|formatAmount }}</td>
{% endif %}
{% endif %}
{% endfor %}
<td>{{ (budget.queryAmount + budget.spent)|formatAmount }}</td>
<td>{{ (budget.queryAmount + spent)|formatAmount }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="2">Balanced by transfers</td>
{% for account in accounts %}
{% if not account.hide %}
<td>
<a href="{{route('reports.balanced-transfers',[account, year, month])}}" class="openModal">{{ account.balancedAmount|formatAmount }}</a>
</td>
{% endif %}
{% endfor %}
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td colspan="2">Left unbalanced</td>
{% for account in accounts %}
{% if not account.hide %}
{% if account.budgetInformation[0] %}
<td>
{% if account.budgetInformation[0].queryAmount + account.balancedAmount != 0.0 %}
<a href="{{route('reports.left-unbalanced',[account, year, month])}}" class="openModal">{{ (account.budgetInformation[0].queryAmount + account.balancedAmount)|formatAmount }}</a>
{% else %}
{{ (account.budgetInformation[0].queryAmount + account.balancedAmount)|formatAmount }}
{% endif %}
</td>
{% else %}
<td>{{ 0|formatAmount }}</td>
{% endif %}
{% endif %}
{% endfor %}
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td colspan="2"><em>Sum</em></td>
{% for account in accounts %}
{% if not account.hide %}
<td>{{ accountAmounts[account.id]|formatAmount }}</td>
{% endif %}
{% endfor %}
<td colspan="2">&nbsp;</td>
</tr>
<tr>
<td colspan="2">Expected balance</td>
{% for account in accounts %}
{% if not account.hide %}
<td>{{ (account.startBalance + accountAmounts[account.id])|formatAmount }}</td>
{% endif %}
{% endfor %}
<td colspan="2">&nbsp;</td>
</tr>
</table>
</div>
</div>
</div>
<!-- modal to show various budget information -->
<div class="modal fade" id="budgetModal">
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="js/reports.js"></script>
{% endblock %}

View File

@ -0,0 +1,74 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<a href="#" class="btn btn-default" id="includeShared" style="display:none;">
<i class="state-icon glyphicon glyphicon-unchecked"></i>
Include shared asset accounts</a>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar fa-fw"></i>
Yearly reports
</div>
<div class="panel-body">
<ul>
{% for year in years %}
<li><a href="{{route('reports.year',year)}}">{{ year }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar fa-fw"></i>
Monthly reports
</div>
<div class="panel-body">
{% for year, entries in months %}
<h5>{{ year }}</h5>
<ul>
{% for month in entries %}
<li><a href="{{route('reports.month',[month.year, month.month])}}">{{ month.formatted}}</a></li>
{% endfor %}
</ul>
{% endfor %}
</div>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar fa-fw"></i>
Budget reports
</div>
<div class="panel-body">
{% for year, entries in months %}
<h5>{{ year }}</h5>
<ul>
{% for month in entries %}
<li><a href="{{route('reports.budget',[month.year,month.month])}}">{{ month.formatted}}</a></li>
{% endfor %}
</ul>
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="js/reports.js"></script>
{% endblock %}

View File

@ -0,0 +1,257 @@
{% extends "./layout/default.twig" %}
{% block content %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, date) }}
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<p>
<a href="#" class="btn btn-default" id="includeShared" style="display:none;">
<i class="state-icon glyphicon glyphicon-unchecked"></i> Include shared asset accounts</a>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-5 col-md-5 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-long-arrow-right fa-fw"></i>
Income
</div>
<table class="table table-bordered">
{% set sum = 0 %}
{% for entry in income %}
{% set sum = sum + entry.queryAmount %}
<tr>
<td>
<a href="{{ route('transactions.show',entry.id) }}" title="{{ entry.description }}">{{ entry.description }}</a>
</td>
<td>
{% if entry.type == 'Withdrawal' %}
<span class="text-danger">{{entry.queryAmount|formatAmountPlain}}</span>
{% endif %}
{% if entry.type == 'Deposit' %}
<span class="text-success">{{entry.queryAmount|formatAmountPlain}}</span>
{% endif %}
{% if entry.type == 'Transfer' %}
<span class="text-info">{{entry.queryAmount|formatAmountPlain}}</span>
{% endif %}
</td>
<td>
{{entry.date.format('j F Y')}}
</td>
<td>
<a href="{{route('accounts.show',entry.account_id)}}">{{ entry.name }}</a>
</td>
</tr>
{% endfor %}
{% if displaySum %}
<tr>
<td><em>Sum</em></td>
<td colspan="3">{{ sum|formatAmount }}</td>
</tr>
{% endif %}
</table>
</div>
</div>
<div class="col-lg-4 col-md-4 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-long-arrow-left fa-fw"></i>
Expenses (top 10)
</div>
<table class="table table-bordered">
{% set sum = 0 %}
{% for id,expense in expenses %}
{% set sum = sum + expense.queryAmount %}
<tr>
{% if id > 0 %}
<td><a href="{{route('accounts.show',id)}}">{{ expense.name }}</a></td>
{% else %}
<td><em>{{ expense.name }}</em></td>
{% endif %}
<td><span class="text-danger">{{ expense.queryAmount|formatAmountPlain }}</span></td>
</tr>
{% endfor %}
<tr>
<td><em>Sum</em></td>
<td><span class="text-danger">{{ sum|formatAmountPlain }}</span></td>
</tr>
</table>
</div>
</div>
<div class="col-lg-3 col-md-4 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-exchange fa-fw"></i>
Sums
</div>
{% set totalIn = 0 %}
{% for entry in income %}
{% set totalIn = totalIn + entry.queryAmount %}
{% endfor %}
<table class="table table-bordered">
<tr>
<td>In</td>
<td>{{ totalIn|formatAmount }}</td>
</tr>
<tr>
<td>Out</td>
<td><span class="text-danger">{{ sum|formatAmountPlain }}</span></td>
</tr>
<tr>
<td>Difference</td>
<td>{{ (totalIn - sum)|formatAmount }}</td>
</tr>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-tasks fa-fw"></i>
Budgets
</div>
<table class="table table-bordered">
<tr>
<th>Budget</th>
<th>Envelope</th>
<th>Spent</th>
<th>Left</th>
</tr>
{% set sumSpent = 0 %}
{% set sumEnvelope = 0 %}
{% set sumLeft = 0 %}
{% for id,budget in budgets %}
{% set sumSpent = sumSpent + budget.spent %}
{% set sumEnvelope = sumEnvelope + budget.queryAmount %}
{% set sumLeft = sumLeft + budget.queryAmount + budget.spent %}
<!-- only display when relevant: -->
{% if budget.queryAmount != 0 or budget.spent != 0 %}
<tr>
<td>
{% if id > 0 %}
<a href="{{route('budgets.show',id)}}">{{ budget.name }}</a>
{% else %}
<em>{{ budget.name }}</em>
{% endif %}
</td>
<td>{{ budget.queryAmount|formatAmount }}</td>
<td><span class="text-danger">{{ (budget.spent*-1)|formatAmountPlain }}</span></td>
<td>{{ (budget.queryAmount + budget.spent)|formatAmount }}</td>
</tr>
{% endif %}
{% endfor %}
<tr>
<td><em>Sum</em></td>
<td>{{ sumEnvelope|formatAmount }}</td>
<td>{{ sumSpent|formatAmount }}</td>
<td>{{ sumLeft|formatAmount }}</td>
</tr>
</table>
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bar-chart fa-fw"></i>
Categories
</div>
<table class="table table-bordered">
<tr>
<th>Category</th>
<th>Spent</th>
</tr>
{% set sum = 0 %}
{% for id,category in categories %}
{% set sum = sum + category.queryAmount %}
<tr>
<td>
{% if id > 0 %}
<a href="{{route('categories.show',id)}}">{{ category.name }}</a>
{% else %}
<em>{{ category.name }}</em>
{% endif %}
</td>
<td><span class="text-danger">{{ (category.queryAmount * -1)|formatAmountPlain }}</span></td>
</tr>
{% endfor %}
<tr>
<td><em>Sum</em></td>
<td><span class="text-danger">{{ (sum * -1)|formatAmountPlain }}</span></td>
</tr>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-credit-card fa-fw"></i>
Accounts
</div>
<table class="table table-bordered">
{% set sumStart = 0 %}
{% set sumEnd = 0 %}
{% set sumDiff = 0 %}
{% for id,account in accounts %}
{% set sumStart = sumStart + account.startBalance %}
{% set sumEnd = sumEnd + account.endBalance %}
{% set sumDiff = sumDiff + account.difference %}
<tr>
<td><a href="{{route('accounts.show',id)}}">{{ account.name }}</a></td>
<td>{{ account.startBalance|formatAmount }}</td>
<td>{{ account.endBalance|formatAmount }}</td>
<td>{{ account.difference|formatAmount }}</td>
</tr>
{% endfor %}
<tr>
<td><em>Sum</em></td>
<td>{{ sumStart|formatAmount }}</td>
<td>{{ sumEnd|formatAmount }}</td>
<td>{{ sumDiff|formatAmount }}</td>
</tr>
</table>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-sort-amount-asc fa-fw"></i>
Piggy banks
</div>
<div class="panel-body">Body</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-calendar-o fa-fw"></i>
Bills
</div>
<div class="panel-body">Body</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-fw fa-folder-o"></i>
Outside of budgets
</div>
<div class="panel-body">Body</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="js/reports.js"></script>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show More