Piggy bank can now have a group.

This commit is contained in:
James Cole
2020-06-07 11:31:01 +02:00
parent 2f63090e7c
commit 16b0307b0a
20 changed files with 439 additions and 105 deletions

View File

@@ -27,6 +27,7 @@ use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -35,6 +36,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
@@ -342,6 +344,34 @@ class AutoCompleteController extends Controller
return response()->json($return);
}
/**
* An auto-complete specifically for expense accounts, used when mass updating mostly.
*
* @param Request $request
*
* @return JsonResponse
*/
public function objectGroups(Request $request): JsonResponse
{
$search = $request->get('search');
/** @var ObjectGroupRepositoryInterface $repository */
$repository = app(ObjectGroupRepositoryInterface::class);
$return = [];
$result = $repository->search((string) $search);
/** @var ObjectGroup $account */
foreach ($result as $objectGroup) {
$return[] = [
'id' => $objectGroup->id,
'title' => $objectGroup->title,
];
}
return response()->json($return);
}
/**
* @return JsonResponse
* @codeCoverageIgnore

View File

@@ -54,6 +54,7 @@ class PiggyBankFormRequest extends Request
'targetamount' => $this->string('targetamount'),
'targetdate' => $this->date('targetdate'),
'notes' => $this->nlString('notes'),
'object_group' => $this->string('object_group'),
];
}

View File

@@ -10,14 +10,27 @@ use Illuminate\Database\Eloquent\Model;
* Class ObjectGroup
*
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBank[] $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read int|null $piggy_banks_count
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup query()
* @mixin \Eloquent
* @property int $id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property string|null $deleted_at
* @property string $title
* @property int $order
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup whereCreatedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup whereDeletedAt($value)
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup whereId($value)
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup whereOrder($value)
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup whereTitle($value)
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\ObjectGroup whereUpdatedAt($value)
*/
class ObjectGroup extends Model
{
protected $fillable = ['title', 'order'];
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/

View File

@@ -78,9 +78,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $notes_count
* @property-read int|null $piggy_bank_events_count
* @property-read int|null $piggy_bank_repetitions_count
* @property bool $encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\ObjectGroup[] $objectGroups
* @property-read int|null $object_groups_count
* @property bool $encrypted
*/
class PiggyBank extends Model
{

View File

@@ -37,6 +37,8 @@ use FireflyIII\Helpers\Report\PopupReport;
use FireflyIII\Helpers\Report\PopupReportInterface;
use FireflyIII\Helpers\Report\ReportHelper;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepository;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Repositories\Telemetry\TelemetryRepository;
use FireflyIII\Repositories\Telemetry\TelemetryRepositoryInterface;
use FireflyIII\Repositories\TransactionType\TransactionTypeRepository;
@@ -172,6 +174,7 @@ class FireflyServiceProvider extends ServiceProvider
// other generators
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
$this->app->bind(TransactionTypeRepositoryInterface::class, TransactionTypeRepository::class);
$this->app->bind(ObjectGroupRepositoryInterface::class,ObjectGroupRepository::class);
$this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class);
// more generators:

View File

@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;
use FireflyIII\Models\ObjectGroup;
/**
* Trait CreatesObjectGroups
*/
trait CreatesObjectGroups
{
/**
* @param string $title
*
* @return null|ObjectGroup
*/
protected function findObjectGroup(string $title): ?ObjectGroup
{
return ObjectGroup::where('title', $title)->first();
}
/**
* @param string $title
*
* @return ObjectGroup|null
*/
protected function findOrCreateObjectGroup(string $title): ?ObjectGroup
{
$group = null;
$maxOrder = $this->getObjectGroupMaxOrder();
if (!$this->hasObjectGroup($title)) {
return ObjectGroup::create(
[
'title' => $title,
'order' => $maxOrder + 1,
]
);
}
return $this->findObjectGroup($title);
}
/**
* @return int
*/
protected function getObjectGroupMaxOrder(): int
{
return ObjectGroup::max('order');
}
/**
* @param string $title
*
* @return bool
*/
protected function hasObjectGroup(string $title): bool
{
return 1 === ObjectGroup::where('title', $title)->count();
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;
use FireflyIII\Models\ObjectGroup;
use Illuminate\Support\Collection;
/**
* Class ObjectGroupRepository
*/
class ObjectGroupRepository implements ObjectGroupRepositoryInterface
{
/**
* @inheritDoc
*/
public function get(): Collection
{
return ObjectGroup::orderBy('order')->get();
}
/**
* @param string $query
*
* @return Collection
*/
public function search(string $query): Collection
{
$dbQuery = ObjectGroup::orderBy('order');
if ('' !== $query) {
// split query on spaces just in case:
$parts = explode(' ', $query);
foreach ($parts as $part) {
$search = sprintf('%%%s%%', $part);
$dbQuery->where('title', 'LIKE', $search);
}
}
return $dbQuery->get(['object_groups.*']);
}
}

View File

@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Repositories\ObjectGroup;
use Illuminate\Support\Collection;
/**
* Interface ObjectGroupRepositoryInterface
*/
interface ObjectGroupRepositoryInterface
{
/**
* @return Collection
*/
public function get(): Collection;
/**
* @param string $query
*
* @return Collection
*/
public function search(string $query): Collection;
}

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use Illuminate\Database\QueryException;
use Log;
@@ -39,7 +40,7 @@ use Log;
*/
trait ModifiesPiggyBanks
{
use CreatesObjectGroups;
/**
* @param PiggyBank $piggyBank
* @param string $amount
@@ -274,6 +275,15 @@ trait ModifiesPiggyBanks
$repetition->save();
}
$objectGroupTitle = $data['object_group'] ?? '';
if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) {
$piggyBank->objectGroups()->sync([$objectGroup->id]);
$piggyBank->save();
}
}
return $piggyBank;
}
@@ -313,6 +323,15 @@ trait ModifiesPiggyBanks
$repetition->save();
}
$objectGroupTitle = $data['object_group'] ?? '';
if ('' !== $objectGroupTitle) {
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
if (null !== $objectGroup) {
$piggyBank->objectGroups()->sync([$objectGroup->id]);
$piggyBank->save();
}
}
return $piggyBank;
}

View File

@@ -265,7 +265,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
*/
public function getPiggyBanks(): Collection
{
return $this->user->piggyBanks()->with(['account'])->orderBy('order', 'ASC')->get();
return $this->user->piggyBanks()->with(['account', 'objectGroups'])->orderBy('order', 'ASC')->get();
}

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Transformers;
use FireflyIII\Models\Account;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
@@ -83,6 +84,17 @@ class PiggyBankTransformer extends AbstractTransformer
$notes = $this->piggyRepos->getNoteText($piggyBank);
$notes = '' === $notes ? null : $notes;
$objectGroupId = null;
$objectGroupOrder = 0;
$objectGroupTitle = null;
/** @var ObjectGroup $objectGroup */
$objectGroup = $piggyBank->objectGroups->first();
if (null !== $objectGroup) {
$objectGroupId = (int) $objectGroup->id;
$objectGroupOrder = (int) $objectGroup->order;
$objectGroupTitle = $objectGroup->title;
}
// get currently saved amount:
$currentAmountStr = $this->piggyRepos->getCurrentAmount($piggyBank);
$currentAmount = round($currentAmountStr, $currency->decimal_places);
@@ -114,9 +126,12 @@ class PiggyBankTransformer extends AbstractTransformer
'save_per_month' => round($this->piggyRepos->getSuggestedMonthlyAmount($piggyBank), $currency->decimal_places),
'start_date' => $startDate,
'target_date' => $targetDate,
'order' => (int)$piggyBank->order,
'order' => (int) $piggyBank->order,
'active' => true,
'notes' => $notes,
'object_group_id' => $objectGroupId,
'object_group_order' => $objectGroupOrder,
'object_group_title' => $objectGroupTitle,
'links' => [
[
'rel' => 'self',

View File

@@ -139,6 +139,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property bool $blocked
* @property string|null $blocked_code
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Role[] $roles
* @property string|null $provider
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\User whereProvider($value)
*/
class User extends Authenticatable
{

View File

@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* Class ChangesForV530
*/
class ChangesForV530 extends Migration
{
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('object_groupables');
Schema::dropIfExists('object_groups');
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!Schema::hasTable('object_groups')) {
Schema::create(
'object_groups', static function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->string('title', 255);
$table->mediumInteger('order', false, true)->default(0);
}
);
}
if (!Schema::hasTable('object_groupables')) {
Schema::create(
'object_groupables', static function (Blueprint $table) {
$table->integer('object_group_id');
$table->integer('object_groupable_id', false, true);
$table->string('object_groupable_type', 255);
}
);
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* edit.js
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/** global: Modernizr */
$(document).ready(function () {
"use strict";
// auto complete for object group.
console.log('Object group auto complete thing.');
var objectGroupAC = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
prefetch: {
url: 'json/object-groups?uid=' + uid,
filter: function (list) {
return $.map(list, function (obj) {
return obj;
});
}
},
remote: {
url: 'json/object-groups?search=%QUERY&uid=' + uid,
wildcard: '%QUERY',
filter: function (list) {
return $.map(list, function (obj) {
return obj;
});
}
}
});
objectGroupAC.initialize();
$('input[name="object_group"]').typeahead({hint: true, highlight: true,}, {source: objectGroupAC, displayKey: 'title', autoSelect: false});
});

View File

@@ -38,6 +38,7 @@ $(function () {
{
helper: fixHelper,
stop: stopSorting,
items: 'tr.sortable',
handle: '.handle',
start: function (event, ui) {
// Build a placeholder cell that spans all the cells in the row
@@ -84,7 +85,7 @@ function stopSorting() {
"use strict";
$('.loadSpin').addClass('fa fa-refresh fa-spin');
$.each($('#sortable-piggy>tbody>tr'), function (i, v) {
$.each($('#sortable-piggy>tbody>tr.sortable'), function (i, v) {
var holder = $(v);
var position = parseInt(holder.data('position'));
var originalOrder = parseInt(holder.data('order'));

View File

@@ -1502,6 +1502,9 @@ return [
// sandstorm.io errors and messages:
'sandstorm_not_available' => 'This function is not available when you are using Firefly III within a Sandstorm.io environment.',
// object groups
'default_group_title_name' => '(ungrouped)',
// empty lists? no objects? instructions:
'no_accounts_title_asset' => 'Let\'s create an asset account!',
'no_accounts_intro_asset' => 'You have no asset accounts yet. Asset accounts are your main accounts: your checking account, savings account, shared account or even your credit card.',

View File

@@ -1,6 +1,3 @@
<div style="padding-left:8px;">
{{ piggyBanks.render|raw }}
</div>
<table class="table table-hover table-condensed" id="sortable-piggy">
<thead>
<tr>
@@ -13,86 +10,92 @@
<th style="text-align: right;" class="hidden-sm hidden-xs">{{ 'suggested_savings_per_month'|_ }}</th>
</tr>
</thead>
<tbody>
{% for piggy in piggyBanks %}
<tr data-id="{{ piggy.id }}" data-name="{{ piggy.name }}" data-order="{{ piggy.order }}" data-position="{{ loop.index0 }}">
<td class="visible-xs visible-sm hidden-md hidden-lg">
&nbsp;
</td>
<td class="visible-xs visible-sm hidden-md hidden-lg">
<div class="btn-group btn-group-xs">
<a href="{{ route('piggy-banks.remove-money-mobile', piggy.id) }}" class="btn btn-default btn-xs"><i class="fa fa-minus"></i></a>
<a href="{{ route('piggy-banks.add-money-mobile', piggy.id) }}" class="btn btn-default btn-xs"><i class="fa fa-plus"></i></a>
</div>
</td>
<td style="width:60px;" class="hidden-sm hidden-xs">
<i class="fa fa-fw fa-bars handle"></i>
<i class="loadSpin"></i>
</td>
<td style="width:100px;" class="hidden-sm hidden-xs">
<div class="btn-group btn-group-xs">
<a href="{{ route('piggy-banks.edit', piggy.id) }}" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
<a href="{{ route('piggy-banks.delete', piggy.id) }}" class="btn btn-danger btn-xs"><i class="fa fa-trash fa-fw"></i></a>
</div>
</td>
<td>
<a href="{{ route('piggy-banks.show', piggy.id) }}" title="{{ piggy.account_name }}">{{ piggy.name }}</a>
{% if piggy.attachments.count > 0 %}
<i class="fa fa-fw fa-paperclip"></i>
{% endif %}
</td>
<td style="text-align: right;" class="piggySaved">
<span title="Saved so far" style="text-align:right;">{{ formatAmountBySymbol(piggy.current_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;width:40px;">
{% if piggy.current_amount > 0 %}
<a href="{{ route('piggy-banks.remove-money', piggy.id) }}" class="btn btn-default btn-xs removeMoney" data-id="{{ piggy.id }}">
<i data-id="{{ piggy.id }}" class="fa fa-minus"></i></a>
{% endif %}
</td>
<td class="hidden-sm hidden-xs piggyBar">
<div class="progress progress" style="margin-bottom:0;">
<div
{% if piggy.percentage == 100 %}
class="progress-bar progress-bar-success"
{% elseif piggy.percentage == 0 %}
class="progress-bar progress-bar-warning"
{% else %}
class="progress-bar progress-bar-info"
{% endif %}
role="progressbar" aria-valuenow="{{ piggy.percentage }}" aria-valuemin="0" aria-valuemax="100"
style="min-width: 30px;width: {{ piggy.percentage }}%;">
{{ piggy.percentage }}%
</div>
</div>
</td>
<td class="hidden-sm hidden-xs" style="width:40px;">
{% if piggy.left_to_save > 0 %}
<a href="{{ route('piggy-banks.add-money', piggy.id) }}" class="btn btn-default btn-xs addMoney" data-id="{{ piggy.id }}">
<i data-id="{{ piggy.id }}" class="fa fa-plus"></i></a>
{% endif %}
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;">
<span title="{{ 'target_amount'|_ }}">{{ formatAmountBySymbol(piggy.target_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;">
{% if piggy.left_to_save > 0 %}
<span title="{{ 'left_to_save'|_ }}">{{ formatAmountBySymbol(piggy.left_to_save,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
{% endif %}
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;">
{% if piggy.target_date %}
{{ formatAmountBySymbol(piggy.save_per_month, piggy.currency_symbol, piggy.currency_decimal_places) }}
{% endif %}
</td>
{% for objectGroupOrder, objectGroup in piggyBanks %}
<tbody>
<tr>
<td><small>{{ objectGroup.object_group_title }}</small></td>
</tr>
{% for piggy in objectGroup.piggy_banks %}
<tr class="sortable" data-id="{{ piggy.id }}" data-name="{{ piggy.name }}" data-order="{{ piggy.order }}" data-position="{{ loop.index0 }}">
<td class="visible-xs visible-sm hidden-md hidden-lg">
&nbsp;
</td>
<td class="visible-xs visible-sm hidden-md hidden-lg">
<div class="btn-group btn-group-xs">
<a href="{{ route('piggy-banks.remove-money-mobile', piggy.id) }}" class="btn btn-default btn-xs"><i class="fa fa-minus"></i></a>
<a href="{{ route('piggy-banks.add-money-mobile', piggy.id) }}" class="btn btn-default btn-xs"><i class="fa fa-plus"></i></a>
</div>
</td>
<td style="width:60px;" class="hidden-sm hidden-xs">
<i class="fa fa-fw fa-bars handle"></i>
<i class="loadSpin"></i>
</td>
<td style="width:100px;" class="hidden-sm hidden-xs">
<div class="btn-group btn-group-xs">
<a href="{{ route('piggy-banks.edit', piggy.id) }}" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
<a href="{{ route('piggy-banks.delete', piggy.id) }}" class="btn btn-danger btn-xs"><i class="fa fa-trash fa-fw"></i></a>
</div>
</td>
<td>
<a href="{{ route('piggy-banks.show', piggy.id) }}" title="{{ piggy.account_name }}">{{ piggy.name }}</a>
{% if piggy.attachments.count > 0 %}
<i class="fa fa-fw fa-paperclip"></i>
{% endif %}
</td>
<td style="text-align: right;" class="piggySaved">
<span title="Saved so far"
style="text-align:right;">{{ formatAmountBySymbol(piggy.current_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;width:40px;">
{% if piggy.current_amount > 0 %}
<a href="{{ route('piggy-banks.remove-money', piggy.id) }}" class="btn btn-default btn-xs removeMoney" data-id="{{ piggy.id }}">
<i data-id="{{ piggy.id }}" class="fa fa-minus"></i></a>
{% endif %}
</td>
<td class="hidden-sm hidden-xs piggyBar">
<div class="progress progress" style="margin-bottom:0;">
<div
{% if piggy.percentage == 100 %}
class="progress-bar progress-bar-success"
{% elseif piggy.percentage == 0 %}
class="progress-bar progress-bar-warning"
{% else %}
class="progress-bar progress-bar-info"
{% endif %}
role="progressbar" aria-valuenow="{{ piggy.percentage }}" aria-valuemin="0" aria-valuemax="100"
style="min-width: 30px;width: {{ piggy.percentage }}%;">
{{ piggy.percentage }}%
</div>
</div>
</td>
<td class="hidden-sm hidden-xs" style="width:40px;">
{% if piggy.left_to_save > 0 %}
<a href="{{ route('piggy-banks.add-money', piggy.id) }}" class="btn btn-default btn-xs addMoney" data-id="{{ piggy.id }}">
<i data-id="{{ piggy.id }}" class="fa fa-plus"></i></a>
{% endif %}
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;">
<span title="{{ 'target_amount'|_ }}">{{ formatAmountBySymbol(piggy.target_amount,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;">
{% if piggy.left_to_save > 0 %}
<span title="{{ 'left_to_save'|_ }}">{{ formatAmountBySymbol(piggy.left_to_save,piggy.currency_symbol,piggy.currency_decimal_places) }}</span>
{% endif %}
</td>
<td class="hidden-sm hidden-xs" style="text-align:right;">
{% if piggy.target_date %}
{{ formatAmountBySymbol(piggy.save_per_month, piggy.currency_symbol, piggy.currency_decimal_places) }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
{% endfor %}
</tbody>
</table>
<div style="padding-left:8px;">
{{ piggyBanks.render|raw }}
</div>

View File

@@ -33,7 +33,7 @@
{{ ExpandedForm.date('targetdate') }}
{{ ExpandedForm.textarea('notes', null, {helpText: trans('firefly.field_supports_markdown')} ) }}
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
{#{{ ExpandedForm.objectGroup('object_group') }}#}
{{ ExpandedForm.objectGroup() }}
</div>
</div>
</div>
@@ -63,6 +63,10 @@
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}

View File

@@ -36,6 +36,7 @@
{{ ExpandedForm.date('targetdate') }}
{{ ExpandedForm.textarea('notes', null, {helpText: trans('firefly.field_supports_markdown')}) }}
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
{{ ExpandedForm.objectGroup() }}
</div>
</div>
</div>
@@ -65,6 +66,9 @@
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/piggy-banks/create.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
{# auto complete for object groups #}
<script type="text/javascript" src="v1/js/lib/typeahead/typeahead.bundle.min.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
<script type="text/javascript" src="v1/js/ff/object-groups/create-edit.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
{% endblock %}
{% block styles %}

View File

@@ -582,6 +582,7 @@ Route::group(
Route::get('expense-accounts', ['uses' => 'Json\AutoCompleteController@expenseAccounts', 'as' => 'autocomplete.expense-accounts']);
Route::get('asset-accounts', ['uses' => 'Json\AutoCompleteController@assetAccounts', 'as' => 'autocomplete.asset-accounts']);
Route::get('budgets', ['uses' => 'Json\AutoCompleteController@budgets', 'as' => 'autocomplete.budgets']);
Route::get('object-groups', ['uses' => 'Json\AutoCompleteController@objectGroups', 'as' => 'autocomplete.object-groups']);
Route::get('bills', ['uses' => 'Json\AutoCompleteController@bills', 'as' => 'autocomplete.bills']);
Route::get('categories', ['uses' => 'Json\AutoCompleteController@categories', 'as' => 'autocomplete.categories']);
Route::get('currencies', ['uses' => 'Json\AutoCompleteController@currencies', 'as' => 'autocomplete.currencies']);
@@ -636,22 +637,23 @@ Route::group(
Route::group(
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'piggy-banks', 'as' => 'piggy-banks.'],
static function () {
Route::get('', ['uses' => 'PiggyBankController@index', 'as' => 'index']);
Route::get('add/{piggyBank}', ['uses' => 'PiggyBankController@add', 'as' => 'add-money']);
Route::get('remove/{piggyBank}', ['uses' => 'PiggyBankController@remove', 'as' => 'remove-money']);
Route::get('add-money/{piggyBank}', ['uses' => 'PiggyBankController@addMobile', 'as' => 'add-money-mobile']);
Route::get('remove-money/{piggyBank}', ['uses' => 'PiggyBankController@removeMobile', 'as' => 'remove-money-mobile']);
Route::get('create', ['uses' => 'PiggyBankController@create', 'as' => 'create']);
Route::get('edit/{piggyBank}', ['uses' => 'PiggyBankController@edit', 'as' => 'edit']);
Route::get('delete/{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'delete']);
Route::get('show/{piggyBank}', ['uses' => 'PiggyBankController@show', 'as' => 'show']);
Route::post('store', ['uses' => 'PiggyBankController@store', 'as' => 'store']);
Route::post('update/{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'update']);
Route::post('destroy/{piggyBank}', ['uses' => 'PiggyBankController@destroy', 'as' => 'destroy']);
Route::post('add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'add']);
Route::post('remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'remove']);
Route::post('set-order/{piggyBank}', ['uses' => 'PiggyBankController@setOrder', 'as' => 'set-order']);
Route::get('', ['uses' => 'PiggyBank\IndexController@index', 'as' => 'index']);
Route::get('add/{piggyBank}', ['uses' => 'PiggyBank\AmountController@add', 'as' => 'add-money']);
Route::get('remove/{piggyBank}', ['uses' => 'PiggyBank\AmountController@remove', 'as' => 'remove-money']);
Route::get('add-money/{piggyBank}', ['uses' => 'PiggyBank\AmountController@addMobile', 'as' => 'add-money-mobile']);
Route::get('remove-money/{piggyBank}', ['uses' => 'PiggyBank\AmountController@removeMobile', 'as' => 'remove-money-mobile']);
Route::get('create', ['uses' => 'PiggyBank\CreateController@create', 'as' => 'create']);
Route::get('edit/{piggyBank}', ['uses' => 'PiggyBank\EditController@edit', 'as' => 'edit']);
Route::get('delete/{piggyBank}', ['uses' => 'PiggyBank\DeleteController@delete', 'as' => 'delete']);
Route::get('show/{piggyBank}', ['uses' => 'PiggyBank\ShowController@show', 'as' => 'show']);
Route::post('store', ['uses' => 'PiggyBank\CreateController@store', 'as' => 'store']);
Route::post('update/{piggyBank}', ['uses' => 'PiggyBank\EditController@update', 'as' => 'update']);
Route::post('destroy/{piggyBank}', ['uses' => 'PiggyBank\DeleteController@destroy', 'as' => 'destroy']);
Route::post('add/{piggyBank}', ['uses' => 'PiggyBank\AmountController@postAdd', 'as' => 'add']);
Route::post('remove/{piggyBank}', ['uses' => 'PiggyBank\AmountController@postRemove', 'as' => 'remove']);
Route::post('set-order/{piggyBank}', ['uses' => 'PiggyBank\IndexController@setOrder', 'as' => 'set-order']);
}
);