diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index d38012e6a2..9c384b4166 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -21,6 +21,7 @@ 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\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Http\Request; @@ -61,6 +62,27 @@ class JsonController extends Controller return Response::json(['html' => $view]); } + /** + * Returns a JSON list of all accounts. + * + * @param AccountRepositoryInterface $repository + * + * @return \Illuminate\Http\JsonResponse + * + */ + public function allAccounts(AccountRepositoryInterface $repository) + { + $return = array_unique( + $repository->getAccountsByType( + [AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET] + )->pluck('name')->toArray() + ); + sort($return); + + return Response::json($return); + + } + /** * @param BillRepositoryInterface $repository * @@ -166,11 +188,8 @@ class JsonController extends Controller */ public function categories(CRI $repository) { - $list = $repository->getCategories(); - $return = []; - foreach ($list as $entry) { - $return[] = $entry->name; - } + $return = array_unique($repository->getCategories()->pluck('name')->toArray()); + sort($return); return Response::json($return); } @@ -195,14 +214,10 @@ class JsonController extends Controller */ public function expenseAccounts(AccountRepositoryInterface $repository) { - $list = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]); - $return = []; - foreach ($list as $entry) { - $return[] = $entry->name; - } + $return = array_unique($repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY])->pluck('name')->toArray()); + sort($return); return Response::json($return); - } /** @@ -213,14 +228,10 @@ class JsonController extends Controller */ public function revenueAccounts(AccountRepositoryInterface $repository) { - $list = $repository->getAccountsByType([AccountType::REVENUE]); - $return = []; - foreach ($list as $entry) { - $return[] = $entry->name; - } + $return = array_unique($repository->getAccountsByType([AccountType::REVENUE])->pluck('name')->toArray()); + sort($return); return Response::json($return); - } /** @@ -232,11 +243,8 @@ class JsonController extends Controller */ public function tags(TagRepositoryInterface $tagRepository) { - $list = $tagRepository->get(); - $return = []; - foreach ($list as $entry) { - $return[] = $entry->tag; - } + $return = array_unique($tagRepository->get()->pluck('tag')->toArray()); + sort($return); return Response::json($return); @@ -270,6 +278,22 @@ 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 @@ -278,25 +302,29 @@ class JsonController extends Controller */ public function transactionJournals(JournalCollectorInterface $collector, string $what) { - $descriptions = []; $type = config('firefly.transactionTypesByWhat.' . $what); $types = [$type]; - // use journal collector instead: $collector->setTypes($types)->setLimit(100)->setPage(1); - $journals = $collector->getJournals(); - foreach ($journals as $j) { - $descriptions[] = $j->description; - } + $return = array_unique($collector->getJournals()->pluck('description')->toArray()); + sort($return); - $descriptions = array_unique($descriptions); - sort($descriptions); - - return Response::json($descriptions); + return Response::json($return); } + /** + * + */ + public function transactionTypes(JournalRepositoryInterface $repository) + { + $return = array_unique($repository->getTransactionTypes()->pluck('type')->toArray()); + sort($return); + + return Response::json($return); + } + /** * @param Request $request * diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 2093793c8d..7dcc7996db 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -137,6 +137,14 @@ class JournalRepository implements JournalRepositoryInterface return $entry; } + /** + * @return Collection + */ + public function getTransactionTypes(): Collection + { + return TransactionType::orderBy('type', 'ASC')->get(); + } + /** * @param array $data * diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index fb9779eec3..ab17ab22a2 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -16,6 +16,7 @@ namespace FireflyIII\Repositories\Journal; use FireflyIII\Models\Account; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; /** @@ -36,6 +37,11 @@ interface JournalRepositoryInterface */ public function convert(TransactionJournal $journal, TransactionType $type, Account $source, Account $destination): MessageBag; + /** + * @return Collection + */ + public function getTransactionTypes(): Collection; + /** * Deletes a journal. * diff --git a/public/js/ff/rules/create-edit.js b/public/js/ff/rules/create-edit.js index cd36a7b1ad..1205cfd728 100644 --- a/public/js/ff/rules/create-edit.js +++ b/public/js/ff/rules/create-edit.js @@ -11,25 +11,47 @@ var triggerCount = 0; var actionCount = 0; +/** + * This method triggers when a new trigger must be added to the form. + */ function addNewTrigger() { "use strict"; triggerCount++; + // get the HTML for the new trigger $.getJSON('json/trigger', {count: triggerCount}).done(function (data) { + + // append it: $('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) + }); + + // update all "select trigger type" dropdowns + // so the accompanying text-box has the correct autocomplete. + onAddNewTrigger(); + + }).fail(function () { alert('Cannot get a new trigger.'); }); } +/** + * Method triggers when a new action must be added to the form.. + */ function addNewAction() { "use strict"; actionCount++; @@ -49,6 +71,11 @@ function addNewAction() { }); } +/** + * Method fires when a trigger must be removed from the form. + * + * @param e + */ function removeTrigger(e) { "use strict"; var target = $(e.target); @@ -64,6 +91,11 @@ function removeTrigger(e) { } } +/** + * Method fires when an action must be removed from the form. + * + * @param e + */ function removeAction(e) { "use strict"; var target = $(e.target); @@ -79,6 +111,72 @@ function removeAction(e) { } } +/** + * Method fires when a new trigger is added. It will update ALL trigger value input fields. + */ +function onAddNewTrigger() { + "use strict"; + console.log('updateTriggerAutoComplete'); + $.each($('.rule-trigger-holder'), function (i, v) { + var holder = $(v); + var select = holder.find('select'); + console.log('Now at input #' + i); + updateTriggerAutoComplete(select); + }); +} + +/** + * Creates a nice auto complete trigger depending on the type of the select list value thing. + * + * @param selectList + */ +function updateTriggerAutoComplete(selectList) { + // 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-trigger-value["]'); + switch (selectList.val()) { + default: + input.typeahead('destroy'); + console.log('Cannot or will not add autocomplete to "' + selectList.val() + '"'); + break; + case 'from_account_starts': + case 'from_account_ends': + case 'from_account_is': + case 'from_account_contains': + case 'to_account_starts': + case 'to_account_ends': + case 'to_account_is': + case 'to_account_contains': + createAutoComplete(input, 'json/all-accounts'); + break; + case 'transaction_type': + createAutoComplete(input, 'json/transaction-types'); + break; + case 'description_starts': + case 'description_ends': + case 'description_contains': + case 'description_is': + createAutoComplete(input, 'json/transaction-journals/all'); + break; + } +} + +/** + * Create actual autocomplete + * @param input + * @param URI + */ +function createAutoComplete(input, URI) { + console.log('Will create auto-complete for "' + URI + '".'); + input.typeahead('destroy'); + $.getJSON(URI).done(function (data) { + input.typeahead({source: data}); + console.log('Created new auto-complete!'); + }); + +} + function testRuleTriggers() { "use strict"; diff --git a/public/js/ff/rules/create.js b/public/js/ff/rules/create.js index ffa65be20e..2ffb875eb6 100644 --- a/public/js/ff/rules/create.js +++ b/public/js/ff/rules/create.js @@ -20,7 +20,6 @@ $(function () { addNewAction(); } - $('.add_rule_trigger').click(function () { addNewTrigger(); diff --git a/resources/views/rules/partials/trigger.twig b/resources/views/rules/partials/trigger.twig index 2f60699ea4..ea9ea7b9e6 100644 --- a/resources/views/rules/partials/trigger.twig +++ b/resources/views/rules/partials/trigger.twig @@ -1,4 +1,4 @@ -