New mass delete form and options. #241

This commit is contained in:
James Cole 2016-04-23 09:33:54 +02:00
parent f43938726a
commit 3948cb8e6c
13 changed files with 288 additions and 6 deletions

View File

@ -7,8 +7,10 @@ use Config;
use ExpandedForm;
use FireflyIII\Events\TransactionJournalStored;
use FireflyIII\Events\TransactionJournalUpdated;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Http\Requests\MassJournalRequest;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction;
@ -222,6 +224,76 @@ class TransactionController extends Controller
}
/**
* @param Collection $journals
*
* @return View
*/
public function massDelete(Collection $journals)
{
$subTitle = trans('firefly.mass_delete_journals');
// put previous url in session
Session::put('transactions.mass-delete.url', URL::previous());
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'mass-delete');
return view('transactions.mass-delete', compact('journals', 'subTitle'));
}
/**
* @param MassJournalRequest $request
* @param JournalRepositoryInterface $repository
*
* @return mixed
*/
public function massDestroy(MassJournalRequest $request, JournalRepositoryInterface $repository)
{
$ids = $request->get('confirm_mass_delete');
$set = new Collection;
if (is_array($ids)) {
/** @var int $journalId */
foreach ($ids as $journalId) {
/** @var TransactionJournal $journal */
$journal = $repository->find($journalId);
if (!is_null($journal->id) && $journalId == $journal->id) {
$set->push($journal);
}
}
}
unset($journal);
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
$repository->delete($journal);
}
Preferences::mark();
Session::flash('success', trans('firefly.mass_deleted_transactions_success'));
// redirect to previous URL:
return redirect(session('transactions.mass-delete.url'));
}
/**
* @param Collection $journals
*/
public function massEdit(Collection $journals)
{
throw new FireflyException('Mass editing of journals is not yet supported.');
}
/**
*
*/
public function massUpdate()
{
}
/**
* @param JournalRepositoryInterface $repository
*

View File

@ -0,0 +1,49 @@
<?php
/**
* MassJournalRequest.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
/**
* MassJournalRequest.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Http\Requests;
use Auth;
/**
* Class MassJournalRequest
*
*
* @package FireflyIII\Http\Requests
*/
class MassJournalRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
return [
'confirm_mass_delete.*' => 'required|belongsToUser:transaction_journals,id',
];
}
}

View File

@ -377,6 +377,12 @@ Route::group(
Route::post('/transaction/destroy/{tj}', ['uses' => 'TransactionController@destroy', 'as' => 'transactions.destroy']);
Route::post('/transaction/reorder', ['uses' => 'TransactionController@reorder', 'as' => 'transactions.reorder']);
// mass edit and mass delete.
Route::get('/transactions/mass-edit/{journalList}', ['uses' => 'TransactionController@massEdit', 'as' => 'transactions.mass-edit']);
Route::get('/transactions/mass-delete/{journalList}', ['uses' => 'TransactionController@massDelete', 'as' => 'transactions.mass-delete']);
Route::post('/transactions/mass-update/{journalList}', ['uses' => 'TransactionController@massUpdate', 'as' => 'transactions.mass-update']);
Route::post('/transactions/mass-destroy', ['uses' => 'TransactionController@massDestroy', 'as' => 'transactions.mass-destroy']);
/**
* POPUP Controllers
*/

View File

@ -51,6 +51,21 @@ class JournalRepository implements JournalRepositoryInterface
return true;
}
/**
* @param int $journalId
*
* @return TransactionJournal
*/
public function find(int $journalId) : TransactionJournal
{
$journal = $this->user->transactionjournals()->where('id', $journalId)->first();
if (is_null($journal)) {
return new TransactionJournal;
}
return $journal;
}
/**
* Get users first transaction journal
*

View File

@ -24,6 +24,13 @@ interface JournalRepositoryInterface
*/
public function delete(TransactionJournal $journal): bool;
/**
* @param int $journalId
*
* @return TransactionJournal
*/
public function find(int $journalId) : TransactionJournal;
/**
* Get users first transaction journal
*

View File

@ -38,7 +38,7 @@ class CategoryList implements BinderInterface
->where('user_id', Auth::user()->id)
->get();
// add empty budget if applicable.
// add empty category if applicable.
if (in_array('0', $ids)) {
$object->push(new Category);
}

View File

@ -0,0 +1,48 @@
<?php
/**
* JournalList.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Support\Binder;
use Auth;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class JournalList
*
* @package FireflyIII\Support\Binder
*/
class JournalList implements BinderInterface
{
/**
* @param $value
* @param $route
*
* @return mixed
*/
public static function routeBinder($value, $route): Collection
{
if (Auth::check()) {
$ids = explode(',', $value);
/** @var \Illuminate\Support\Collection $object */
$object = TransactionJournal::whereIn('transaction_journals.id', $ids)
->expanded()
->where('transaction_journals.user_id', Auth::user()->id)
->get(TransactionJournal::QUERYFIELDS);
if ($object->count() > 0) {
return $object;
}
}
throw new NotFoundHttpException;
}
}

View File

@ -80,7 +80,7 @@ class FireflyValidator extends Validator
$count = DB::table($parameters[0])->where('user_id', Auth::user()->id)->where($field, $value)->count();
if ($count == 1) {
if ($count === 1) {
return true;
}

View File

@ -173,6 +173,7 @@ return [
// lists
'accountList' => 'FireflyIII\Support\Binder\AccountList',
'budgetList' => 'FireflyIII\Support\Binder\BudgetList',
'journalList' => 'FireflyIII\Support\Binder\JournalList',
'categoryList' => 'FireflyIII\Support\Binder\CategoryList',
// others

View File

@ -29,7 +29,6 @@ $(document).ready(function () {
function goToMassEdit() {
"use strict";
var checkedArray = getCheckboxes();
console.log('Journals: ' + checkedArray);
// go to specially crafted URL:
window.location.href = 'transactions/mass-edit/' + checkedArray;
@ -39,7 +38,6 @@ function goToMassEdit() {
function goToMassDelete() {
"use strict";
var checkedArray = getCheckboxes();
console.log('Journals: ' + checkedArray);
// go to specially crafted URL:
window.location.href = 'transactions/mass-delete/' + checkedArray;
@ -63,7 +61,6 @@ function getCheckboxes() {
function countChecked() {
"use strict";
var checked = $('.select_all_single:checked').length;
console.log("Now " + checked + " selected.");
if (checked > 0) {
$('.mass_edit span').text(edit_selected_txt + ' (' + checked + ')')
$('.mass_delete span').text(delete_selected_txt + ' (' + checked + ')')
@ -88,9 +85,11 @@ function stopMassSelect() {
"use strict";
// uncheck all:
$('input[name="select_all"]').prop('checked', false);
uncheckAll();
countChecked();
// hide "select all" box in table header.
$('.select_boxes').hide();

View File

@ -560,6 +560,10 @@ return [
'stop_selection' => 'Stop selecting transactions',
'edit_selected' => 'Edit selected',
'delete_selected' => 'Delete selected',
'mass_delete_journals' => 'Delete a number of transactions',
'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be catious.',
// new user:
'welcome' => 'Welcome to Firefly!',
'createNewAsset' => 'Create a new asset account to get started. ' .

View File

@ -112,8 +112,11 @@ return [
'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
'mass_journal_are_you_sure' => 'Are you sure you want to delete these transactions?',
'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.',
'mass_make_selection' => 'You can still prevent items from being deleted by removing the checkbox.',
'delete_all_permanently' => 'Delete all permanently',
'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',

View File

@ -0,0 +1,78 @@
{% extends "./layout/default.twig" %}
{% block breadcrumbs %}
{{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName, journal) }}
{% endblock %}
{% block content %}
{{ Form.open({'class' : 'form-horizontal','id' : 'destroy','url' : route('transactions.mass-destroy')}) }}
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-8 coll-offset-md-2 col-sm-12">
<div class="box box-danger">
<div class="box-header with-border">
<h3 class="box-title">{{ 'mass_delete_journals'|_ }}</h3>
</div>
<div class="box-body">
<p class="text-danger">
{{ trans('form.permDeleteWarning') }}
{{ 'perm-delete-many'|_ }}
</p>
<p>
{{ trans('form.mass_journal_are_you_sure') }}
{{ trans('form.mass_make_selection') }}
</p>
<table class="table table-striped table-condensed">
<tr>
<th>&nbsp;</th>
<th>{{ trans('list.description') }}</th>
<th>{{ trans('list.amount') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.date') }}</th>
<th class="hidden-xs">{{ trans('list.from') }}</th>
<th class="hidden-xs">{{ trans('list.to') }}</th>
</tr>
{% for journal in journals %}
<tr>
<td>
<input type="checkbox" name="confirm_mass_delete[]" value="{{ journal.id }}" checked />
</td>
<td>
<a href="{{ route('transactions.show',journal.id) }}" title="{{ journal.description }}">{{ journal.description }}</a>
</td>
<td>
{{ journal|formatJournal }}
</td>
<td>
{{ journal.date.formatLocalized(monthAndDayFormat) }}
</td>
<td>
{% if journal.source_account_type == 'Cash account' %}
<span class="text-success">(cash)</span>
{% else %}
<a href="{{ route('accounts.show',journal.source_account_id) }}">{{ journal.source_account_name }}</a>
{% endif %}
</td>
<td>
{% if journal.destination_account_type == 'Cash account' %}
<span class="text-success">(cash)</span>
{% else %}
<a href="{{ route('accounts.show',journal.destination_account_id) }}">{{ journal.destination_account_name }}</a>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<div class="box-footer">
<input type="submit" name="submit" value="{{ trans('form.delete_all_permanently') }}" class="btn btn-danger pull-right"/>
<a href="{{ route('index') }}" class="btn-default btn">{{ trans('form.cancel') }}</a>
</div>
</div>
</div>
</div>
{{ Form.close|raw }}
{% endblock %}