Stuff for categories.

This commit is contained in:
James Cole 2015-02-22 16:19:32 +01:00
parent b44e69e09b
commit 5a0a28a04c
19 changed files with 550 additions and 23 deletions

View File

@ -54,7 +54,7 @@ class AccountController extends Controller
{
$subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
return View::make('accounts.delete', compact('account', 'subTitle'));
return view('accounts.delete', compact('account', 'subTitle'));
}
/**
@ -134,7 +134,7 @@ class AccountController extends Controller
$journals = $repository->getJournals($account, $page, $range);
$subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
return View::make('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle'));
return view('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle'));
}
/**

View File

@ -49,7 +49,7 @@ class BudgetController extends Controller
*/
public function create()
{
return View::make('budgets.create')->with('subTitle', 'Create a new budget');
return view('budgets.create')->with('subTitle', 'Create a new budget');
}
/**
@ -61,7 +61,7 @@ class BudgetController extends Controller
{
$subTitle = 'Delete budget' . e($budget->name) . '"';
return View::make('budgets.delete', compact('budget', 'subTitle'));
return view('budgets.delete', compact('budget', 'subTitle'));
}
/**
@ -89,7 +89,7 @@ class BudgetController extends Controller
{
$subTitle = 'Edit budget "' . e($budget->name) . '"';
return View::make('budgets.edit', compact('budget', 'subTitle'));
return view('budgets.edit', compact('budget', 'subTitle'));
}
@ -117,7 +117,7 @@ class BudgetController extends Controller
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
return View::make('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
return view('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
}
/**
@ -137,7 +137,7 @@ class BudgetController extends Controller
->get(['transaction_journals.*']);
$subTitle = 'Transactions without a budget in ' . $start->format('F Y');
return View::make('budgets.noBudget', compact('list', 'subTitle'));
return view('budgets.noBudget', compact('list', 'subTitle'));
}
/**
@ -176,7 +176,7 @@ class BudgetController extends Controller
public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository)
{
if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) {
return View::make('error')->with('message', 'Invalid selection.');
return view('error')->with('message', 'Invalid selection.');
}
$hideBudget = true; // used in transaction list.
@ -184,7 +184,7 @@ class BudgetController extends Controller
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
}
/**
@ -216,7 +216,7 @@ class BudgetController extends Controller
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$budgetAmount = Preferences::get('budgetIncomeTotal' . $date, 1000);
return View::make('budgets.income')->with('amount', $budgetAmount);
return view('budgets.income')->with('amount', $budgetAmount);
}
}

View File

@ -0,0 +1,127 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\CategoryFormRequest;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use Redirect;
use Session;
use View;
/**
* Class CategoryController
*
* @package FireflyIII\Http\Controllers
*/
class CategoryController extends Controller
{
public function __construct()
{
View::share('title', 'Categories');
View::share('mainTitleIcon', 'fa-bar-chart');
}
/**
* @return $this
*/
public function create()
{
return view('categories.create')->with('subTitle', 'Create a new category');
}
/**
* @param Category $category
*
* @return \Illuminate\View\View
*/
public function delete(Category $category)
{
$subTitle = 'Delete category' . e($category->name) . '"';
return view('categories.delete', compact('category', 'subTitle'));
}
/**
* @param Category $category
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Category $category, CategoryRepositoryInterface $repository)
{
$name = $category->name;
$repository->destroy($category);
Session::flash('success', 'The category "' . e($name) . '" was deleted.');
return Redirect::route('categories.index');
}
/**
* @param Category $category
*
* @return $this
*/
public function edit(Category $category)
{
$subTitle = 'Edit category "' . e($category->name) . '"';
return view('categories.edit', compact('category', 'subTitle'));
}
/**
* @return $this
*/
public function index()
{
$categories = Auth::user()->categories()->get();
return view('categories.index', compact('categories'));
}
/**
* @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository
*
* @return mixed
*/
public function store(CategoryFormRequest $request, CategoryRepositoryInterface $repository)
{
$categoryData = [
'name' => $request->input('name'),
'user' => Auth::user()->id,
];
$category = $repository->store($categoryData);
Session::flash('success', 'New category "' . $category->name . '" stored!');
return Redirect::route('categories.index');
}
/**
* @param Category $category
* @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Category $category, CategoryFormRequest $request, CategoryRepositoryInterface $repository)
{
$categoryData = [
'name' => $request->input('name'),
];
$repository->update($category, $categoryData);
Session::flash('success', 'Category "' . $category->name . '" updated.');
return Redirect::route('categories.index');
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace FireflyIII\Http\Requests;
use Auth;
use FireflyIII\Models\Category;
use Input;
/**
* Class CategoryFormRequest
*
* @package FireflyIII\Http\Requests
*/
class CategoryFormRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
$nameRule = 'required|between:1,100|uniqueForUser:categories,name';
if (Category::find(Input::get('id'))) {
$nameRule = 'required|between:1,100';
}
return [
'name' => $nameRule,
];
}
}

View File

@ -3,6 +3,7 @@ use Carbon\Carbon;
use DaveJamesMiller\Breadcrumbs\Generator;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\Category;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
/*

View File

@ -1,7 +1,8 @@
<?php
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
@ -10,8 +11,7 @@ Route::bind(
'account',
function ($value, $route) {
if (Auth::check()) {
$account = Account::
leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
$account = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.editable', 1)
->where('accounts.id', $value)
->where('user_id', Auth::user()->id)
@ -27,8 +27,7 @@ Route::bind(
Route::bind(
'bill', function ($value, $route) {
if (Auth::check()) {
return Bill::
where('id', $value)->where('user_id', Auth::user()->id)->first();
return Bill::where('id', $value)->where('user_id', Auth::user()->id)->first();
}
return null;
@ -38,8 +37,7 @@ Route::bind(
Route::bind(
'budget', function ($value, $route) {
if (Auth::check()) {
return Budget::
where('id', $value)->where('user_id', Auth::user()->id)->first();
return Budget::where('id', $value)->where('user_id', Auth::user()->id)->first();
}
return null;
@ -60,6 +58,16 @@ Route::bind(
}
);
Route::bind(
'category', function ($value, $route) {
if (Auth::check()) {
return Category::where('id', $value)->where('user_id', Auth::user()->id)->first();
}
return null;
}
);
/**
* Home Controller
*/
@ -90,7 +98,7 @@ Route::group(
//Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching.
Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']);
//Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']);
// Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
// Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']);
/**
@ -113,11 +121,14 @@ Route::group(
* Category Controller
*/
Route::get('/categories', ['uses' => 'CategoryController@index', 'as' => 'categories.index']);
//Route::get('/categories/create', ['uses' => 'CategoryController@create', 'as' => 'categories.create']);
//Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']);
//Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']);
Route::get('/categories/create', ['uses' => 'CategoryController@create', 'as' => 'categories.create']);
Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']);
Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']);
Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']);
//Route::get('/categories/list/noCategory', ['uses' => 'CategoryController@noCategory', 'as' => 'categories.noCategory']);
Route::get('/categories/list/noCategory', ['uses' => 'CategoryController@noCategory', 'as' => 'categories.noCategory']);
Route::post('/categories/store', ['uses' => 'CategoryController@store', 'as' => 'categories.store']);
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']);
/**
* Currency Controller

View File

@ -12,6 +12,8 @@ class Category extends Model
{
use SoftDeletes;
protected $fillable = ['user_id', 'name'];
/**
* @return array
*/

View File

@ -59,7 +59,9 @@ class FireflyServiceProvider extends ServiceProvider
// preferences
$this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository');
$this->app->bind('FireflyIII\Repositories\Budget\BudgetRepositoryInterface', 'FireflyIII\Repositories\Budget\BudgetRepository');
$this->app->bind('FireflyIII\Repositories\Category\CategoryRepositoryInterface', 'FireflyIII\Repositories\Category\CategoryRepository');
$this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository');
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace FireflyIII\Repositories\Category;
use FireflyIII\Models\Category;
/**
* Class CategoryRepository
*
* @package FireflyIII\Repositories\Category
*/
class CategoryRepository implements CategoryRepositoryInterface
{
/**
* @param Category $category
*
* @return boolean
*/
public function destroy(Category $category)
{
$category->delete();
return true;
}
/**
* @param array $data
*
* @return Category
*/
public function store(array $data)
{
$newCategory = new Category(
[
'user_id' => $data['user'],
'name' => $data['name'],
]
);
$newCategory->save();
return $newCategory;
}
/**
* @param Category $category
* @param array $data
*
* @return Category
*/
public function update(Category $category, array $data)
{
// update the account:
$category->name = $data['name'];
$category->save();
return $category;
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace FireflyIII\Repositories\Category;
use FireflyIII\Models\Category;
/**
* Interface CategoryRepositoryInterface
*
* @package FireflyIII\Repositories\Category
*/
interface CategoryRepositoryInterface
{
/**
* @param Category $category
*
* @return boolean
*/
public function destroy(Category $category);
/**
* @param array $data
*
* @return Category
*/
public function store(array $data);
/**
* @param Category $category
* @param array $data
*
* @return Category
*/
public function update(Category $category, array $data);
}

9
public/js/categories.js Normal file
View File

@ -0,0 +1,9 @@
$(function () {
if (typeof componentID !== 'undefined' && typeof repetitionID === 'undefined') {
googleColumnChart('chart/category/' + componentID + '/spending/' + year, 'componentOverview');
}
});

View File

@ -0,0 +1,41 @@
@extends('layouts.default')
@section('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>
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new category
</button>
</p>
</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>
{!! Form::close() !!}
@stop

View File

@ -0,0 +1,27 @@
@extends('layouts.default')
@section('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?
</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::close()!!}
@stop

View File

@ -0,0 +1,39 @@
@extends('layouts.default')
@section('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>
<p>
<button type="submit" class="btn btn-lg btn-success">
Update category
</button>
</p>
</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>
{!! Form::close() !!}
@stop

View File

@ -0,0 +1,39 @@
@extends('layouts.default')
@section('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')
</div>
</div>
</div>
@stop
@section('scripts')
<script type="text/javascript">
var currencyCode = '{{Amount::getCurrencyCode()}}';
</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>
@stop

View File

@ -0,0 +1,24 @@
@extends('layouts.default')
@section('content')
{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }}
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-12 ">
<!-- time based navigation -->
@include('partials.date_nav')
</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">
{{{$subTitle}}}
</div>
<div class="panel-body">
@include('list.journals-full',['journals' => $list])
</div>
</div>
</div>
</div>
@stop

View File

@ -0,0 +1,42 @@
@extends('layouts.default')
@section('content')
{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $category) }}
<div class="row">
<div class="col-lg-9 col-md-9 col-sm-7">
<div class="panel panel-default">
<div class="panel-heading">
Overview
</div>
<div class="panel-body">
<div id="componentOverview"></div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
Transactions
</div>
<div class="panel-body">
@include('list.journals-full')
</div>
</div>
</div>
<div class="col-lg-3 col-md-3 col-sm-5">
BLa bla something here.
</div>
</div>
@stop
@section('scripts')
<script type="text/javascript">
var componentID = {{$category->id}};
var year = {{Session::get('start',\Carbon\Carbon::now()->startOfMonth())->format('Y')}};
var currencyCode = '{{Amount::getCurrencyCode()}}';
</script>
<!-- load the libraries and scripts necessary for Google Charts: -->
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
{{HTML::script('assets/javascript/firefly/gcharts.options.js')}}
{{HTML::script('assets/javascript/firefly/gcharts.js')}}
{{HTML::script('assets/javascript/firefly/categories.js')}}
@stop

View File

@ -0,0 +1,29 @@
<table class="table table-striped table-bordered">
<tr>
<th>&nbsp;</th>
<th>Name</th>
<th>Last activity</th>
</tr>
<tr>
<td>&nbsp;</td>
<td><a href="{{route('categories.noCategory')}}"><em>Without a category</em></a></td>
<td>&nbsp;</td>
</tr>
@foreach($categories as $category)
<tr>
<td>
<div class="btn-group btn-group-xs">
<a href="{{route('categories.edit',$category->id)}}" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span></a>
<a href="{{route('categories.delete',$category->id)}}" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-trash"></span></a>
</div>
</td>
<td>
<a href="{{route('categories.show',$category->id)}}" title="{{{$category->name}}}">{{{$category->name}}}</a>
</td>
<td>
<em>Never</em>
</td>
</tr>
@endforeach
</table>

View File

@ -239,5 +239,4 @@ class BudgetControllerCest
$I->wantTo('update my monthly income');
$I->see('Update (expected) income for ');
}
}