mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-11-22 17:06:39 -06:00
First attempt at basic tag functionality.
This commit is contained in:
parent
6081cc399f
commit
e7165a526b
152
app/Http/Controllers/TagController.php
Normal file
152
app/Http/Controllers/TagController.php
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Http\Requests\TagFormRequest;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use View;
|
||||
use URL;
|
||||
use Redirect;
|
||||
|
||||
/**
|
||||
* Class TagController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class TagController extends Controller
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
View::share('title', 'Tags');
|
||||
View::share('mainTitleIcon', 'fa-tags');
|
||||
$tagOptions = [
|
||||
'nothing' => 'Just a regular tag.',
|
||||
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
|
||||
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
|
||||
];
|
||||
View::share('tagOptions', $tagOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$subTitle = 'New tag';
|
||||
$subTitleIcon = 'fa-tag';
|
||||
|
||||
$preFilled = [
|
||||
'tagMode' => 'nothing'
|
||||
];
|
||||
if (!Input::old('tagMode')) {
|
||||
Session::flash('preFilled', $preFilled);
|
||||
}
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (Session::get('tags.create.fromStore') !== true) {
|
||||
Session::put('tags.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('tags.create.fromStore');
|
||||
|
||||
return view('tags.create', compact('subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
public function edit(Tag $tag)
|
||||
{
|
||||
$subTitle = 'Edit tag "' . e($tag->tag) . '"';
|
||||
$subTitleIcon = 'fa-tag';
|
||||
|
||||
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $state
|
||||
*/
|
||||
public function hideTagHelp($state)
|
||||
{
|
||||
|
||||
$state = $state == 'true' ? true : false;
|
||||
Preferences::set('hideTagHelp', $state);
|
||||
|
||||
return Response::json(true);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
/** @var Preference $helpHiddenPref */
|
||||
$helpHiddenPref = Preferences::get('hideTagHelp', false);
|
||||
$title = 'Tags';
|
||||
$mainTitleIcon = 'fa-tags';
|
||||
$helpHidden = $helpHiddenPref->data;
|
||||
$tags = Auth::user()->tags()->get();
|
||||
|
||||
return view('tags.index', compact('title', 'mainTitleIcon', 'helpHidden', 'tags'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Tag $tag
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show(Tag $tag)
|
||||
{
|
||||
$subTitle = $tag->tag;
|
||||
$subTitleIcon = 'fa-tag';
|
||||
|
||||
return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TagFormRequest $request
|
||||
*/
|
||||
public function store(TagFormRequest $request, TagRepositoryInterface $repository)
|
||||
{
|
||||
if (Input::get('setTag') == 'true') {
|
||||
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
|
||||
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
|
||||
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
|
||||
} else {
|
||||
$latitude = null;
|
||||
$longitude = null;
|
||||
$zoomLevel = null;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'tag' => $request->get('tag'),
|
||||
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
|
||||
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : null,
|
||||
'latitude' => $latitude,
|
||||
'longitude' => $longitude,
|
||||
'zoomLevel' => $zoomLevel,
|
||||
'tagMode' => $request->get('tagMode'),
|
||||
];
|
||||
$tag = $repository->store($data);
|
||||
|
||||
Session::flash('success','The tag has been created!');
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('tags.create.fromStore', true);
|
||||
|
||||
return Redirect::route('tags.create')->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('tags.create.url'));
|
||||
|
||||
}
|
||||
}
|
43
app/Http/Requests/TagFormRequest.php
Normal file
43
app/Http/Requests/TagFormRequest.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 27/04/15
|
||||
* Time: 12:50
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
|
||||
/**
|
||||
* Class TagFormRequest
|
||||
*
|
||||
* @package FireflyIII\Http\Requests
|
||||
*/
|
||||
class TagFormRequest extends Request
|
||||
{
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
// Only allow logged in users
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag,TRUE',
|
||||
'description' => 'min:1',
|
||||
'date' => 'date',
|
||||
'latitude' => 'numeric|min:-90|max:90',
|
||||
'longitude' => 'numeric|min:-90|max:90',
|
||||
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
|
||||
];
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
||||
use FireflyIII\Models\Tag;
|
||||
/*
|
||||
* Back home.
|
||||
*/
|
||||
@ -350,3 +350,24 @@ Breadcrumbs::register(
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// tags
|
||||
Breadcrumbs::register(
|
||||
'tags.index', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push('Tags', route('tags.index'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'tags.create', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('tags.index');
|
||||
$breadcrumbs->push('Create tag', route('tags.create'));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'tags.show', function (Generator $breadcrumbs, Tag $tag) {
|
||||
$breadcrumbs->parent('tags.index');
|
||||
$breadcrumbs->push(e($tag->tag), route('tags.show', $tag));
|
||||
}
|
||||
);
|
@ -8,6 +8,7 @@ use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\Tag;
|
||||
|
||||
|
||||
// models
|
||||
@ -124,6 +125,16 @@ Route::bind(
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'tag', function ($value, $route) {
|
||||
if (Auth::check()) {
|
||||
return Tag::where('id', $value)->where('user_id', Auth::user()->id)->first();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Auth\AuthController
|
||||
@ -327,6 +338,22 @@ Route::group(
|
||||
*/
|
||||
Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']);
|
||||
|
||||
/**
|
||||
* Tag Controller
|
||||
*/
|
||||
Route::get('/tags', ['uses' => 'TagController@index', 'as' => 'tags.index']);
|
||||
Route::get('/tags/create', ['uses' => 'TagController@create', 'as' => 'tags.create']);
|
||||
Route::get('/tags/show/{tag}', ['uses' => 'TagController@show', 'as' => 'tags.show']);
|
||||
Route::get('/tags/edit/{tag}', ['uses' => 'TagController@edit', 'as' => 'tags.edit']);
|
||||
Route::get('/tags/delete/{tag}', ['uses' => 'TagController@delete', 'as' => 'tags.delete']);
|
||||
|
||||
Route::post('/tags/store', ['uses' => 'TagController@store', 'as' => 'tags.store']);
|
||||
Route::post('/tags/update/{tag}', ['uses' => 'TagController@update', 'as' => 'tags.update']);
|
||||
Route::post('/tags/destroy/{tag}', ['uses' => 'TagController@destroy', 'as' => 'tags.destroy']);
|
||||
|
||||
Route::post('/tags/hideTagHelp/{state}', ['uses' => 'TagController@hideTagHelp', 'as' => 'tags.hideTagHelp']);
|
||||
|
||||
|
||||
/**
|
||||
* Transaction Controller
|
||||
*/
|
||||
|
77
app/Models/Tag.php
Normal file
77
app/Models/Tag.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Models;
|
||||
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class Tag
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Tag extends Model
|
||||
{
|
||||
|
||||
protected $fillable = ['user_id', 'tag', 'date', 'description', 'longitude', 'latitude','zoomLevel','tagMode'];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'date'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDescriptionAttribute($value)
|
||||
{
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTagAttribute($value)
|
||||
{
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setDescriptionAttribute($value)
|
||||
{
|
||||
$this->attributes['description'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setTagAttribute($value)
|
||||
{
|
||||
$this->attributes['tag'] = Crypt::encrypt($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
}
|
@ -241,4 +241,12 @@ class TransactionJournal extends Model
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function tags()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\Tag');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,6 +63,7 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
$this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
|
||||
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
|
||||
|
||||
|
||||
|
39
app/Repositories/Tag/TagRepository.php
Normal file
39
app/Repositories/Tag/TagRepository.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Tag;
|
||||
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Tag;
|
||||
|
||||
/**
|
||||
* Class TagRepository
|
||||
*
|
||||
* @package FireflyIII\Repositories\Tag
|
||||
*/
|
||||
class TagRepository implements TagRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function store(array $data)
|
||||
{
|
||||
$tag = new Tag;
|
||||
$tag->tag = $data['tag'];
|
||||
$tag->date = $data['date'];
|
||||
$tag->description = $data['description'];
|
||||
$tag->latitude = $data['latitude'];
|
||||
$tag->longitude = $data['longitude'];
|
||||
$tag->zoomLevel = $data['zoomLevel'];
|
||||
$tag->tagMode = $data['tagMode'];
|
||||
$tag->user()->associate(Auth::user());
|
||||
$tag->save();
|
||||
|
||||
return $tag;
|
||||
|
||||
|
||||
}
|
||||
}
|
20
app/Repositories/Tag/TagRepositoryInterface.php
Normal file
20
app/Repositories/Tag/TagRepositoryInterface.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Tag;
|
||||
use FireflyIII\Models\Tag;
|
||||
|
||||
|
||||
/**
|
||||
* Interface TagRepositoryInterface
|
||||
*
|
||||
* @package FireflyIII\Repositories\Tag
|
||||
*/
|
||||
interface TagRepositoryInterface {
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
public function store(array $data);
|
||||
}
|
@ -62,7 +62,10 @@ class ExpandedForm
|
||||
'account_id' => 'Asset account',
|
||||
'budget_id' => 'Budget',
|
||||
'openingBalance' => 'Opening balance',
|
||||
'tagMode' => 'Tag mode',
|
||||
'tagPosition' => 'Tag location',
|
||||
'virtualBalance' => 'Virtual balance',
|
||||
'longitude_latitude' => 'Location',
|
||||
'targetamount' => 'Target amount',
|
||||
'accountRole' => 'Account role',
|
||||
'openingBalanceDate' => 'Opening balance date',
|
||||
@ -201,15 +204,17 @@ class ExpandedForm
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function month($name, $value = null, array $options = [])
|
||||
public function integer($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$html = View::make('form.month', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = '1';
|
||||
$html = View::make('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,14 +224,13 @@ class ExpandedForm
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function integer($name, $value = null, array $options = [])
|
||||
public function location($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = '1';
|
||||
$html = View::make('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$html = View::make('form.location', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
@ -265,6 +269,44 @@ class ExpandedForm
|
||||
return $selectList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function month($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$html = View::make('form.month', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function multiRadio($name, array $list = [], $selected = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$selected = $this->fillFieldValue($name, $selected);
|
||||
|
||||
unset($options['class']);
|
||||
$html = View::make('form.multiRadio', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @param $name
|
||||
@ -336,4 +378,24 @@ class ExpandedForm
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function textarea($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['rows'] = 4;
|
||||
$html = View::make('form.textarea', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
|
||||
return $this->hasMany('FireflyIII\Models\Account');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function tags()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\Tag');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
|
@ -181,10 +181,14 @@ class FireflyValidator extends Validator
|
||||
*/
|
||||
public function validateUniqueObjectForUser($attribute, $value, $parameters)
|
||||
{
|
||||
$table = $parameters[0];
|
||||
$field = $parameters[1];
|
||||
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
|
||||
$exclude = isset($parameters[3]) ? $parameters[3] : null;
|
||||
$table = $parameters[0];
|
||||
$field = $parameters[1];
|
||||
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
|
||||
$exclude = isset($parameters[3]) ? $parameters[3] : null;
|
||||
$alwaysEncrypted = false;
|
||||
if ($encrypted == 'TRUE') {
|
||||
$alwaysEncrypted = true;
|
||||
}
|
||||
|
||||
$query = DB::table($table)->where('user_id', Auth::user()->id);
|
||||
|
||||
@ -195,8 +199,12 @@ class FireflyValidator extends Validator
|
||||
|
||||
$set = $query->get();
|
||||
foreach ($set as $entry) {
|
||||
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
|
||||
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
|
||||
if (!$alwaysEncrypted) {
|
||||
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
|
||||
} else {
|
||||
$isEncrypted = true;
|
||||
}
|
||||
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
|
||||
if ($checkValue == $value) {
|
||||
return false;
|
||||
}
|
||||
|
@ -137,6 +137,9 @@ return [
|
||||
'Illuminate\View\ViewServiceProvider',
|
||||
'Illuminate\Html\HtmlServiceProvider',
|
||||
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
|
||||
'Barryvdh\Debugbar\ServiceProvider',
|
||||
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
|
||||
|
||||
|
||||
/*
|
||||
* Application Service Providers...
|
||||
|
87
database/migrations/2015_04_26_054507_changes_for_v3310.php
Normal file
87
database/migrations/2015_04_26_054507_changes_for_v3310.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class ChangesForV3310 extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('tags');
|
||||
Schema::drop('tag_transaction_journal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
//
|
||||
Schema::table(
|
||||
'transaction_groups', function (Blueprint $table) {
|
||||
|
||||
// drop column "relation"
|
||||
$table->dropColumn('relation');
|
||||
}
|
||||
);
|
||||
|
||||
Schema::table(
|
||||
'transaction_groups', function (Blueprint $table) {
|
||||
|
||||
// drop column "relation"
|
||||
$table->string('relation', 50);
|
||||
}
|
||||
);
|
||||
// make new column "relation"
|
||||
|
||||
// set all current entries to be "balance"
|
||||
DB::table('transaction_groups')->update(['relation' => 'balance']);
|
||||
|
||||
/*
|
||||
* New table!
|
||||
*/
|
||||
Schema::create(
|
||||
'tags', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->string('tag', 1024);
|
||||
$table->string('tagMode', 1024);
|
||||
$table->date('date')->nullable();
|
||||
$table->text('description')->nullable();
|
||||
$table->decimal('latitude', 18, 12)->nullable();
|
||||
$table->decimal('longitude', 18, 12)->nullable();
|
||||
$table->smallInteger('zoomLevel', false, true)->nullable();
|
||||
|
||||
|
||||
// connect reminders to users
|
||||
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
Schema::create('tag_transaction_journal',function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->integer('tag_id')->unsigned();
|
||||
$table->integer('transaction_journal_id')->unsigned();
|
||||
|
||||
// link to foreign tables.
|
||||
$table->foreign('tag_id', 'tag_grp_id')->references('id')->on('tags')->onDelete('cascade');
|
||||
$table->foreign('transaction_journal_id', 'tag_trj_id')->references('id')->on('transaction_journals')->onDelete('cascade');
|
||||
|
||||
// add unique.
|
||||
$table->unique(['tag_id', 'transaction_journal_id'], 'tag_t_joined');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -5,4 +5,9 @@
|
||||
.ui-sortable-placeholder {
|
||||
display: inline-block;
|
||||
height: 1px;
|
||||
}
|
||||
#map-canvas {
|
||||
height: 100%;
|
||||
margin: 0px;
|
||||
padding: 0px
|
||||
}
|
115
public/js/tags.js
Normal file
115
public/js/tags.js
Normal file
@ -0,0 +1,115 @@
|
||||
$(function () {
|
||||
|
||||
/*
|
||||
Hide and show the tag index help.
|
||||
*/
|
||||
$('#tagHelp').on('show.bs.collapse', function () {
|
||||
// set hideTagHelp = false
|
||||
$.post('/tags/hideTagHelp/false', {_token: token});
|
||||
$('#tagHelpButton').text('Hide help');
|
||||
|
||||
}).on('hide.bs.collapse', function () {
|
||||
// set hideTagHelp = true
|
||||
$.post('/tags/hideTagHelp/true', {_token: token});
|
||||
$('#tagHelpButton').text('Show help');
|
||||
|
||||
});
|
||||
|
||||
$('#clearLocation').click(clearLocation);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Some vars as prep for the map:
|
||||
*/
|
||||
var map;
|
||||
var markers = [];
|
||||
var setTag = false;
|
||||
|
||||
var mapOptions = {
|
||||
zoom: zoomLevel,
|
||||
center: new google.maps.LatLng(latitude, longitude),
|
||||
disableDefaultUI: true
|
||||
};
|
||||
|
||||
/*
|
||||
Clear location and reset zoomLevel.
|
||||
*/
|
||||
function clearLocation() {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
$('input[name="latitude"]').val("");
|
||||
$('input[name="longitude"]').val("");
|
||||
$('input[name="zoomLevel"]').val("6");
|
||||
setTag = false;
|
||||
$('input[name="setTag"]').val('false');
|
||||
return false;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
/*
|
||||
Create new map:
|
||||
*/
|
||||
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
|
||||
|
||||
/*
|
||||
Respond to click event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'rightclick', function (event) {
|
||||
placeMarker(event);
|
||||
});
|
||||
|
||||
/*
|
||||
Respond to zoom event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'zoom_changed', function () {
|
||||
saveZoomLevel(event);
|
||||
});
|
||||
/*
|
||||
Maybe place marker?
|
||||
*/
|
||||
if(doPlaceMarker) {
|
||||
var myLatlng = new google.maps.LatLng(latitude,longitude);
|
||||
var fakeEvent = {};
|
||||
fakeEvent.latLng = myLatlng;
|
||||
placeMarker(fakeEvent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save zoom level of map into hidden input.
|
||||
*/
|
||||
function saveZoomLevel() {
|
||||
"use strict";
|
||||
$('input[name="zoomLevel"]').val(map.getZoom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Place marker on map.
|
||||
* @param event
|
||||
*/
|
||||
function placeMarker(event) {
|
||||
deleteMarkers();
|
||||
var marker = new google.maps.Marker({position: event.latLng, map: map});
|
||||
$('input[name="latitude"]').val(event.latLng.lat());
|
||||
$('input[name="longitude"]').val(event.latLng.lng());
|
||||
markers.push(marker);
|
||||
setTag = true;
|
||||
$('input[name="setTag"]').val('true');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes all markers in the array by removing references to them.
|
||||
*/
|
||||
function deleteMarkers() {
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
markers[i].setMap(null);
|
||||
}
|
||||
markers = [];
|
||||
}
|
||||
|
||||
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
14
resources/views/form/location.blade.php
Normal file
14
resources/views/form/location.blade.php
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')
|
||||
</div>
|
||||
</div>
|
16
resources/views/form/multiRadio.blade.php
Normal file
16
resources/views/form/multiRadio.blade.php
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">
|
||||
@foreach($list as $value => $description)
|
||||
<div class="radio">
|
||||
<label>
|
||||
{!! Form::radio($name, $value, ($selected == $value), $options) !!}
|
||||
{{$description}}
|
||||
</label>
|
||||
</div>
|
||||
@endforeach
|
||||
@include('form.help')
|
||||
@include('form.feedback')
|
||||
|
||||
</div>
|
||||
</div>
|
7
resources/views/form/textarea.blade.php
Normal file
7
resources/views/form/textarea.blade.php
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')
|
||||
</div>
|
||||
</div>
|
@ -1,5 +1,4 @@
|
||||
@extends('app')
|
||||
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
@ -122,7 +122,7 @@
|
||||
<a @if($r == 'categories.index') class="active" @endif href="{{route('categories.index')}}"><i class="fa fa-bar-chart fa-fw"></i> Categories</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#"><i class="fa fa-tags fa-fw"></i> Tags</a>
|
||||
<a @if($r == 'tags.index') class="active" @endif href="{{route('tags.index')}}"><i class="fa fa-tags fa-fw"></i> Tags</a>
|
||||
</li>
|
||||
<li>
|
||||
<a @if(!(strpos($r,'reports') === false)) class="active" @endif href="{{route('reports.index')}}"><i class="fa fa-line-chart fa-fw"></i> Reports</a>
|
||||
|
85
resources/views/tags/create.blade.php
Normal file
85
resources/views/tags/create.blade.php
Normal file
@ -0,0 +1,85 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) !!}
|
||||
{!! Form::open(['class' => 'form-horizontal','id' => 'store','route' => 'tags.store']) !!}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-5 col-sm-12">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-tag"></i> Mandatory fields
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{!! ExpandedForm::text('tag') !!}
|
||||
{!! ExpandedForm::multiRadio('tagMode',$tagOptions) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-7 col-md-7 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">
|
||||
{!! ExpandedForm::date('date') !!}
|
||||
{!! ExpandedForm::textarea('description') !!}
|
||||
{!! ExpandedForm::location('tagPosition') !!}
|
||||
</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','tag') !!}
|
||||
</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 tag
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
@stop
|
||||
@section('scripts')
|
||||
<script type="text/javascript">
|
||||
@if(Input::old('latitude'))
|
||||
var latitude = "{{Input::old('latitude')}}";
|
||||
@else
|
||||
var latitude = "52.3167";
|
||||
@endif
|
||||
|
||||
@if(Input::old('latitude') && Input::old('longitude') && Input::old('zoomLevel'))
|
||||
var doPlaceMarker = true;
|
||||
@else
|
||||
var doPlaceMarker = false;
|
||||
@endif
|
||||
|
||||
@if(Input::old('longitude'))
|
||||
var longitude = "{{Input::old('longitude')}}";
|
||||
@else
|
||||
var longitude = "5.5500";
|
||||
@endif
|
||||
|
||||
@if(Input::old('zoomLevel'))
|
||||
var zoomLevel = {{intval(Input::old('zoomLevel'))}};
|
||||
@else
|
||||
var zoomLevel = 6;
|
||||
@endif
|
||||
|
||||
</script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?v=3"></script>
|
||||
<script src="js/tags.js"></script>
|
||||
@stop
|
86
resources/views/tags/edit.blade.php
Normal file
86
resources/views/tags/edit.blade.php
Normal file
@ -0,0 +1,86 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $tag) !!}
|
||||
{!! Form::model($tag, ['class' => 'form-horizontal','id' => 'update','url' => route('tags.update',$tag->id)]) !!}
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-5 col-md-5 col-sm-12">
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-tag"></i> Mandatory fields
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{!! ExpandedForm::text('tag') !!}
|
||||
{!! ExpandedForm::multiRadio('tagMode',$tagOptions) !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-7 col-md-7 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">
|
||||
{!! ExpandedForm::date('date') !!}
|
||||
{!! ExpandedForm::textarea('description') !!}
|
||||
{!! ExpandedForm::location('tagPosition') !!}
|
||||
</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','tag') !!}
|
||||
</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 tag
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
@stop
|
||||
@section('scripts')
|
||||
<script type="text/javascript">
|
||||
@if(Input::old('latitude'))
|
||||
var latitude = "{{Input::old('latitude')}}";
|
||||
@else
|
||||
var latitude = "52.3167";
|
||||
@endif
|
||||
|
||||
@if(Input::old('latitude') && Input::old('longitude') && Input::old('zoomLevel'))
|
||||
var doPlaceMarker = true;
|
||||
@else
|
||||
var doPlaceMarker = false;
|
||||
@endif
|
||||
|
||||
@if(Input::old('longitude'))
|
||||
var longitude = "{{Input::old('longitude')}}";
|
||||
@else
|
||||
var longitude = "5.5500";
|
||||
@endif
|
||||
|
||||
@if(Input::old('zoomLevel'))
|
||||
var zoomLevel = {{intval(Input::old('zoomLevel'))}};
|
||||
@else
|
||||
var zoomLevel = 6;
|
||||
@endif
|
||||
|
||||
</script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?v=3"></script>
|
||||
<script src="js/tags.js"></script>
|
||||
@stop
|
63
resources/views/tags/index.blade.php
Normal file
63
resources/views/tags/index.blade.php
Normal file
@ -0,0 +1,63 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><i class="fa fa-fw fa-tags"></i> Tags</div>
|
||||
<div class="panel-body">
|
||||
<div id="tagHelp" class="collapse
|
||||
@if($helpHidden === false)
|
||||
in
|
||||
@endif
|
||||
">
|
||||
<p>
|
||||
Usually tags are singular words, designed to quickly band items together
|
||||
using things like <span class="label label-info">expensive</span>,
|
||||
<span class="label label-info">bill</span> or
|
||||
<span class="label label-info">for-party</span>. In Firefly III, tags can have more properties
|
||||
such as a date, description and location. This allows you to join transactions together in a more meaningful
|
||||
way. For example, you could make a tag called <span class="label label-success">Christmas dinner with friends</span>
|
||||
and add information about the restaurant. Such tags are "singular", you would only use them for a single occasion,
|
||||
perhaps with multiple transactions.
|
||||
</p>
|
||||
<p>
|
||||
Tags group transactions together, which makes it possible to store reimbursements
|
||||
(in case you front money for others) and other "balancing acts" where expenses
|
||||
are summed up (the payments on your new TV) or where expenses and deposits
|
||||
are cancelling each other out (buying something with saved money). It's all up to you.
|
||||
Using tags the old-fashioned way is of course always possible.
|
||||
</p>
|
||||
<p>
|
||||
Create a tag to get started or enter tags when creating new transactions.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<a data-toggle="collapse" id="tagHelpButton" href="#tagHelp" aria-expanded="false" aria-controls="tagHelp">
|
||||
@if($helpHidden === false)
|
||||
Hide help
|
||||
@else
|
||||
Show help
|
||||
@endif
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{route('tags.create')}}" title="New tag" class="btn btn-info"><i class="fa fa-fw fa-tag"></i> Create new tag</a>
|
||||
</p>
|
||||
<p>
|
||||
@if(count($tags) == 0)
|
||||
<em>No tags</em>
|
||||
@else
|
||||
@foreach($tags as $tag)
|
||||
<h4 style="display: inline;"><a class="label label-success" href="{{route('tags.show',$tag)}}">{{$tag->tag}}</a></h4>
|
||||
@endforeach
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@section('scripts')
|
||||
<script type="text/javascript" src="js/tags.js"></script>
|
||||
@endsection
|
77
resources/views/tags/show.blade.php
Normal file
77
resources/views/tags/show.blade.php
Normal file
@ -0,0 +1,77 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $tag) !!}
|
||||
<!-- show this block only when the tag has some meta-data -->
|
||||
@if($tag->latitude && $tag->longitude && $tag->zoomLevel)
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-fw {{$subTitleIcon}} fa-fw"></i> {{{$tag->tag}}}
|
||||
@if($tag->date)
|
||||
on {{$tag->date->format('jS F Y')}}
|
||||
@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('tags.edit',$tag->id)}}"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
|
||||
<li><a href="{{route('tags.delete',$tag->id)}}"><i class="fa fa-trash fa-fw"></i> Delete</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
@if($tag->description)
|
||||
<p class="text-info">
|
||||
{{$tag->description}}
|
||||
</p>
|
||||
@endif
|
||||
@if($tag->latitude && $tag->longitude && $tag->zoomLevel)
|
||||
<p>
|
||||
<img src="https://maps.googleapis.com/maps/api/staticmap?center={{$tag->latitude}},{{$tag->longitude}}&zoom={{$tag->zoomLevel}}&size=600x300">
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<!-- if no such thing, show another block maybe? -->
|
||||
<div class="row">
|
||||
<div class="col-lg-612 col-md-12 col-sm-12 col-xs-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-repeat fa-fw"></i> Transactions
|
||||
<!-- here is the edit menu when there is no meta-data -->
|
||||
@if(!($tag->latitude && $tag->longitude && $tag->zoomLevel))
|
||||
<!-- 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('tags.edit',$tag->id)}}"><i class="fa fa-pencil fa-fw"></i> Edit</a></li>
|
||||
<li><a href="{{route('tags.delete',$tag->id)}}"><i class="fa fa-trash fa-fw"></i> Delete</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@include('list.journals-full',['journals' => $tag->transactionjournals])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
<script type="text/javascript">
|
||||
var tagID = {{{$tag->id}}};
|
||||
</script>
|
||||
@stop
|
@ -53,50 +53,6 @@
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<i class="fa fa-fw fa-exchange"></i>
|
||||
Related transactions
|
||||
</div>
|
||||
@if($journal->transactiongroups()->count() == 0)
|
||||
<div class="panel-body">
|
||||
<p>
|
||||
<em>No related transactions</em>
|
||||
</p>
|
||||
</div>
|
||||
@else
|
||||
<table class="table">
|
||||
@foreach($journal->transactiongroups()->get() as $group)
|
||||
<tr>
|
||||
<th colspan="2">Group #{{$group->id}} ({{$group->relation}})</th>
|
||||
</tr>
|
||||
@foreach($group->transactionjournals()->where('transaction_journals.id','!=',$journal->id)->get() as $jrnl)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{route('related.getRemoveRelation',[$journal->id, $jrnl->id])}}" class="btn btn-danger btn-xs"><span class="glyphicon glyphicon-trash"></span></a>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{route('transactions.show',$jrnl->id)}}">{{{$jrnl->description}}}</a>
|
||||
</td>
|
||||
<td>
|
||||
@foreach($jrnl->transactions()->get() as $t)
|
||||
@if($t->amount > 0)
|
||||
{!! Amount::formatTransaction($t) !!}
|
||||
@endif
|
||||
@endforeach
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
||||
@endif
|
||||
<div class="panel-footer">
|
||||
<p>
|
||||
<a href="#" data-id="{{$journal->id}}" class="relateTransaction btn btn-default"><i data-id="{{$journal->id}}" class="fa fa-compress"></i> Relate to another transaction</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user