mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-30 02:26:58 +00:00
First attempt at basic tag functionality.
This commit is contained in:
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\PiggyBank;
|
||||||
use FireflyIII\Models\Reminder;
|
use FireflyIII\Models\Reminder;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\Tag;
|
||||||
/*
|
/*
|
||||||
* Back home.
|
* 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\Reminder;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\Tag;
|
||||||
|
|
||||||
|
|
||||||
// models
|
// 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
|
* Auth\AuthController
|
||||||
@@ -327,6 +338,22 @@ Route::group(
|
|||||||
*/
|
*/
|
||||||
Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']);
|
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
|
* 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 $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\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository');
|
||||||
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');
|
$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\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');
|
$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',
|
'account_id' => 'Asset account',
|
||||||
'budget_id' => 'Budget',
|
'budget_id' => 'Budget',
|
||||||
'openingBalance' => 'Opening balance',
|
'openingBalance' => 'Opening balance',
|
||||||
|
'tagMode' => 'Tag mode',
|
||||||
|
'tagPosition' => 'Tag location',
|
||||||
'virtualBalance' => 'Virtual balance',
|
'virtualBalance' => 'Virtual balance',
|
||||||
|
'longitude_latitude' => 'Location',
|
||||||
'targetamount' => 'Target amount',
|
'targetamount' => 'Target amount',
|
||||||
'accountRole' => 'Account role',
|
'accountRole' => 'Account role',
|
||||||
'openingBalanceDate' => 'Opening balance date',
|
'openingBalanceDate' => 'Opening balance date',
|
||||||
@@ -201,15 +204,17 @@ class ExpandedForm
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function month($name, $value = null, array $options = [])
|
public function integer($name, $value = null, array $options = [])
|
||||||
{
|
{
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
$value = $this->fillFieldValue($name, $value);
|
$value = $this->fillFieldValue($name, $value);
|
||||||
$html = View::make('form.month', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
$options['step'] = '1';
|
||||||
|
$html = View::make('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -219,14 +224,13 @@ class ExpandedForm
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function integer($name, $value = null, array $options = [])
|
public function location($name, $value = null, array $options = [])
|
||||||
{
|
{
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
$value = $this->fillFieldValue($name, $value);
|
$value = $this->fillFieldValue($name, $value);
|
||||||
$options['step'] = '1';
|
$html = View::make('form.location', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||||
$html = View::make('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
|
||||||
@@ -265,6 +269,44 @@ class ExpandedForm
|
|||||||
return $selectList;
|
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 $type
|
||||||
* @param $name
|
* @param $name
|
||||||
@@ -336,4 +378,24 @@ class ExpandedForm
|
|||||||
return $html;
|
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 $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
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
*/
|
*/
|
||||||
|
@@ -181,10 +181,14 @@ class FireflyValidator extends Validator
|
|||||||
*/
|
*/
|
||||||
public function validateUniqueObjectForUser($attribute, $value, $parameters)
|
public function validateUniqueObjectForUser($attribute, $value, $parameters)
|
||||||
{
|
{
|
||||||
$table = $parameters[0];
|
$table = $parameters[0];
|
||||||
$field = $parameters[1];
|
$field = $parameters[1];
|
||||||
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
|
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
|
||||||
$exclude = isset($parameters[3]) ? $parameters[3] : null;
|
$exclude = isset($parameters[3]) ? $parameters[3] : null;
|
||||||
|
$alwaysEncrypted = false;
|
||||||
|
if ($encrypted == 'TRUE') {
|
||||||
|
$alwaysEncrypted = true;
|
||||||
|
}
|
||||||
|
|
||||||
$query = DB::table($table)->where('user_id', Auth::user()->id);
|
$query = DB::table($table)->where('user_id', Auth::user()->id);
|
||||||
|
|
||||||
@@ -195,8 +199,12 @@ class FireflyValidator extends Validator
|
|||||||
|
|
||||||
$set = $query->get();
|
$set = $query->get();
|
||||||
foreach ($set as $entry) {
|
foreach ($set as $entry) {
|
||||||
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
|
if (!$alwaysEncrypted) {
|
||||||
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
|
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
|
||||||
|
} else {
|
||||||
|
$isEncrypted = true;
|
||||||
|
}
|
||||||
|
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
|
||||||
if ($checkValue == $value) {
|
if ($checkValue == $value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -137,6 +137,9 @@ return [
|
|||||||
'Illuminate\View\ViewServiceProvider',
|
'Illuminate\View\ViewServiceProvider',
|
||||||
'Illuminate\Html\HtmlServiceProvider',
|
'Illuminate\Html\HtmlServiceProvider',
|
||||||
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
|
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
|
||||||
|
'Barryvdh\Debugbar\ServiceProvider',
|
||||||
|
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Application Service Providers...
|
* 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 {
|
.ui-sortable-placeholder {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 1px;
|
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')
|
@section('content')
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<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>
|
<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>
|
||||||
<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>
|
||||||
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@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>
|
||||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user