mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-28 09:51:21 -06:00
Merge branch 'feature/twig' into develop
This commit is contained in:
commit
b2fd346ef8
18
.env.backup
Executable file
18
.env.backup
Executable 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
18
.env.local
Executable 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=
|
@ -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.
|
||||
*
|
||||
|
@ -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'));
|
||||
}
|
||||
|
@ -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');
|
||||
$start = clone $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();
|
||||
$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) ^^
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $end) {
|
||||
$budgets = $this->query->getBudgetSummary($account, $start, $end);
|
||||
$balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end);
|
||||
$array = [];
|
||||
$hide = true;
|
||||
foreach ($budgets as $budget) {
|
||||
$id = intval($budget->id);
|
||||
$data = $budget->toArray();
|
||||
$array[$id] = $data;
|
||||
if (floatval($data['queryAmount']) != 0) {
|
||||
$hide = false;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
$account->hide = $hide;
|
||||
$account->budgetInformation = $array;
|
||||
$account->balancedAmount = $balancedAmount;
|
||||
|
||||
$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'));
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -35,6 +35,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
'Illuminate\Contracts\Auth\Registrar',
|
||||
'FireflyIII\Services\Registrar'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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' => [],
|
||||
],
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -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');
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -160,12 +160,15 @@ 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);
|
||||
|
||||
define('FFCURRENCYCODE', $currency->code);
|
||||
return $currency->code;
|
||||
}
|
||||
|
||||
return $currency->code;
|
||||
return 'EUR';
|
||||
}
|
||||
|
||||
public function getDefaultCurrency()
|
||||
|
53
app/Support/Twig/Budget.php
Normal file
53
app/Support/Twig/Budget.php
Normal 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';
|
||||
}
|
||||
}
|
146
app/Support/Twig/General.php
Normal file
146
app/Support/Twig/General.php
Normal 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';
|
||||
}
|
||||
|
||||
}
|
78
app/Support/Twig/Journal.php
Normal file
78
app/Support/Twig/Journal.php
Normal 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';
|
||||
}
|
||||
}
|
41
app/Support/Twig/PiggyBank.php
Normal file
41
app/Support/Twig/PiggyBank.php
Normal 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';
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
176
composer.lock
generated
@ -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,
|
||||
|
@ -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',
|
||||
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
@ -201,13 +203,14 @@ return [
|
||||
'View' => 'Illuminate\Support\Facades\View',
|
||||
'Form' => 'Illuminate\Html\FormFacade',
|
||||
'Html' => 'Illuminate\Html\HtmlFacade',
|
||||
'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
|
||||
|
||||
'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',
|
||||
|
||||
|
||||
],
|
||||
|
||||
|
@ -14,7 +14,7 @@ return [
|
||||
*/
|
||||
|
||||
'paths' => [
|
||||
realpath(base_path('resources/views'))
|
||||
realpath(base_path('resources/twig'))
|
||||
],
|
||||
|
||||
/*
|
||||
|
@ -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"/>
|
||||
|
@ -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');
|
||||
}
|
||||
});
|
||||
|
61
resources/twig/accounts/create.twig
Normal file
61
resources/twig/accounts/create.twig
Normal 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 %}
|
36
resources/twig/accounts/delete.twig
Normal file
36
resources/twig/accounts/delete.twig
Normal 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 %}
|
71
resources/twig/accounts/edit.twig
Normal file
71
resources/twig/accounts/edit.twig
Normal 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 %}
|
46
resources/twig/accounts/index.twig
Normal file
46
resources/twig/accounts/index.twig
Normal 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 %}
|
60
resources/twig/accounts/show.twig
Normal file
60
resources/twig/accounts/show.twig
Normal 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 %}
|
57
resources/twig/auth/login.twig
Normal file
57
resources/twig/auth/login.twig
Normal 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">×</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 — 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 %}
|
||||
|
45
resources/twig/auth/password.twig
Normal file
45
resources/twig/auth/password.twig
Normal 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 — 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 %}
|
58
resources/twig/auth/register.twig
Normal file
58
resources/twig/auth/register.twig
Normal 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 — 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 %}
|
69
resources/twig/bills/create.twig
Normal file
69
resources/twig/bills/create.twig
Normal 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 %}
|
32
resources/twig/bills/delete.twig
Normal file
32
resources/twig/bills/delete.twig
Normal 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 %}
|
66
resources/twig/bills/edit.twig
Normal file
66
resources/twig/bills/edit.twig
Normal 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 %}
|
27
resources/twig/bills/index.twig
Normal file
27
resources/twig/bills/index.twig
Normal 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 %}
|
113
resources/twig/bills/show.twig
Normal file
113
resources/twig/bills/show.twig
Normal 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 %}
|
45
resources/twig/budgets/create.twig
Normal file
45
resources/twig/budgets/create.twig
Normal 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 %}
|
43
resources/twig/budgets/delete.twig
Normal file
43
resources/twig/budgets/delete.twig
Normal 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 %}
|
49
resources/twig/budgets/edit.twig
Normal file
49
resources/twig/budgets/edit.twig
Normal 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 %}
|
22
resources/twig/budgets/income.twig
Normal file
22
resources/twig/budgets/income.twig
Normal 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">×</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>
|
192
resources/twig/budgets/index.twig
Normal file
192
resources/twig/budgets/index.twig
Normal 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 %}
|
17
resources/twig/budgets/noBudget.twig
Normal file
17
resources/twig/budgets/noBudget.twig
Normal 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 %}
|
107
resources/twig/budgets/show.twig
Normal file
107
resources/twig/budgets/show.twig
Normal 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 %}
|
45
resources/twig/categories/create.twig
Normal file
45
resources/twig/categories/create.twig
Normal 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 %}
|
||||
|
33
resources/twig/categories/delete.twig
Normal file
33
resources/twig/categories/delete.twig
Normal 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 %}
|
44
resources/twig/categories/edit.twig
Normal file
44
resources/twig/categories/edit.twig
Normal 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 %}
|
40
resources/twig/categories/index.twig
Normal file
40
resources/twig/categories/index.twig
Normal 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 %}
|
18
resources/twig/categories/noCategory.twig
Normal file
18
resources/twig/categories/noCategory.twig
Normal 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 %}
|
54
resources/twig/categories/show.twig
Normal file
54
resources/twig/categories/show.twig
Normal 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 %}
|
44
resources/twig/currency/create.twig
Normal file
44
resources/twig/currency/create.twig
Normal 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 %}
|
26
resources/twig/currency/delete.twig
Normal file
26
resources/twig/currency/delete.twig
Normal 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 %}
|
45
resources/twig/currency/edit.twig
Normal file
45
resources/twig/currency/edit.twig
Normal 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 %}
|
49
resources/twig/currency/index.twig
Normal file
49
resources/twig/currency/index.twig
Normal 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> </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 %}
|
1
resources/twig/emails/password.twig
Normal file
1
resources/twig/emails/password.twig
Normal file
@ -0,0 +1 @@
|
||||
Click here to reset your password: {{ url('password/reset/' . token) }}
|
5
resources/twig/emails/registered.twig
Normal file
5
resources/twig/emails/registered.twig
Normal 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
18
resources/twig/error.twig
Normal 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 %}
|
41
resources/twig/errors/503.twig
Normal file
41
resources/twig/errors/503.twig
Normal 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>
|
23
resources/twig/form/amount.twig
Normal file
23
resources/twig/form/amount.twig
Normal 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>
|
22
resources/twig/form/balance.twig
Normal file
22
resources/twig/form/balance.twig
Normal 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>
|
11
resources/twig/form/checkbox.twig
Normal file
11
resources/twig/form/checkbox.twig
Normal 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>
|
8
resources/twig/form/date.twig
Normal file
8
resources/twig/form/date.twig
Normal 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>
|
4
resources/twig/form/feedback.twig
Normal file
4
resources/twig/form/feedback.twig
Normal 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 %}
|
3
resources/twig/form/help.twig
Normal file
3
resources/twig/form/help.twig
Normal file
@ -0,0 +1,3 @@
|
||||
{% if options.helpText %}
|
||||
<p class="help-block">{{ options.helpText }}</p>
|
||||
{% endif %}
|
9
resources/twig/form/integer.twig
Normal file
9
resources/twig/form/integer.twig
Normal 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>
|
14
resources/twig/form/location.twig
Normal file
14
resources/twig/form/location.twig
Normal 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>
|
16
resources/twig/form/multiRadio.twig
Normal file
16
resources/twig/form/multiRadio.twig
Normal 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>
|
30
resources/twig/form/options.twig
Normal file
30
resources/twig/form/options.twig
Normal 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 %}
|
9
resources/twig/form/select.twig
Normal file
9
resources/twig/form/select.twig
Normal 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>
|
7
resources/twig/form/tags.twig
Normal file
7
resources/twig/form/tags.twig
Normal 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>
|
7
resources/twig/form/text.twig
Normal file
7
resources/twig/form/text.twig
Normal 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>
|
7
resources/twig/form/textarea.twig
Normal file
7
resources/twig/form/textarea.twig
Normal 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
212
resources/twig/index.twig
Normal 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 %}
|
168
resources/twig/layout/default.twig
Normal file
168
resources/twig/layout/default.twig
Normal 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">×</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>
|
62
resources/twig/layout/guest.twig
Normal file
62
resources/twig/layout/guest.twig
Normal 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>
|
59
resources/twig/list/accounts.twig
Normal file
59
resources/twig/list/accounts.twig
Normal file
@ -0,0 +1,59 @@
|
||||
<table class="table table-striped table-bordered sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-defaultsort="disabled"> </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>
|
78
resources/twig/list/bills.twig
Normal file
78
resources/twig/list/bills.twig
Normal file
@ -0,0 +1,78 @@
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<th> </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> </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>
|
38
resources/twig/list/categories.twig
Normal file
38
resources/twig/list/categories.twig
Normal file
@ -0,0 +1,38 @@
|
||||
<table class="table table-striped table-bordered sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-defaultsort="disabled"> </th>
|
||||
<th>Name</th>
|
||||
<th>Last activity</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><a href="{{ route('categories.noCategory') }}"><em>Without a category</em></a></td>
|
||||
<td> </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>
|
37
resources/twig/list/journals-tiny.twig
Normal file
37
resources/twig/list/journals-tiny.twig
Normal 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>
|
113
resources/twig/list/journals.twig
Normal file
113
resources/twig/list/journals.twig
Normal file
@ -0,0 +1,113 @@
|
||||
{{ journals.render|raw }}
|
||||
|
||||
<table class="table table-striped table-bordered sortable-table">
|
||||
<tr class="ignore">
|
||||
<th colspan="2"> </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> </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 }}
|
33
resources/twig/list/piggy-bank-events.twig
Normal file
33
resources/twig/list/piggy-bank-events.twig
Normal 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>
|
56
resources/twig/list/piggy-banks.twig
Normal file
56
resources/twig/list/piggy-banks.twig
Normal 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>
|
45
resources/twig/list/reminders.twig
Normal file
45
resources/twig/list/reminders.twig
Normal 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>
|
92
resources/twig/partials/boxes.twig
Normal file
92
resources/twig/partials/boxes.twig
Normal 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 -->
|
27
resources/twig/partials/flashes.twig
Normal file
27
resources/twig/partials/flashes.twig
Normal 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">×</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">×</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">×</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">×</span><span class="sr-only">Close</span></button>
|
||||
<strong>Error!</strong> {{Session.get('error')}}
|
||||
</div>
|
||||
{% endif %}
|
182
resources/twig/partials/menu.twig
Normal file
182
resources/twig/partials/menu.twig
Normal 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> </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>
|
27
resources/twig/piggy-banks/add.twig
Normal file
27
resources/twig/piggy-banks/add.twig
Normal 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">×</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>
|
||||
|
57
resources/twig/piggy-banks/create.twig
Normal file
57
resources/twig/piggy-banks/create.twig
Normal 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 %}
|
26
resources/twig/piggy-banks/delete.twig
Normal file
26
resources/twig/piggy-banks/delete.twig
Normal 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 %}
|
61
resources/twig/piggy-banks/edit.twig
Normal file
61
resources/twig/piggy-banks/edit.twig
Normal 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 %}
|
62
resources/twig/piggy-banks/index.twig
Normal file
62
resources/twig/piggy-banks/index.twig
Normal 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 %}
|
26
resources/twig/piggy-banks/remove.twig
Normal file
26
resources/twig/piggy-banks/remove.twig
Normal 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">×</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>
|
120
resources/twig/piggy-banks/show.twig
Normal file
120
resources/twig/piggy-banks/show.twig
Normal 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 %}
|
102
resources/twig/preferences/index.twig
Normal file
102
resources/twig/preferences/index.twig
Normal 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 %}
|
55
resources/twig/profile/change-password.twig
Normal file
55
resources/twig/profile/change-password.twig
Normal 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 %}
|
49
resources/twig/profile/delete-account.twig
Normal file
49
resources/twig/profile/delete-account.twig
Normal 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 %}
|
19
resources/twig/profile/index.twig
Normal file
19
resources/twig/profile/index.twig
Normal 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 %}
|
37
resources/twig/reminders/index.twig
Normal file
37
resources/twig/reminders/index.twig
Normal 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 %}
|
40
resources/twig/reminders/show.twig
Normal file
40
resources/twig/reminders/show.twig
Normal 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 %}
|
159
resources/twig/reports/budget.twig
Normal file
159
resources/twig/reports/budget.twig
Normal 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"> </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"> </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"> </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"> </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 %}
|
74
resources/twig/reports/index.twig
Normal file
74
resources/twig/reports/index.twig
Normal 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 %}
|
257
resources/twig/reports/month.twig
Normal file
257
resources/twig/reports/month.twig
Normal 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
Loading…
Reference in New Issue
Block a user