Merge branch 'release/3.1.1'

This commit is contained in:
Sander Dorigo 2014-10-12 07:39:27 +02:00
commit 6a6d889983
8 changed files with 417 additions and 199 deletions

View File

@ -2,7 +2,7 @@
use Carbon\Carbon; use Carbon\Carbon;
return [ return [
'index_periods' => ['1D', '1W', '1M', '3M', '6M', 'custom'], 'index_periods' => ['1D', '1W', '1M', '3M', '6M','1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], 'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'piggybank_periods' => ['day', 'week', 'month', 'year'], 'piggybank_periods' => ['day', 'week', 'month', 'year'],
'periods_to_text' => [ 'periods_to_text' => [
@ -21,6 +21,14 @@ return [
'6M' => 'half year', '6M' => 'half year',
'custom' => '(custom)' 'custom' => '(custom)'
], ],
'range_to_name' => [
'1D' => 'one day',
'1W' => 'one week',
'1M' => 'one month',
'3M' => 'three months',
'6M' => 'six months',
'1Y' => 'one year',
],
'range_to_repeat_freq' => [ 'range_to_repeat_freq' => [
'1D' => 'weekly', '1D' => 'weekly',
'1W' => 'weekly', '1W' => 'weekly',

View File

@ -17,10 +17,10 @@ class HomeController extends BaseController
protected $_reminders; protected $_reminders;
/** /**
* @param ARI $accounts * @param ARI $accounts
* @param PHI $preferences * @param PHI $preferences
* @param TJRI $journal * @param TJRI $journal
* @param RRI $reminders * @param RRI $reminders
*/ */
public function __construct(ARI $accounts, PHI $preferences, TJRI $journal, RRI $reminders) public function __construct(ARI $accounts, PHI $preferences, TJRI $journal, RRI $reminders)
{ {
@ -30,8 +30,9 @@ class HomeController extends BaseController
$this->_reminders = $reminders; $this->_reminders = $reminders;
} }
public function jobDev() { public function jobDev()
$fullName = storage_path().DIRECTORY_SEPARATOR.'firefly-export-2014-07-23.json'; {
$fullName = storage_path() . DIRECTORY_SEPARATOR . 'firefly-export-2014-07-23.json';
\Log::notice('Pushed start job.'); \Log::notice('Pushed start job.');
Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => 1]); Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => 1]);
@ -40,7 +41,8 @@ class HomeController extends BaseController
/* /*
* *
*/ */
public function sessionPrev() { public function sessionPrev()
{
/** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
$toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
$toolkit->prev(); $toolkit->prev();
@ -51,7 +53,8 @@ class HomeController extends BaseController
/* /*
* *
*/ */
public function sessionNext() { public function sessionNext()
{
/** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */ /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
$toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface'); $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
$toolkit->next(); $toolkit->next();
@ -59,6 +62,19 @@ class HomeController extends BaseController
//return Redirect::route('index'); //return Redirect::route('index');
} }
public function rangeJump($range)
{
$viewRange = $this->_preferences->get('viewRange', '1M');
$valid = ['1D', '1W', '1M', '3M', '6M', '1Y',];
if(in_array($range,$valid)) {
$this->_preferences->set('viewRange', $range);
Session::forget('range');
}
return Redirect::back();
}
/** /**
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
*/ */
@ -102,6 +118,6 @@ class HomeController extends BaseController
// build the home screen: // build the home screen:
return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly') return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly')
->with('subTitle', 'What\'s playing?')->with('mainTitleIcon','fa-fire'); ->with('subTitle', 'What\'s playing?')->with('mainTitleIcon', 'fa-fire');
} }
} }

View File

@ -19,7 +19,6 @@ class JsonController extends BaseController
$this->helper = $helper; $this->helper = $helper;
} }
/** /**
@ -97,11 +96,32 @@ class JsonController extends BaseController
return Response::json($resultSet); return Response::json($resultSet);
} }
/**
*
*/
public function recurringjournals(RecurringTransaction $recurringTransaction)
{
$parameters = $this->helper->dataTableParameters();
$parameters['transactionTypes'] = ['Withdrawal'];
$parameters['amount'] = 'negative';
$query = $this->helper->journalQuery($parameters);
$query->where('recurring_transaction_id', $recurringTransaction->id);
$resultSet = $this->helper->journalDataset($parameters, $query);
/*
* Build return data:
*/
return Response::json($resultSet);
}
public function recurring() public function recurring()
{ {
$parameters = $this->helper->dataTableParameters(); $parameters = $this->helper->dataTableParameters();
$query = $this->helper->recurringTransactionsQuery($parameters); $query = $this->helper->recurringTransactionsQuery($parameters);
$resultSet = $this->helper->recurringTransactionsDataset($parameters, $query); $resultSet = $this->helper->recurringTransactionsDataset($parameters, $query);
return Response::json($resultSet); return Response::json($resultSet);
} }

View File

@ -84,22 +84,23 @@ class Toolkit implements ToolkitInterface
/** /**
* *
*/ */
public function checkImportJobs() { public function checkImportJobs()
{
/* /*
* Get all jobs. * Get all jobs.
*/ */
/** @var \Importmap $importJob */ /** @var \Importmap $importJob */
$importJob = \Importmap::where('user_id',\Auth::user()->id) $importJob = \Importmap::where('user_id', \Auth::user()->id)
->where('totaljobs','>',\DB::Raw('`jobsdone`')) ->where('totaljobs', '>', \DB::Raw('`jobsdone`'))
->orderBy('created_at','DESC') ->orderBy('created_at', 'DESC')
->first(); ->first();
if(!is_null($importJob)) { if (!is_null($importJob)) {
$diff = intval($importJob->totaljobs) - intval($importJob->jobsdone); $diff = intval($importJob->totaljobs) - intval($importJob->jobsdone);
$date = new Carbon; $date = new Carbon;
$today = new Carbon; $today = new Carbon;
$date->addSeconds($diff); $date->addSeconds($diff);
\Session::put('job_pct',$importJob->pct()); \Session::put('job_pct', $importJob->pct());
\Session::put('job_text',$date->diffForHumans()); \Session::put('job_text', $date->diffForHumans());
} else { } else {
\Session::forget('job_pct'); \Session::forget('job_pct');
\Session::forget('job_text'); \Session::forget('job_text');
@ -134,7 +135,6 @@ class Toolkit implements ToolkitInterface
*/ */
protected function _updateStartDate($range, Carbon $start) protected function _updateStartDate($range, Carbon $start)
{ {
$today = new Carbon;
switch ($range) { switch ($range) {
case '1D': case '1D':
$start->startOfDay(); $start->startOfDay();
@ -149,12 +149,15 @@ class Toolkit implements ToolkitInterface
$start->firstOfQuarter(); $start->firstOfQuarter();
break; break;
case '6M': case '6M':
if (intval($today->format('m')) >= 7) { if (intval($start->format('m')) >= 7) {
$start->startOfYear()->addMonths(6); $start->startOfYear()->addMonths(6);
} else { } else {
$start->startOfYear(); $start->startOfYear();
} }
break; break;
case '1Y':
$start->startOfYear();
break;
} }
return $start; return $start;
@ -170,33 +173,32 @@ class Toolkit implements ToolkitInterface
*/ */
protected function _updateEndDate($range, Carbon $start) protected function _updateEndDate($range, Carbon $start)
{ {
$end = clone $start;
switch ($range) { switch ($range) {
case '1D': case '1D':
$end = clone $start;
$end->endOfDay(); $end->endOfDay();
break; break;
case '1W': case '1W':
$end = clone $start;
$end->endOfWeek(); $end->endOfWeek();
break; break;
case '1M': case '1M':
$end = clone $start;
$end->endOfMonth(); $end->endOfMonth();
break; break;
case '3M': case '3M':
$end = clone $start;
$end->lastOfQuarter(); $end->lastOfQuarter();
break; break;
case '6M': case '6M':
$end = clone $start;
if (intval($start->format('m')) >= 7) { if (intval($start->format('m')) >= 7) {
$end->endOfYear(); $end->endOfYear();
} else { } else {
$end->startOfYear()->addMonths(6); $end->startOfYear()->addMonths(6);
} }
break; break;
default: case '1Y':
throw new FireflyException('Nothing happened with $end!'); $end->endOfYear();
break;
default:
throw new FireflyException('_updateEndDate cannot handle $range ' . $range);
break; break;
} }
@ -209,9 +211,30 @@ class Toolkit implements ToolkitInterface
default: default:
throw new FireflyException('No _periodName() for range "' . $range . '"'); throw new FireflyException('No _periodName() for range "' . $range . '"');
break; break;
case '1D':
return $date->format('jS F Y');
break;
case '1W':
return 'week ' . $date->format('W, Y');
break;
case '1M': case '1M':
return $date->format('F Y'); return $date->format('F Y');
break; break;
case '3M':
$month = intval($date->format('m'));
return 'Q' . ceil(($month / 12) * 4) . ' ' . $date->format('Y');
break;
case '6M':
$month = intval($date->format('m'));
$half = ceil(($month / 12) * 2);
$halfName = $half == 1 ? 'first' : 'second';
return $halfName . ' half of ' . $date->format('d-m-Y');
break;
case '1Y':
return $date->format('Y');
break;
} }
} }
@ -231,12 +254,19 @@ class Toolkit implements ToolkitInterface
$date->firstOfQuarter()->subMonths(3)->firstOfQuarter(); $date->firstOfQuarter()->subMonths(3)->firstOfQuarter();
break; break;
case '6M': case '6M':
if (intval($date->format('m')) >= 7) { $month = intval($date->format('m'));
$date->startOfYear(); if ($month <= 6) {
} else {
$date->startOfYear()->subMonths(6); $date->startOfYear()->subMonths(6);
} else {
$date->startOfYear();
} }
break; break;
case '1Y':
$date->startOfYear()->subYear();
break;
default:
throw new FireflyException('Cannot do _previous() on ' . $range);
break;
} }
return $date; return $date;
} }
@ -254,7 +284,7 @@ class Toolkit implements ToolkitInterface
$date->endOfMonth()->addDay()->startOfMonth(); $date->endOfMonth()->addDay()->startOfMonth();
break; break;
case '3M': case '3M':
$date->lastOfQuarter(); $date->lastOfQuarter()->addDay();
break; break;
case '6M': case '6M':
if (intval($date->format('m')) >= 7) { if (intval($date->format('m')) >= 7) {
@ -263,6 +293,12 @@ class Toolkit implements ToolkitInterface
$date->startOfYear()->addMonths(6); $date->startOfYear()->addMonths(6);
} }
break; break;
case '1Y':
$date->startOfYear()->addYear();
break;
default:
throw new FireflyException('Cannot do _next() on ' . $range);
break;
} }
return $date; return $date;
} }
@ -311,7 +347,7 @@ class Toolkit implements ToolkitInterface
* Takes any collection and tries to make a sensible select list compatible array of it. * Takes any collection and tries to make a sensible select list compatible array of it.
* *
* @param Collection $set * @param Collection $set
* @param null $titleField * @param null $titleField
* *
* @return mixed * @return mixed
*/ */

View File

@ -133,6 +133,7 @@ Route::group(['before' => 'auth'], function () {
// some date routes: // some date routes:
Route::get('/prev',['uses' => 'HomeController@sessionPrev', 'as' => 'sessionPrev']); Route::get('/prev',['uses' => 'HomeController@sessionPrev', 'as' => 'sessionPrev']);
Route::get('/next',['uses' => 'HomeController@sessionNext', 'as' => 'sessionNext']); Route::get('/next',['uses' => 'HomeController@sessionNext', 'as' => 'sessionNext']);
Route::get('/jump/{range}',['uses' => 'HomeController@rangeJump','as' => 'rangeJump']);
// account controller: // account controller:
Route::get('/accounts', ['uses' => 'AccountController@index', 'as' => 'accounts.index']); Route::get('/accounts', ['uses' => 'AccountController@index', 'as' => 'accounts.index']);
@ -187,6 +188,7 @@ Route::group(['before' => 'auth'], function () {
Route::get('/json/revenue', ['uses' => 'JsonController@revenue', 'as' => 'json.revenue']); Route::get('/json/revenue', ['uses' => 'JsonController@revenue', 'as' => 'json.revenue']);
Route::get('/json/transfers', ['uses' => 'JsonController@transfers', 'as' => 'json.transfers']); Route::get('/json/transfers', ['uses' => 'JsonController@transfers', 'as' => 'json.transfers']);
Route::get('/json/recurring', ['uses' => 'JsonController@recurring', 'as' => 'json.recurring']); Route::get('/json/recurring', ['uses' => 'JsonController@recurring', 'as' => 'json.recurring']);
Route::get('/json/recurringjournals/{recurring}', ['uses' => 'JsonController@recurringjournals', 'as' => 'json.recurringjournals']);
// limit controller: // limit controller:
Route::get('/budgets/limits/create/{budget?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']); Route::get('/budgets/limits/create/{budget?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']);

View File

@ -2,6 +2,22 @@
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-clock-o fa-fw"></i> <i class="fa fa-clock-o fa-fw"></i>
{{{\Session::get('period')}}} {{{\Session::get('period')}}}
<!-- ACTIONS MENU -->
<div class="pull-right">
<div class="btn-group">
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown">
Range
<span class="caret"></span>
</button>
<ul class="dropdown-menu pull-right" role="menu">
@foreach(Config::get('firefly.range_to_name') as $name => $label)
<li><a href="{{route('rangeJump',$name)}}"><i class="fa fa-calendar fa-fw"></i> {{{ucfirst($label)}}}</a></li>
@endforeach
</ul>
</div>
</div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div class="btn-group btn-group-sm btn-group-justified"> <div class="btn-group btn-group-sm btn-group-justified">

View File

@ -1,68 +1,96 @@
@extends('layouts.default') @extends('layouts.default')
@section('content') @section('content')
<div class="row"> <div class="row">
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-6 col-sm-6 col-md-12">
<p class="lead">Use recurring transactions to track repeated withdrawals</p> <div class="panel panel-default">
<p> <div class="panel-heading">
<div class="btn-group btn-group-xs"> <i class="fa fa-rotate-right"></i> {{{$recurring->name}}}
<a href="{{route('recurring.edit',$recurring->id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></span> edit</a>
<a href="{{route('recurring.delete',$recurring->id)}}" class="btn btn-danger"><span class="glyphicon glyphicon-trash"></span> delete</a> @if($recurring->active)
</div> <span class="glyphicon glyphicon-ok" title="Active"></span>
</p> @else
<span class="glyphicon glyphicon-remove" title="Inactive"></span>
@endif
@if($recurring->automatch)
<span class="glyphicon glyphicon-ok" title="Automatically matched by Firefly"></span>
@else
<span class="glyphicon glyphicon-remove" title="Not automatically matched by Firefly"></span>
@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('recurring.edit',$recurring->id)}}"><span class="glyphicon glyphicon-pencil"></span> edit</a></li>
<li><a href="{{route('recurring.delete',$recurring->id)}}"><span class="glyphicon glyphicon-trash"></span> delete</a></li>
</ul>
</div>
</div>
</div>
<div class="panel-body">
<table class="table">
<tr>
<td colspan="2">
Matching on
@foreach(explode(' ',$recurring->match) as $word)
<span class="label label-info">{{{$word}}}</span>
@endforeach
between {{mf($recurring->amount_min)}} and {{mf($recurring->amount_max)}}.
Repeats {{$recurring->repeat_freq}}.</td>
</tr>
<tr>
<td>Next reminder</td>
<td>TODO TODO</td>
</tr>
</table>
</div>
</div>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-lg-6 col-sm-6 col-md-12"> <div class="col-lg-12 col-sm-12 col-md-12">
<div class="panel panel-default">
<table class="table"> <div class="panel-heading">
<tr> Connected transaction journals
<td>Matches on: </td> </div>
<td> <div class="panel-body">
@foreach(explode(' ',$recurring->match) as $word) <table id="transactionTable" class="table table-striped table-bordered" >
<span class="label label-info">{{{$word}}}</span> <thead>
@endforeach <tr>
</td> <th>Date</th>
</tr> <th>Description</th>
<tr> <th>Amount (&euro;)</th>
<td>Between</td> <th>From</th>
<td> {{mf($recurring->amount_min)}} &ndash; {{mf($recurring->amount_max)}}</td> <th>To</th>
</tr> <th>Budget / category</th>
<tr> <th>ID</th>
<td>Repeats</td> </tr>
<td>{{ucfirst($recurring->repeat_freq)}}</td> </thead>
</tr> </table>
<tr> </div>
<td>Next reminder</td> </div>
<td>{{$recurring->next()->format('d-m-Y')}}</td>
</tr>
<tr>
<td>Will be auto-matched</td>
<td>
@if($recurring->automatch)
<span class="glyphicon glyphicon-ok"></span>
@else
<span class="glyphicon glyphicon-remove"></span>
@endif
</td>
</tr>
<tr>
<td>Is active</td>
<td>
@if($recurring->active)
<span class="glyphicon glyphicon-ok"></span>
@else
<span class="glyphicon glyphicon-remove"></span>
@endif
</td>
</tr>
</table>
<td>
</td>
</tr>
</div> </div>
</div> </div>
@stop
@section('scripts')
<script type="text/javascript">
var URL = '{{route('json.recurringjournals',$recurring->id)}}';
</script>
{{HTML::script('assets/javascript/typeahead/bootstrap3-typeahead.min.js')}}
{{HTML::script('assets/javascript/datatables/jquery.dataTables.min.js')}}
{{HTML::script('assets/javascript/datatables/dataTables.bootstrap.js')}}
{{HTML::script('assets/javascript/firefly/recurring.js')}}
@stop
@section('styles')
{{HTML::style('assets/stylesheets/datatables/dataTables.bootstrap.css')}}
@stop @stop

View File

@ -1,112 +1,204 @@
$(document).ready(function () { $(document).ready(function () {
$('#recurringTable').DataTable( if ($('#recurringTable').length > 0) {
{ $('#recurringTable').DataTable(
serverSide: true,
ajax: URL,
paging: true,
processing: true,
order: [],
"lengthMenu": [[50, 100, 250, -1], [50, 100, 250, "All"]],
columns: [
{ {
name: 'name', serverSide: true,
data: 'name', ajax: URL,
searchable: true, paging: true,
title: 'Name', processing: true,
render: function (data) { order: [],
return '<a href="' + data.url + '" title="' + data.name + '">' + data.name + '</a>'; "lengthMenu": [[50, 100, 250, -1], [50, 100, 250, "All"]],
} columns: [
}, {
{ name: 'name',
name: 'match', data: 'name',
data: 'match', searchable: true,
searchable: true, title: 'Name',
title: 'Matches on', render: function (data) {
render: function (data) { return '<a href="' + data.url + '" title="' + data.name + '">' + data.name + '</a>';
var str = ''; }
for (x in data) { },
str += '<span class="label label-info">' + data[x] + '</span> '; {
} name: 'match',
return str;//return '<a href="' + data.url + '" title="' + data.name + '">' + data.name + '</a>'; data: 'match',
} searchable: true,
}, title: 'Matches on',
{ render: function (data) {
name: 'amount_min', var str = '';
data: 'amount_min', for (x in data) {
searchable: false, str += '<span class="label label-info">' + data[x] + '</span> ';
title: '&rarr;', }
render: function (data) { return str;//return '<a href="' + data.url + '" title="' + data.name + '">' + data.name + '</a>';
return '<span class="text-info">\u20AC ' + data.toFixed(2) + '</span>'; }
} },
}, {
{ name: 'amount_min',
name: 'amount_max', data: 'amount_min',
data: 'amount_max', searchable: false,
searchable: false, title: '&rarr;',
title: '&larr;', render: function (data) {
render: function (data) { return '<span class="text-info">\u20AC ' + data.toFixed(2) + '</span>';
return '<span class="text-info">\u20AC ' + data.toFixed(2) + '</span>'; }
} },
{
name: 'amount_max',
data: 'amount_max',
searchable: false,
title: '&larr;',
render: function (data) {
return '<span class="text-info">\u20AC ' + data.toFixed(2) + '</span>';
}
}, },
{ {
name: 'date', name: 'date',
data: 'date', data: 'date',
title: 'Expected on', title: 'Expected on',
searchable: false searchable: false
}, },
{ {
name: 'active', name: 'active',
data: 'active', data: 'active',
searchable: false, searchable: false,
sortable: false, sortable: false,
render: function(data) { render: function (data) {
if(data == 1) { if (data == 1) {
return '<i class="fa fa-check fa-faw"></i>'; return '<i class="fa fa-check fa-faw"></i>';
} else { } else {
return '<i class="fa fa-remove fa-faw"></i>'; return '<i class="fa fa-remove fa-faw"></i>';
}
},
title: 'Is active?'
},
{
name: 'automatch',
data: 'automatch',
sortable: false,
searchable: false,
render: function (data) {
if (data == 1) {
return '<i class="fa fa-check fa-faw"></i>';
} else {
return '<i class="fa fa-remove fa-faw"></i>';
}
},
title: 'Automatch?'
},
{
name: 'repeat_freq',
data: 'repeat_freq',
searchable: false,
sortable: false,
title: 'Repeat frequency'
},
{
name: 'id',
data: 'id',
searchable: false,
sortable: false,
title: '',
render: function (data, type, full, meta) {
return '<div class="btn-group btn-group-xs">' +
'<a class="btn btn-default btn-xs" href="' + data.edit + '">' +
'<span class="glyphicon glyphicon-pencil"</a>' +
'<a class="btn btn-danger btn-xs" href="' + data.delete + '">' +
'<span class="glyphicon glyphicon-trash"</a>' +
'</a></div>';
}
} }
}, ]
title: 'Is active?'
},
{
name: 'automatch',
data: 'automatch',
sortable: false,
searchable: false,
render: function(data) {
if(data == 1) {
return '<i class="fa fa-check fa-faw"></i>';
} else {
return '<i class="fa fa-remove fa-faw"></i>';
}
},
title: 'Automatch?'
},
{
name: 'repeat_freq',
data: 'repeat_freq',
searchable: false,
sortable: false,
title: 'Repeat frequency'
},
{
name: 'id',
data: 'id',
searchable: false,
sortable: false,
title: '',
render: function (data, type, full, meta) {
return '<div class="btn-group btn-group-xs">' +
'<a class="btn btn-default btn-xs" href="' + data.edit + '">' +
'<span class="glyphicon glyphicon-pencil"</a>' +
'<a class="btn btn-danger btn-xs" href="' + data.delete + '">' +
'<span class="glyphicon glyphicon-trash"</a>' +
'</a></div>';
}
} }
] );
} }
); if ($('#transactionTable').length > 0) {
}); $('#transactionTable').DataTable(
{
serverSide: true,
ajax: URL,
paging: true,
processing: true,
order: [],
"lengthMenu": [[50, 100, 250, -1], [50, 100, 250, "All"]],
columns: [
{
name: 'date',
data: 'date',
searchable: false
},
{
name: 'description',
data: 'description',
render: function (data, type, full, meta) {
icon = 'glyphicon-arrow-left';
return '<span class="glyphicon ' + icon + '"></span> ' +
'<a href="' + data.url + '" title="' + data.description + '">' + data.description + '</a>';
}
},
{
name: 'amount',
data: 'amount',
'title': 'Amount (\u20AC)',
searchable: false,
render: function (data, type, full, meta) {
return '<span class="text-danger">\u20AC ' + data.toFixed(2) + '</span>';
}
},
{
name: 'from',
data: 'from',
searchable: false,
render: function (data, type, full, meta) {
return '<a href="' + data.url + '" title="' + data.name + '">' + data.name + '</a>';
}
},
{
name: 'to',
data: 'to',
searchable: false,
render: function (data, type, full, meta) {
return '<a href="' + data.url + '" title="' + data.name + '">' + data.name + '</a>';
}
},
{
name: 'components',
data: 'components',
searchable: true,
sortable: false,
title: '',
render: function (data, type, full, meta) {
var html = '';
if (data.budget_id > 0) {
html += '<a href="' + data.budget_url + '" title="' + data.budget_name + '"><i class="fa fa-tasks fa-fw"></i></a> ';
}
if (data.category_id > 0) {
html += '<a href="' + data.category_url + '" title="' + data.category_name + '"><i class="fa fa-bar-chart fa-fw"></i></a> ';
}
if (data.recurring_id > 0) {
html += '<a href="' + data.recurring_url + '" title="' + data.recurring_name + '"><i class="fa fa-rotate-right fa-fw"></i></a> ';
}
return html;
}
},
{
name: 'id',
data: 'id',
searchable: false,
sortable: false,
title: '',
render: function (data, type, full, meta) {
return '<div class="btn-group btn-group-xs">' +
'<a class="btn btn-default btn-xs" href="' + data.edit + '">' +
'<span class="glyphicon glyphicon-pencil"</a>' +
'<a class="btn btn-danger btn-xs" href="' + data.delete + '">' +
'<span class="glyphicon glyphicon-trash"</a>' +
'</a></div>';
}
}
]
}
);
}
}
);