mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-23 04:46:44 +00:00
New features for rules in search.
This commit is contained in:
@@ -92,14 +92,7 @@ class IndexController extends Controller
|
||||
public function search(Rule $rule): RedirectResponse
|
||||
{
|
||||
$route = route('search.index');
|
||||
$params = [];
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if ('user_action' !== $trigger->trigger_type) {
|
||||
$params[] = sprintf('%s:"%s"', OperatorQuerySearch::getRootOperator($trigger->trigger_type), $trigger->trigger_value);
|
||||
}
|
||||
}
|
||||
$query = implode(' ', $params);
|
||||
$query = $this->ruleRepos->getSearchQuery($rule);
|
||||
$route = sprintf('%s?%s', $route, http_build_query(['search' => $query, 'rule' => $rule->id]));
|
||||
|
||||
return redirect($route);
|
||||
|
@@ -189,4 +189,51 @@ class SelectController extends Controller
|
||||
return response()->json(['html' => $view, 'warning' => $warning]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows the user to test a certain set of rule triggers. The rule triggers are grabbed from
|
||||
* the rule itself.
|
||||
*
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return JsonResponse
|
||||
*
|
||||
*/
|
||||
public function testTriggersByRule(Rule $rule): JsonResponse
|
||||
{
|
||||
$triggers = $rule->ruleTriggers;
|
||||
|
||||
if (0 === count($triggers)) {
|
||||
return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
|
||||
// create new rule engine:
|
||||
$newRuleEngine = app(RuleEngineInterface::class);
|
||||
|
||||
// set rules:
|
||||
$newRuleEngine->setRules(new Collection([$rule]));
|
||||
$collection = $newRuleEngine->find();
|
||||
$collection = $collection->slice(0, 20);
|
||||
|
||||
$warning = '';
|
||||
if (0 === count($collection)) {
|
||||
$warning = (string) trans('firefly.warning_no_matching_transactions'); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// Return json response
|
||||
$view = 'ERROR, see logs.';
|
||||
try {
|
||||
$view = view('list.journals-array-tiny', ['groups' => $collection])->render();
|
||||
// @codeCoverageIgnoreStart
|
||||
} catch (Throwable $exception) {
|
||||
Log::error(sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage()));
|
||||
Log::error($exception->getTraceAsString());
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
return response()->json(['html' => $view, 'warning' => $warning]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use FireflyIII\Support\Search\SearchInterface;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -62,15 +63,33 @@ class SearchController extends Controller
|
||||
*/
|
||||
public function index(Request $request, SearchInterface $searcher)
|
||||
{
|
||||
// search params:
|
||||
$fullQuery = (string) $request->get('search');
|
||||
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
|
||||
$ruleId = (int) $request->get('rule');
|
||||
$rule = null;
|
||||
$ruleChanged = false;
|
||||
|
||||
// find rule, check if query is different, offer to update.
|
||||
$ruleRepository = app(RuleRepositoryInterface::class);
|
||||
$rule = $ruleRepository->find($ruleId);
|
||||
if (null !== $rule) {
|
||||
$originalQuery = $ruleRepository->getSearchQuery($rule);
|
||||
if ($originalQuery !== $fullQuery) {
|
||||
$ruleChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
// parse search terms:
|
||||
$searcher->parseQuery($fullQuery);
|
||||
$query = $searcher->getWordsAsString();
|
||||
$modifiers = $searcher->getModifiers();
|
||||
$subTitle = (string) trans('breadcrumbs.search_result', ['query' => $query]);
|
||||
|
||||
return view('search.index', compact('query', 'modifiers', 'page', 'fullQuery', 'subTitle'));
|
||||
// words from query and operators:
|
||||
$query = $searcher->getWordsAsString();
|
||||
$operators = $searcher->getOperators();
|
||||
|
||||
$subTitle = (string) trans('breadcrumbs.search_result', ['query' => $fullQuery]);
|
||||
|
||||
return view('search.index', compact('query', 'operators', 'page', 'rule', 'fullQuery', 'subTitle', 'ruleId', 'ruleChanged'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -27,6 +27,7 @@ use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Support\Search\OperatorQuerySearch;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@@ -535,4 +536,20 @@ class RuleRepository implements RuleRepositoryInterface
|
||||
}
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getSearchQuery(Rule $rule): string
|
||||
{
|
||||
$params = [];
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if ('user_action' !== $trigger->trigger_type) {
|
||||
$params[] = sprintf('%s:"%s"', OperatorQuerySearch::getRootOperator($trigger->trigger_type), $trigger->trigger_value);
|
||||
}
|
||||
}
|
||||
return implode(' ', $params);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -39,6 +39,14 @@ interface RuleRepositoryInterface
|
||||
*/
|
||||
public function count(): int;
|
||||
|
||||
/**
|
||||
* Return search query for rule.
|
||||
*
|
||||
* @param Rule $rule
|
||||
* @return string
|
||||
*/
|
||||
public function getSearchQuery(Rule $rule): string;
|
||||
|
||||
/**
|
||||
* @param Rule $rule
|
||||
* @param RuleGroup $ruleGroup
|
||||
|
@@ -318,6 +318,8 @@ return [
|
||||
'search_modifier_bill_is' => 'Bill is ":value"',
|
||||
'search_modifier_transaction_type' => 'Transaction type is ":value"',
|
||||
'search_modifier_tag_is' => 'Tag is ":value"',
|
||||
'update_rule_from_query' => 'Update rule ":rule" from search query',
|
||||
'create_rule_from_query' => 'Create new rule from search query',
|
||||
|
||||
// END
|
||||
'modifiers_applies_are' => 'The following modifiers are applied to the search as well:',
|
||||
|
@@ -72,27 +72,6 @@
|
||||
<tr class="single-rule" data-order="{{ rule.order }}" data-id="{{ rule.id }}" data-group-id="{{ ruleGroup.id }}" data-position="{{ loop.index0 }}">
|
||||
<td>
|
||||
<div class="btn-group btn-group-xs prio_buttons">
|
||||
{#
|
||||
{% if rule.order > 1 %}
|
||||
<a title="{{ 'rule_priority_up'|_ }}"
|
||||
href="{{ route('rules.up', rule.id) }}"
|
||||
class="btn btn-default"><span
|
||||
class="fa fa-fw fa-arrow-up"></span></a>
|
||||
{% else %}
|
||||
<button disabled="disabled" class="btn btn-default"><span
|
||||
class="fa fa-fw"></span></button>
|
||||
{% endif %}
|
||||
{% if rule.order < ruleGroup.rules.count %}
|
||||
<a title="{{ 'rule_priority_down'|_ }}"
|
||||
href="{{ route('rules.down', rule.id) }}"
|
||||
class="btn btn-default"><span
|
||||
class="fa fa-fw fa-arrow-down"></span>
|
||||
</a>
|
||||
{% else %}
|
||||
<button disabled="disabled" class="btn btn-default"><span
|
||||
class="fa fa-fw"></span></button>
|
||||
{% endif %}
|
||||
#}
|
||||
<i class="fa fa-fw fa-bars rule-handle"></i>
|
||||
</div>
|
||||
</td>
|
||||
@@ -109,21 +88,16 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="btn-group btn-group-xs test_buttons">
|
||||
{# show which transactions would match #}
|
||||
{% if rule.active %}
|
||||
<a href="#" class="btn btn-default test_rule_triggers" data-id="{{ rule.id }}"
|
||||
title="{{ 'test_rule_triggers'|_ }}"><i data-id="{{ rule.id }}"
|
||||
class="test_rule_triggers fa fa-fw fa-flask"></i></a>
|
||||
{# show which transactions would match #}
|
||||
<a href="{{ route('rules.search',rule.id) }}" class="btn btn-default {% if false == rule.strict %}test_rule_triggers{% endif %}" data-id="{{ rule.id }}" title="{{ 'test_rule_triggers'|_ }}"><i data-id="{{ rule.id }}" class="fa fa-fw fa-flask"></i></a>
|
||||
|
||||
{# actually execute rule #}
|
||||
<a href="{{ route('rules.select-transactions',rule.id) }}" class="btn btn-default"
|
||||
title=" {{ trans('firefly.apply_rule_selection', {title: rule.title}) }}">
|
||||
<i class="fa fa-fw fa-power-off "></i></a>
|
||||
<a href="{{ route('rules.select-transactions',rule.id) }}" class="btn btn-default" title=" {{ trans('firefly.apply_rule_selection', {title: rule.title}) }}"><i class="fa fa-fw fa-power-off "></i></a>
|
||||
{% endif %}
|
||||
|
||||
{# duplicate rule #}
|
||||
<a href="{{ route('rules.duplicate',rule.id) }}" class="btn btn-default"
|
||||
title=" {{ trans('firefly.duplicate_rule', {title: rule.title}) }}">
|
||||
<i class="fa fa-fw fa-copy"></i></a>
|
||||
<a href="{{ route('rules.duplicate',rule.id) }}" class="btn btn-default" title=" {{ trans('firefly.duplicate_rule', {title: rule.title}) }}"><i class="fa fa-fw fa-copy"></i></a>
|
||||
</div>
|
||||
</td>
|
||||
<td class="markdown">
|
||||
|
@@ -1,7 +1,7 @@
|
||||
{% extends "./layout/default" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, query) }}
|
||||
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, fullQuery) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@@ -26,20 +26,27 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-1 col-sm-10">
|
||||
<button type="submit" class="btn btn-default"><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 %}
|
||||
<a href="#" class="btn btn-default">{{ trans('firefly.update_rule_from_query', {rule: rule.title}) }}</a>
|
||||
{% endif %}
|
||||
<a href="#" class="btn btn-default">{{ 'create_rule_from_query'|_ }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% if 0 != ruleId %}
|
||||
<input type="hidden" name="rule" value="{{ ruleId }}" />
|
||||
{% endif %}
|
||||
</form>
|
||||
{% if '' != query %}
|
||||
<p>
|
||||
{{ trans('firefly.search_for_query', {query: query|escape})|raw}}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if modifiers|length > 0 %}
|
||||
{% if operators|length > 0 %}
|
||||
<p>{{ trans('firefly.modifiers_applies_are') }}</p>
|
||||
<ul>
|
||||
{% for modifier in modifiers %}
|
||||
<li>{{ trans('firefly.search_modifier_'~modifier.type, {value: modifier.value}) }}</li>
|
||||
{% for operator in operators %}
|
||||
<li>{{ trans('firefly.search_modifier_'~operator.type, {value: operator.value}) }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
@@ -920,6 +920,7 @@ Route::group(
|
||||
// select controller
|
||||
Route::get('test', ['uses' => 'Rule\SelectController@testTriggers', 'as' => 'test-triggers']);
|
||||
Route::get('test-rule/{rule}', ['uses' => 'Rule\SelectController@testTriggersByRule', 'as' => 'test-triggers-rule']);
|
||||
Route::get('search/{rule}', ['uses' => 'Rule\IndexController@search', 'as' => 'search']);
|
||||
Route::get('select/{rule}', ['uses' => 'Rule\SelectController@selectTransactions', 'as' => 'select-transactions']);
|
||||
Route::post('execute/{rule}', ['uses' => 'Rule\SelectController@execute', 'as' => 'execute']);
|
||||
|
||||
|
Reference in New Issue
Block a user