mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-05 20:22:07 +00:00
Expand rule/search combination.
This commit is contained in:
@@ -32,11 +32,15 @@ use FireflyIII\Models\TransactionJournal;
|
|||||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
use FireflyIII\Support\Http\Controllers\ModelInformation;
|
use FireflyIII\Support\Http\Controllers\ModelInformation;
|
||||||
use FireflyIII\Support\Http\Controllers\RuleManagement;
|
use FireflyIII\Support\Http\Controllers\RuleManagement;
|
||||||
|
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||||
|
use FireflyIII\Support\Search\SearchInterface;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Redirector;
|
use Illuminate\Routing\Redirector;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
|
use Log;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateController
|
* Class CreateController
|
||||||
@@ -44,6 +48,7 @@ use Illuminate\View\View;
|
|||||||
class CreateController extends Controller
|
class CreateController extends Controller
|
||||||
{
|
{
|
||||||
use RuleManagement, ModelInformation;
|
use RuleManagement, ModelInformation;
|
||||||
|
|
||||||
/** @var RuleRepositoryInterface Rule repository */
|
/** @var RuleRepositoryInterface Rule repository */
|
||||||
private $ruleRepos;
|
private $ruleRepos;
|
||||||
|
|
||||||
@@ -86,6 +91,20 @@ class CreateController extends Controller
|
|||||||
$oldTriggers = [];
|
$oldTriggers = [];
|
||||||
$oldActions = [];
|
$oldActions = [];
|
||||||
|
|
||||||
|
// build triggers from query, if present.
|
||||||
|
$query = (string) $request->get('from_query');
|
||||||
|
if ('' !== $query) {
|
||||||
|
$search = app(SearchInterface::class);
|
||||||
|
$search->parseQuery($query);
|
||||||
|
$words = $search->getWordsAsString();
|
||||||
|
$operators = $search->getOperators()->toArray();
|
||||||
|
if ('' !== $words) {
|
||||||
|
session()->flash('warning', trans('firefly.rule_from_search_words', ['string' => $words]));
|
||||||
|
array_push($operators, ['type' => 'description_contains', 'value' => $words]);
|
||||||
|
}
|
||||||
|
$oldTriggers = $this->parseFromOperators($operators);
|
||||||
|
}
|
||||||
|
|
||||||
// restore actions and triggers from old input:
|
// restore actions and triggers from old input:
|
||||||
if ($request->old()) {
|
if ($request->old()) {
|
||||||
$oldTriggers = $this->getPreviousTriggers($request);
|
$oldTriggers = $this->getPreviousTriggers($request);
|
||||||
@@ -183,8 +202,8 @@ class CreateController extends Controller
|
|||||||
$subTitle = (string) trans('firefly.make_new_rule_no_group');
|
$subTitle = (string) trans('firefly.make_new_rule_no_group');
|
||||||
|
|
||||||
// get triggers and actions for journal.
|
// get triggers and actions for journal.
|
||||||
$oldTriggers = $this->getTriggersForJournal($journal);
|
$oldTriggers = $this->getTriggersForJournal($journal);
|
||||||
$oldActions = [];
|
$oldActions = [];
|
||||||
|
|
||||||
$this->createDefaultRuleGroup();
|
$this->createDefaultRuleGroup();
|
||||||
$this->createDefaultRule();
|
$this->createDefaultRule();
|
||||||
@@ -271,4 +290,45 @@ class CreateController extends Controller
|
|||||||
|
|
||||||
return $redirect;
|
return $redirect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $submittedOperators
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function parseFromOperators(array $submittedOperators): array
|
||||||
|
{
|
||||||
|
// TODO duplicated code.
|
||||||
|
$operators = config('firefly.search.operators');
|
||||||
|
$renderedEntries = [];
|
||||||
|
$triggers = [];
|
||||||
|
foreach ($operators as $key => $operator) {
|
||||||
|
if ('user_action' !== $key && false === $operator['alias']) {
|
||||||
|
|
||||||
|
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asort($triggers);
|
||||||
|
|
||||||
|
$index = 0;
|
||||||
|
foreach ($submittedOperators as $operator) {
|
||||||
|
try {
|
||||||
|
$renderedEntries[] = view(
|
||||||
|
'rules.partials.trigger',
|
||||||
|
[
|
||||||
|
'oldTrigger' => OperatorQuerySearch::getRootOperator($operator['type']),
|
||||||
|
'oldValue' => $operator['value'],
|
||||||
|
'oldChecked' => 1 === (int) ($oldTrigger['stop_processing'] ?? '0'),
|
||||||
|
'count' => $index + 1,
|
||||||
|
'triggers' => $triggers,
|
||||||
|
]
|
||||||
|
)->render();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||||
|
Log::error($e->getTraceAsString());
|
||||||
|
}
|
||||||
|
$index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $renderedEntries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,6 +30,8 @@ use FireflyIII\Models\Rule;
|
|||||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
use FireflyIII\Support\Http\Controllers\RenderPartialViews;
|
use FireflyIII\Support\Http\Controllers\RenderPartialViews;
|
||||||
use FireflyIII\Support\Http\Controllers\RuleManagement;
|
use FireflyIII\Support\Http\Controllers\RuleManagement;
|
||||||
|
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||||
|
use FireflyIII\Support\Search\SearchInterface;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -81,15 +83,31 @@ class EditController extends Controller
|
|||||||
$actionCount = 0;
|
$actionCount = 0;
|
||||||
$oldActions = [];
|
$oldActions = [];
|
||||||
$oldTriggers = [];
|
$oldTriggers = [];
|
||||||
|
|
||||||
|
// build triggers from query, if present.
|
||||||
|
$query = (string) $request->get('from_query');
|
||||||
|
if ('' !== $query) {
|
||||||
|
$search = app(SearchInterface::class);
|
||||||
|
$search->parseQuery($query);
|
||||||
|
$words = $search->getWordsAsString();
|
||||||
|
$operators = $search->getOperators()->toArray();
|
||||||
|
if ('' !== $words) {
|
||||||
|
session()->flash('warning', trans('firefly.rule_from_search_words', ['string' => $words]));
|
||||||
|
array_push($operators, ['type' => 'description_contains', 'value' => $words]);
|
||||||
|
}
|
||||||
|
$oldTriggers = $this->parseFromOperators($operators);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// has old input?
|
// has old input?
|
||||||
if (count($request->old()) > 0) {
|
if (count($request->old()) > 0) {
|
||||||
$oldTriggers = $this->getPreviousTriggers($request);
|
$oldTriggers = $this->getPreviousTriggers($request);
|
||||||
$triggerCount = count($oldTriggers);
|
|
||||||
$oldActions = $this->getPreviousActions($request);
|
$oldActions = $this->getPreviousActions($request);
|
||||||
$actionCount = count($oldActions);
|
|
||||||
}
|
}
|
||||||
|
$triggerCount = count($oldTriggers);
|
||||||
|
$actionCount = count($oldActions);
|
||||||
|
|
||||||
// overrule old input when it has no rule data:
|
// overrule old input and query data when it has no rule data:
|
||||||
if (0 === $triggerCount && 0 === $actionCount) {
|
if (0 === $triggerCount && 0 === $actionCount) {
|
||||||
$oldTriggers = $this->getCurrentTriggers($rule);
|
$oldTriggers = $this->getCurrentTriggers($rule);
|
||||||
$triggerCount = count($oldTriggers);
|
$triggerCount = count($oldTriggers);
|
||||||
@@ -146,4 +164,45 @@ class EditController extends Controller
|
|||||||
|
|
||||||
return $redirect;
|
return $redirect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $submittedOperators
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function parseFromOperators(array $submittedOperators): array
|
||||||
|
{
|
||||||
|
// TODO duplicated code.
|
||||||
|
$operators = config('firefly.search.operators');
|
||||||
|
$renderedEntries = [];
|
||||||
|
$triggers = [];
|
||||||
|
foreach ($operators as $key => $operator) {
|
||||||
|
if ('user_action' !== $key && false === $operator['alias']) {
|
||||||
|
|
||||||
|
$triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asort($triggers);
|
||||||
|
|
||||||
|
$index = 0;
|
||||||
|
foreach ($submittedOperators as $operator) {
|
||||||
|
try {
|
||||||
|
$renderedEntries[] = view(
|
||||||
|
'rules.partials.trigger',
|
||||||
|
[
|
||||||
|
'oldTrigger' => OperatorQuerySearch::getRootOperator($operator['type']),
|
||||||
|
'oldValue' => $operator['value'],
|
||||||
|
'oldChecked' => 1 === (int) ($oldTrigger['stop_processing'] ?? '0'),
|
||||||
|
'count' => $index + 1,
|
||||||
|
'triggers' => $triggers,
|
||||||
|
]
|
||||||
|
)->render();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
|
||||||
|
Log::error($e->getTraceAsString());
|
||||||
|
}
|
||||||
|
$index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $renderedEntries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||||
use League\CommonMark\CommonMarkConverter;
|
use League\CommonMark\CommonMarkConverter;
|
||||||
use Route;
|
use Route;
|
||||||
use Twig\Extension\AbstractExtension;
|
use Twig\Extension\AbstractExtension;
|
||||||
@@ -64,9 +65,20 @@ class General extends AbstractExtension
|
|||||||
$this->formatDate(),
|
$this->formatDate(),
|
||||||
$this->getMetaField(),
|
$this->getMetaField(),
|
||||||
$this->hasRole(),
|
$this->hasRole(),
|
||||||
|
$this->getRootSearchOperator(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getRootSearchOperator(): TwigFunction
|
||||||
|
{
|
||||||
|
return new TwigFunction(
|
||||||
|
'getRootSearchOperator',
|
||||||
|
static function (string $operator): string {
|
||||||
|
return OperatorQuerySearch::getRootOperator($operator);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will return "active" when a part of the route matches the argument.
|
* Will return "active" when a part of the route matches the argument.
|
||||||
* ie. "accounts" will match "accounts.index".
|
* ie. "accounts" will match "accounts.index".
|
||||||
|
@@ -320,6 +320,8 @@ return [
|
|||||||
'search_modifier_tag_is' => 'Tag is ":value"',
|
'search_modifier_tag_is' => 'Tag is ":value"',
|
||||||
'update_rule_from_query' => 'Update rule ":rule" from search query',
|
'update_rule_from_query' => 'Update rule ":rule" from search query',
|
||||||
'create_rule_from_query' => 'Create new rule from search query',
|
'create_rule_from_query' => 'Create new rule from search query',
|
||||||
|
'rule_from_search_words' => 'The rule engine has a hard time handling ":string". The suggested rule that fits your search query may give different results. Please verify the rule triggers carefully.',
|
||||||
|
|
||||||
|
|
||||||
// END
|
// END
|
||||||
'modifiers_applies_are' => 'The following modifiers are applied to the search as well:',
|
'modifiers_applies_are' => 'The following modifiers are applied to the search as well:',
|
||||||
|
@@ -128,7 +128,8 @@
|
|||||||
{% if not rule.active %}
|
{% if not rule.active %}
|
||||||
class="text-muted"
|
class="text-muted"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
data-id="{{ trigger.id }}">{{ trans(('firefly.rule_trigger_' ~ trigger.trigger_type), {trigger_value: trigger.trigger_value}) }}
|
data-id="{{ trigger.id }}">
|
||||||
|
{{ trans(('firefly.rule_trigger_' ~ getRootSearchOperator(trigger.trigger_type)), {trigger_value: trigger.trigger_value}) }}
|
||||||
|
|
||||||
{% if trigger.stop_processing %}
|
{% if trigger.stop_processing %}
|
||||||
<i class="fa fa-stop-circle-o"></i>
|
<i class="fa fa-stop-circle-o"></i>
|
||||||
|
@@ -28,9 +28,9 @@
|
|||||||
<div class="col-sm-offset-1 col-sm-10">
|
<div class="col-sm-offset-1 col-sm-10">
|
||||||
<button type="submit" class="btn btn-info"><i class="fa fa-search"></i> {{ 'search'|_ }}</button>
|
<button type="submit" class="btn btn-info"><i class="fa fa-search"></i> {{ 'search'|_ }}</button>
|
||||||
{% if ruleId > 0 and ruleChanged %}
|
{% if ruleId > 0 and ruleChanged %}
|
||||||
<a href="#" class="btn btn-default">{{ trans('firefly.update_rule_from_query', {rule: rule.title}) }}</a>
|
<a href="{{ route('rules.edit', [ruleId]) }}?from_query={{ fullQuery }}" class="btn btn-default">{{ trans('firefly.update_rule_from_query', {rule: rule.title}) }}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="#" class="btn btn-default">{{ 'create_rule_from_query'|_ }}</a>
|
<a href="{{ route('rules.create') }}?from_query={{ fullQuery }}" class="btn btn-default">{{ 'create_rule_from_query'|_ }}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if 0 != ruleId %}
|
{% if 0 != ruleId %}
|
||||||
|
Reference in New Issue
Block a user