From 4270fe07abfe0e3124ff4d25ca78e4339e662eb2 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 22 Jan 2017 09:15:53 +0100 Subject: [PATCH] Rules now have auto-complete. --- app/Http/Controllers/JsonController.php | 62 +++++--- public/js/ff/rules/create-edit.js | 170 ++++++++++++++++++--- public/js/ff/rules/create.js | 40 ----- public/js/ff/rules/edit.js | 53 ------- resources/views/rules/partials/action.twig | 2 +- resources/views/rules/rule/create.twig | 6 +- resources/views/rules/rule/edit.twig | 4 +- routes/web.php | 1 + 8 files changed, 191 insertions(+), 147 deletions(-) delete mode 100644 public/js/ff/rules/create.js delete mode 100644 public/js/ff/rules/edit.js diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 9c384b4166..94ed5988e5 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -20,7 +20,8 @@ use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Repositories\Category\CategoryRepositoryInterface as CRI; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\CacheProperties; @@ -50,6 +51,7 @@ class JsonController extends Controller */ public function action(Request $request) { + sleep(5); $count = intval($request->get('count')) > 0 ? intval($request->get('count')) : 1; $keys = array_keys(config('firefly.rule-actions')); $actions = []; @@ -83,6 +85,22 @@ class JsonController extends Controller } + /** + * @param JournalCollectorInterface $collector + * + * @return \Illuminate\Http\JsonResponse + */ + public function allTransactionJournals(JournalCollectorInterface $collector) + { + $collector->setLimit(100)->setPage(1); + $return = array_unique($collector->getJournals()->pluck('description')->toArray()); + sort($return); + + return Response::json($return); + + + } + /** * @param BillRepositoryInterface $repository * @@ -180,13 +198,26 @@ class JsonController extends Controller } /** - * Returns a list of categories. - * - * @param CRI $repository + * @param BudgetRepositoryInterface $repository * * @return \Illuminate\Http\JsonResponse */ - public function categories(CRI $repository) + public function budgets(BudgetRepositoryInterface $repository) + { + $return = array_unique($repository->getBudgets()->pluck('name')->toArray()); + sort($return); + + return Response::json($return); + } + + /** + * Returns a list of categories. + * + * @param CategoryRepositoryInterface $repository + * + * @return \Illuminate\Http\JsonResponse + */ + public function categories(CategoryRepositoryInterface $repository) { $return = array_unique($repository->getCategories()->pluck('name')->toArray()); sort($return); @@ -278,22 +309,6 @@ class JsonController extends Controller return Response::json(['steps' => $steps, 'template' => $template]); } - /** - * @param JournalCollectorInterface $collector - * - * @return \Illuminate\Http\JsonResponse - */ - public function allTransactionJournals(JournalCollectorInterface $collector) - { - $collector->setLimit(100)->setPage(1); - $return = array_unique($collector->getJournals()->pluck('description')->toArray()); - sort($return); - - return Response::json($return); - - - } - /** * @param JournalCollectorInterface $collector * @param string $what @@ -302,8 +317,8 @@ class JsonController extends Controller */ public function transactionJournals(JournalCollectorInterface $collector, string $what) { - $type = config('firefly.transactionTypesByWhat.' . $what); - $types = [$type]; + $type = config('firefly.transactionTypesByWhat.' . $what); + $types = [$type]; $collector->setTypes($types)->setLimit(100)->setPage(1); $return = array_unique($collector->getJournals()->pluck('description')->toArray()); @@ -332,6 +347,7 @@ class JsonController extends Controller */ public function trigger(Request $request) { + sleep(5); $count = intval($request->get('count')) > 0 ? intval($request->get('count')) : 1; $keys = array_keys(config('firefly.rule-triggers')); $triggers = []; diff --git a/public/js/ff/rules/create-edit.js b/public/js/ff/rules/create-edit.js index 1205cfd728..ebee001611 100644 --- a/public/js/ff/rules/create-edit.js +++ b/public/js/ff/rules/create-edit.js @@ -8,8 +8,34 @@ * See the LICENSE file for details. */ -var triggerCount = 0; -var actionCount = 0; +/** global: triggerCount, actionCount */ + +$(function () { + "use strict"; + if (triggerCount === 0) { + console.log('addNewTrigger() because count is zero'); + addNewTrigger(); + } + if (actionCount === 0) { + console.log('addNewAction() because count is zero'); + addNewAction(); + } + if (triggerCount > 0) { + console.log('onAddNewTrigger() because count is > zero'); + onAddNewTrigger(); + } + + if (actionCount > 0) { + console.log('onAddNewAction() because count is > zero'); + onAddNewAction(); + } + + $('.add_rule_trigger').click(addNewTrigger); + $('.add_rule_action').click(addNewAction); + $('.test_rule_triggers').click(testRuleTriggers); + $('.remove-trigger').unbind('click').click(removeTrigger); + $('.remove-action').unbind('click').click(removeAction); +}); /** * This method triggers when a new trigger must be added to the form. @@ -17,35 +43,33 @@ var actionCount = 0; function addNewTrigger() { "use strict"; triggerCount++; + console.log('click on add_rule_trigger'); + + // disable the button + $('.add_rule_trigger').attr('disabled', 'disabled'); + console.log('Disabled the button'); // get the HTML for the new trigger $.getJSON('json/trigger', {count: triggerCount}).done(function (data) { + console.log('new trigger html retrieved'); - // append it: + // append it to the other triggers $('tbody.rule-trigger-tbody').append(data.html); - - // update all "remove trigger"-buttons so they will respond correctly - // and remove the trigger. - $('.remove-trigger').unbind('click').click(function (e) { - removeTrigger(e); - - return false; - }); - - // update all "select trigger type" dropdown buttons so they will respond correctly - $('select[name^="rule-trigger["]').unbind('change').change(function (e) { - var target = $(e.target); - updateTriggerAutoComplete(target) - }); + $('.remove-trigger').unbind('click').click(removeTrigger); // update all "select trigger type" dropdowns // so the accompanying text-box has the correct autocomplete. onAddNewTrigger(); + $('.add_rule_trigger').removeAttr('disabled'); + console.log('Enabled the button'); + }).fail(function () { alert('Cannot get a new trigger.'); + $('.add_rule_trigger').removeAttr('disabled'); }); + return false; } @@ -54,21 +78,34 @@ function addNewTrigger() { */ function addNewAction() { "use strict"; + console.log('click on add_rule_action'); actionCount++; + // disable the button + $('.add_rule_action').attr('disabled', 'disabled'); + console.log('Disabled the button'); + + $.getJSON('json/action', {count: actionCount}).done(function (data) { $('tbody.rule-action-tbody').append(data.html); // add action things. - $('.remove-action').unbind('click').click(function (e) { - removeAction(e); + $('.remove-action').unbind('click').click(removeAction); - return false; - }); + // update all "select trigger type" dropdowns + // so the accompanying text-box has the correct autocomplete. + onAddNewAction(); + + $('.add_rule_action').removeAttr('disabled'); + console.log('Enabled the button'); }).fail(function () { alert('Cannot get a new action.'); + + $('.add_rule_action').removeAttr('disabled'); + console.log('Enabled the button'); }); + return false; } /** @@ -78,6 +115,7 @@ function addNewAction() { */ function removeTrigger(e) { "use strict"; + console.log('click on remove-trigger'); var target = $(e.target); if (target.prop("tagName") == "I") { target = target.parent(); @@ -87,8 +125,10 @@ function removeTrigger(e) { // if now at zero, immediatly add one again: if ($('.rule-trigger-tbody tr').length == 0) { + console.log('Add a new trigger again'); addNewTrigger(); } + return false; } /** @@ -98,6 +138,7 @@ function removeTrigger(e) { */ function removeAction(e) { "use strict"; + console.log('click on remove-action'); var target = $(e.target); if (target.prop("tagName") == "I") { target = target.parent(); @@ -107,8 +148,32 @@ function removeAction(e) { // if now at zero, immediatly add one again: if ($('.rule-action-tbody tr').length == 0) { + console.log('Add a new action again'); addNewAction(); } + return false; + +} + +/** + * Method fires when a new action is added. It will update ALL action value input fields. + */ +function onAddNewAction() { + "use strict"; + console.log('now in onAddNewAction'); + + // update all "select action type" dropdown buttons so they will respond correctly + $('select[name^="rule-action["]').unbind('change').change(function (e) { + var target = $(e.target); + updateActionInput(target) + }); + + $.each($('.rule-action-holder'), function (i, v) { + console.log('Update action input for row ' + i); + var holder = $(v); + var select = holder.find('select'); + updateActionInput(select); + }); } /** @@ -116,21 +181,74 @@ function removeAction(e) { */ function onAddNewTrigger() { "use strict"; - console.log('updateTriggerAutoComplete'); + console.log('now in onAddNewTrigger'); + + // update all "select trigger type" dropdown buttons so they will respond correctly + $('select[name^="rule-trigger["]').unbind('change').change(function (e) { + var target = $(e.target); + updateTriggerInput(target) + }); + $.each($('.rule-trigger-holder'), function (i, v) { + console.log('Update trigger input for row ' + i); var holder = $(v); var select = holder.find('select'); - console.log('Now at input #' + i); - updateTriggerAutoComplete(select); + updateTriggerInput(select); }); } +/** + * Creates a nice auto complete action depending on the type of the select list value thing. + * + * @param selectList + */ +function updateActionInput(selectList) { + console.log('now in updateActionInput'); + // the actual row this select list is in: + var parent = selectList.parent().parent(); + // the text input we're looking for: + var input = parent.find('input[name^="rule-action-value["]'); + input.removeAttr('disabled'); + switch (selectList.val()) { + default: + input.typeahead('destroy'); + console.log('Cannot or will not do stuff to "' + selectList.val() + '"'); + break; + case 'set_category': + console.log('Create autocomplete for category list'); + createAutoComplete(input, 'json/categories'); + break; + case 'clear_category': + case 'clear_budget': + case 'remove_all_tags': + input.attr('disabled', 'disabled'); + break; + case 'set_budget': + console.log('Create autocomplete for budget list'); + createAutoComplete(input, 'json/budgets'); + break; + case 'add_tag': + case 'remove_tag': + createAutoComplete(input, 'json/tags'); + break; + case 'set_description': + createAutoComplete(input, 'json/transaction-journals/all'); + break; + case 'set_source_account': + createAutoComplete(input, 'json/all-accounts'); + break; + case 'set_destination_account': + createAutoComplete(input, 'json/all-accounts'); + break; + } +} + /** * Creates a nice auto complete trigger depending on the type of the select list value thing. * * @param selectList */ -function updateTriggerAutoComplete(selectList) { +function updateTriggerInput(selectList) { // the actual row this select list is in: var parent = selectList.parent().parent(); // the text input we're looking for: @@ -179,6 +297,7 @@ function createAutoComplete(input, URI) { function testRuleTriggers() { "use strict"; + console.log('click on test_rule_triggers'); // Serialize all trigger data var triggerData = $(".rule-trigger-tbody").find("input[type=text], input[type=checkbox], select").serializeArray(); @@ -203,4 +322,5 @@ function testRuleTriggers() { }).fail(function () { alert('Cannot get transactions for given triggers.'); }); + return false; } \ No newline at end of file diff --git a/public/js/ff/rules/create.js b/public/js/ff/rules/create.js deleted file mode 100644 index 2ffb875eb6..0000000000 --- a/public/js/ff/rules/create.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * create.js - * Copyright (C) 2016 thegrumpydictator@gmail.com - * - * This software may be modified and distributed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International License. - * - * See the LICENSE file for details. - */ - -/** global: triggerCount, actionCount */ - - -$(function () { - "use strict"; - if (triggerCount === 0) { - addNewTrigger(); - } - if (actionCount === 0) { - addNewAction(); - } - - $('.add_rule_trigger').click(function () { - addNewTrigger(); - - return false; - }); - - $('.add_rule_action').click(function () { - addNewAction(); - - return false; - }); - - $('.test_rule_triggers').click(function () { - testRuleTriggers(); - - return false; - }); -}); diff --git a/public/js/ff/rules/edit.js b/public/js/ff/rules/edit.js deleted file mode 100644 index 893feff138..0000000000 --- a/public/js/ff/rules/edit.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * edit.js - * Copyright (C) 2016 thegrumpydictator@gmail.com - * - * This software may be modified and distributed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International License. - * - * See the LICENSE file for details. - */ - -/** global: triggerCount, actionCount */ - -$(function () { - "use strict"; - if (triggerCount === 0) { - addNewTrigger(); - } - if (actionCount === 0) { - addNewAction(); - } - - - $('.add_rule_trigger').click(function () { - addNewTrigger(); - - return false; - }); - - $('.test_rule_triggers').click(function () { - testRuleTriggers(); - - return false; - }); - - $('.add_rule_action').click(function () { - addNewAction(); - - return false; - }); - - $('.remove-trigger').unbind('click').click(function (e) { - removeTrigger(e); - - return false; - }); - - // add action things. - $('.remove-action').unbind('click').click(function (e) { - removeAction(e); - - return false; - }); -}); \ No newline at end of file diff --git a/resources/views/rules/partials/action.twig b/resources/views/rules/partials/action.twig index d3b215ee6b..f7e7a0886d 100644 --- a/resources/views/rules/partials/action.twig +++ b/resources/views/rules/partials/action.twig @@ -1,4 +1,4 @@ - + diff --git a/resources/views/rules/rule/create.twig b/resources/views/rules/rule/create.twig index f7b290a54f..dd17381052 100644 --- a/resources/views/rules/rule/create.twig +++ b/resources/views/rules/rule/create.twig @@ -63,7 +63,7 @@


- {{ 'add_rule_trigger'|_ }} + {{ 'test_rule_triggers'|_ }}

@@ -128,12 +128,12 @@ {% endblock %} {% block scripts %} - - + + {% endblock %} {% block styles %} {% endblock %} diff --git a/resources/views/rules/rule/edit.twig b/resources/views/rules/rule/edit.twig index 089d9f4e24..84f56a72a3 100644 --- a/resources/views/rules/rule/edit.twig +++ b/resources/views/rules/rule/edit.twig @@ -127,10 +127,10 @@ {% endblock %} {% block scripts %} - - + + {% endblock %} diff --git a/routes/web.php b/routes/web.php index 489b7b5762..bd438f5f59 100755 --- a/routes/web.php +++ b/routes/web.php @@ -383,6 +383,7 @@ Route::group( Route::get('all-accounts', ['uses' => 'JsonController@allAccounts', 'as' => 'all-accounts']); Route::get('revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'revenue-accounts']); Route::get('categories', ['uses' => 'JsonController@categories', 'as' => 'categories']); + Route::get('budgets', ['uses' => 'JsonController@budgets', 'as' => 'budgets']); Route::get('tags', ['uses' => 'JsonController@tags', 'as' => 'tags']); Route::get('tour', ['uses' => 'JsonController@tour', 'as' => 'tour']); Route::get('box/in', ['uses' => 'JsonController@boxIn', 'as' => 'box.in']);