mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-11-22 00:47:24 -06:00
Can sort and group bills.
This commit is contained in:
parent
029774687c
commit
e337bcf8bd
@ -32,6 +32,8 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
|
||||
use FireflyIII\Transformers\BillTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||
|
||||
/**
|
||||
@ -174,4 +176,27 @@ class IndexController extends Controller
|
||||
|
||||
return $sums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order of a bill.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function setOrder(Request $request, Bill $bill): JsonResponse
|
||||
{
|
||||
$objectGroupTitle = (string)$request->get('objectGroupTitle');
|
||||
$newOrder = (int) $request->get('order');
|
||||
$this->repository->setOrder($bill, $newOrder);
|
||||
if ('' !== $objectGroupTitle) {
|
||||
$this->repository->setObjectGroup($bill, $objectGroupTitle);
|
||||
}
|
||||
if ('' === $objectGroupTitle) {
|
||||
$this->repository->removeObjectGroup($bill);
|
||||
}
|
||||
|
||||
return response()->json(['data' => 'OK']);
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ class IndexController extends Controller
|
||||
*/
|
||||
public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
$objectGroupTitle = $request->get('objectGroupTitle');
|
||||
$objectGroupTitle = (string) $request->get('objectGroupTitle');
|
||||
$newOrder = (int) $request->get('order');
|
||||
$this->piggyRepos->setOrder($piggyBank, $newOrder);
|
||||
if ('' !== $objectGroupTitle) {
|
||||
|
@ -32,6 +32,7 @@ use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Services\Internal\Destroy\BillDestroyService;
|
||||
use FireflyIII\Services\Internal\Update\BillUpdateService;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
@ -48,6 +49,7 @@ use Storage;
|
||||
*/
|
||||
class BillRepository implements BillRepositoryInterface
|
||||
{
|
||||
use CreatesObjectGroups;
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
@ -730,4 +732,36 @@ class BillRepository implements BillRepositoryInterface
|
||||
$current++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill
|
||||
{
|
||||
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
||||
if (null !== $objectGroup) {
|
||||
$bill->objectGroups()->sync([$objectGroup->id]);
|
||||
}
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function removeObjectGroup(Bill $bill): Bill
|
||||
{
|
||||
$bill->objectGroups()->sync([]);
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setOrder(Bill $bill, int $order): void
|
||||
{
|
||||
$bill->order = $order;
|
||||
$bill->save();
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,21 @@ use Illuminate\Support\Collection;
|
||||
interface BillRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param string $objectGroupTitle
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function setObjectGroup(Bill $bill, string $objectGroupTitle): Bill;
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function removeObjectGroup(Bill $bill): Bill;
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*/
|
||||
@ -45,6 +60,14 @@ interface BillRepositoryInterface
|
||||
*/
|
||||
public function correctOrder(): void;
|
||||
|
||||
/**
|
||||
* Set specific piggy bank to specific order.
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @param int $order
|
||||
*/
|
||||
public function setOrder(Bill $bill, int $order): void;
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
|
@ -89,12 +89,13 @@ class BillTransformer extends AbstractTransformer
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
'name' => $bill->name,
|
||||
'amount_min' => round((float)$bill->amount_min, $currency->decimal_places),
|
||||
'amount_max' => round((float)$bill->amount_max, $currency->decimal_places),
|
||||
'amount_min' => round((float) $bill->amount_min, $currency->decimal_places),
|
||||
'amount_max' => round((float) $bill->amount_max, $currency->decimal_places),
|
||||
'date' => $bill->date->format('Y-m-d'),
|
||||
'repeat_freq' => $bill->repeat_freq,
|
||||
'skip' => (int)$bill->skip,
|
||||
'skip' => (int) $bill->skip,
|
||||
'active' => $bill->active,
|
||||
'order' => (int) $bill->order,
|
||||
'notes' => $notes,
|
||||
'next_expected_match' => $paidData['next_expected_match'],
|
||||
'pay_dates' => $payDates,
|
||||
|
30
composer.lock
generated
30
composer.lock
generated
@ -1414,16 +1414,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v7.17.2",
|
||||
"version": "v7.18.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "d16ff3a0a66d98e04163456b39c4b7302cf50a40"
|
||||
"reference": "116b508bafd81de97b1c09744445d32a91076b60"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/d16ff3a0a66d98e04163456b39c4b7302cf50a40",
|
||||
"reference": "d16ff3a0a66d98e04163456b39c4b7302cf50a40",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/116b508bafd81de97b1c09744445d32a91076b60",
|
||||
"reference": "116b508bafd81de97b1c09744445d32a91076b60",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1567,7 +1567,7 @@
|
||||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"time": "2020-06-24T13:11:25+00:00"
|
||||
"time": "2020-06-30T13:52:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
@ -1644,16 +1644,16 @@
|
||||
},
|
||||
{
|
||||
"name": "laravel/ui",
|
||||
"version": "v2.0.3",
|
||||
"version": "v2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/ui.git",
|
||||
"reference": "15368c5328efb7ce94f35ca750acde9b496ab1b1"
|
||||
"reference": "da9350533d0da60d5dc42fb7de9c561c72129bba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/ui/zipball/15368c5328efb7ce94f35ca750acde9b496ab1b1",
|
||||
"reference": "15368c5328efb7ce94f35ca750acde9b496ab1b1",
|
||||
"url": "https://api.github.com/repos/laravel/ui/zipball/da9350533d0da60d5dc42fb7de9c561c72129bba",
|
||||
"reference": "da9350533d0da60d5dc42fb7de9c561c72129bba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1695,7 +1695,7 @@
|
||||
"laravel",
|
||||
"ui"
|
||||
],
|
||||
"time": "2020-04-29T15:06:45+00:00"
|
||||
"time": "2020-06-30T20:56:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravelcollective/html",
|
||||
@ -7443,16 +7443,16 @@
|
||||
},
|
||||
{
|
||||
"name": "myclabs/deep-copy",
|
||||
"version": "1.10.0",
|
||||
"version": "1.10.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/DeepCopy.git",
|
||||
"reference": "5796d127b0c4ff505b77455148ea9d5269d99758"
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/5796d127b0c4ff505b77455148ea9d5269d99758",
|
||||
"reference": "5796d127b0c4ff505b77455148ea9d5269d99758",
|
||||
"url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"reference": "969b211f9a51aa1f6c01d1d2aef56d3bd91598e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -7493,7 +7493,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-06-28T07:02:41+00:00"
|
||||
"time": "2020-06-29T13:22:24+00:00"
|
||||
},
|
||||
{
|
||||
"name": "netresearch/jsonmapper",
|
||||
|
3
public/v1/css/firefly.css
vendored
3
public/v1/css/firefly.css
vendored
@ -93,6 +93,9 @@ p.tagcloud .label {
|
||||
.rule-handle {
|
||||
cursor: move;
|
||||
}
|
||||
.bill-handle {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
body.waiting * {
|
||||
cursor: progress;
|
||||
|
91
public/v1/js/ff/bills/index.js
vendored
Normal file
91
public/v1/js/ff/bills/index.js
vendored
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* index.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: token */
|
||||
var fixBillHelper = function (e, tr) {
|
||||
"use strict";
|
||||
var $originals = tr.children();
|
||||
var $helper = tr.clone();
|
||||
$helper.children().each(function (index) {
|
||||
// Set helper cell sizes to match the original sizes
|
||||
$(this).width($originals.eq(index).width());
|
||||
});
|
||||
return $helper;
|
||||
};
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
$('#bill-sortable').find('tbody').sortable(
|
||||
{
|
||||
helper: fixBillHelper,
|
||||
stop: stopSorting,
|
||||
connectWith: '.bill-connected-list',
|
||||
items: 'tr.bill-sortable',
|
||||
handle: '.bill-handle',
|
||||
start: function (event, ui) {
|
||||
// Build a placeholder cell that spans all the cells in the row
|
||||
var cellCount = 0;
|
||||
$('td, th', ui.helper).each(function () {
|
||||
// For each TD or TH try and get it's colspan attribute, and add that or 1 to the total
|
||||
var colspan = 1;
|
||||
var colspanAttr = $(this).attr('colspan');
|
||||
if (colspanAttr > 1) {
|
||||
colspan = colspanAttr;
|
||||
}
|
||||
cellCount += colspan;
|
||||
});
|
||||
|
||||
// Add the placeholder UI - note that this is the item's content, so TD rather than TR
|
||||
ui.placeholder.html('<td colspan="' + cellCount + '"> </td>');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
function stopSorting() {
|
||||
"use strict";
|
||||
|
||||
$.each($('#bill-sortable>tbody>tr.bill-sortable'), function (i, v) {
|
||||
var holder = $(v);
|
||||
var parentBody = holder.parent();
|
||||
var objectGroupTitle = parentBody.data('title');
|
||||
var position = parseInt(holder.data('position'));
|
||||
var originalOrder = parseInt(holder.data('order'));
|
||||
var name = holder.data('name');
|
||||
var id = parseInt(holder.data('id'));
|
||||
var newOrder;
|
||||
if (position === i) {
|
||||
// not changed, position is what it should be.
|
||||
return;
|
||||
}
|
||||
if (position < i) {
|
||||
// position is less.
|
||||
console.log('"' + name + '" ("' + objectGroupTitle + '") has moved down from position ' + originalOrder + ' to ' + (i + 1));
|
||||
}
|
||||
if (position > i) {
|
||||
console.log('"' + name + '" ("' + objectGroupTitle + '") has moved up from position ' + originalOrder + ' to ' + (i + 1));
|
||||
}
|
||||
// update position:
|
||||
holder.data('position', i);
|
||||
newOrder = i+1;
|
||||
|
||||
$.post('bills/set-order/' + id, {order: newOrder, objectGroupTitle: objectGroupTitle, _token: token})
|
||||
});
|
||||
}
|
@ -41,8 +41,6 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script type="text/javascript" nonce="{{ JS_NONCE }}">
|
||||
var start = '2018-01-01';
|
||||
var end = '2018-01-31';
|
||||
</script>
|
||||
<script src="v1/js/lib/jquery-ui.min.js?v={{ FF_VERSION }}" type="text/javascript" nonce="{{ JS_NONCE }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/bills/index.js?v={{ FF_VERSION }}" nonce="{{ JS_NONCE }}"></script>
|
||||
{% endblock %}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div style="padding-left:8px;">
|
||||
{{ paginator.render|raw }}
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<table class="table table-hover" id="bill-sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="hidden-sm hidden-xs"> </th>
|
||||
@ -23,7 +23,7 @@
|
||||
<td colspan="6"><small>{{ objectGroup.object_group_title }}</small></td>
|
||||
</tr>
|
||||
{% for entry in objectGroup.bills %}
|
||||
<tr{% if not entry.active %} data-disablesort="true"{% endif %}>
|
||||
<tr class="bill-sortable" data-id="{{ entry.id }}" data-name="{{ entry.name }}" data-order="{{ entry.order }}" data-position="{{ loop.index0 }}">
|
||||
<td class="hidden-sm hidden-xs">
|
||||
<i class="fa fa-fw fa-bars bill-handle"></i>
|
||||
</td>
|
||||
|
@ -194,6 +194,8 @@ Route::group(
|
||||
Route::post('store', ['uses' => 'Bill\CreateController@store', 'as' => 'store']);
|
||||
Route::post('update/{bill}', ['uses' => 'Bill\EditController@update', 'as' => 'update']);
|
||||
Route::post('destroy/{bill}', ['uses' => 'Bill\DeleteController@destroy', 'as' => 'destroy']);
|
||||
|
||||
Route::post('set-order/{bill}', ['uses' => 'Bill\IndexController@setOrder', 'as' => 'set-order']);
|
||||
}
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user