From 9705ee76e891eeb65ce66bfe8d52dbd309624f88 Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 28 Sep 2026 18:33:14 +0200 Subject: [PATCH] First attempts at filter + view. --- app/Api/V1/Requests/Generic/FilterRequest.php | 75 +++++++++++++++++++ .../Requests/Models/Account/ShowRequest.php | 2 + app/Rules/IsValidFilterInstruction.php | 43 +++++++++++ .../assets/v3/js/pages/accounts/index.js | 4 +- .../assets/v3/js/pages/dashboard/dashboard.js | 4 + 5 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 app/Api/V1/Requests/Generic/FilterRequest.php create mode 100644 app/Rules/IsValidFilterInstruction.php diff --git a/app/Api/V1/Requests/Generic/FilterRequest.php b/app/Api/V1/Requests/Generic/FilterRequest.php new file mode 100644 index 0000000000..89a6c95efd --- /dev/null +++ b/app/Api/V1/Requests/Generic/FilterRequest.php @@ -0,0 +1,75 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests\Generic; + +use FireflyIII\Api\V1\Requests\ApiRequest; +use FireflyIII\Rules\IsValidFilterInstruction; +use FireflyIII\Rules\IsValidSortInstruction; +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Contracts\Validation\Validator; +use RuntimeException; + +class FilterRequest extends ApiRequest +{ + use ChecksLogin; + use ConvertsDataTypes; + private ?string $filterClass = null; + + public function handleConfig(array $config): void + { + parent::handleConfig($config); + + $this->filterClass = $config['filter_class'] ?? null; + + if (null === $this->filterClass) { + throw new RuntimeException('FilterRequest requires a filter_class config'); + } + } + + public function rules(): array + { + return [ + 'filter.*' => ['min:0','max:255', $this->required, new IsValidFilterInstruction((string) $this->filterClass)], + ]; + } + + public function withValidator(Validator $validator): void + { + $validator->after(function (Validator $validator): void { + if (count($validator->failed()) > 0) { + return; + } + var_dump($this->input('filter'));exit; + $filter = $this->convertToFilter(); + $this->attributes->set('filter', $filter); + }); + } + private function convertToFilter(string $value): array { + var_dump($value); + exit; + return []; + } +} diff --git a/app/Api/V1/Requests/Models/Account/ShowRequest.php b/app/Api/V1/Requests/Models/Account/ShowRequest.php index f303c645de..e5b8c26d4f 100644 --- a/app/Api/V1/Requests/Models/Account/ShowRequest.php +++ b/app/Api/V1/Requests/Models/Account/ShowRequest.php @@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Requests\AggregateFormRequest; use FireflyIII\Api\V1\Requests\DateRangeRequest; use FireflyIII\Api\V1\Requests\DateRequest; use FireflyIII\Api\V1\Requests\Generic\ActiveObjectRequest; +use FireflyIII\Api\V1\Requests\Generic\FilterRequest; use FireflyIII\Api\V1\Requests\PaginationRequest; use FireflyIII\Models\Account; @@ -37,6 +38,7 @@ class ShowRequest extends AggregateFormRequest { return [ [PaginationRequest::class, 'sort_class' => Account::class], + [FilterRequest::class, 'filter_class' => Account::class], DateRangeRequest::class, ActiveObjectRequest::class, DateRequest::class, diff --git a/app/Rules/IsValidFilterInstruction.php b/app/Rules/IsValidFilterInstruction.php new file mode 100644 index 0000000000..5fc32153ab --- /dev/null +++ b/app/Rules/IsValidFilterInstruction.php @@ -0,0 +1,43 @@ +. + */ + +namespace FireflyIII\Rules; + +use Closure; +use Illuminate\Contracts\Validation\ValidationRule; + +class IsValidFilterInstruction implements ValidationRule +{ + public function __construct( + private readonly string $class + ) {} + + #[\Override] + public function validate(string $attribute, mixed $value, Closure $fail): void + { + if('' === (string)$value) { + return; + } + var_dump($attribute); + var_dump($value); + // TODO: Implement validate() method. + } +} diff --git a/resources/assets/v3/js/pages/accounts/index.js b/resources/assets/v3/js/pages/accounts/index.js index c64c223626..33bec441d2 100644 --- a/resources/assets/v3/js/pages/accounts/index.js +++ b/resources/assets/v3/js/pages/accounts/index.js @@ -124,7 +124,7 @@ let index = function () { // hide search again document.querySelectorAll("table.sortable .hide-button").forEach((el) => { - el.addEventListener("click", (event) => { + el.addEventListener("click", () => { let column = el.dataset.column; // show search input again document.querySelector(`span.title[data-column="${column}"]`).classList.remove('d-none'); @@ -141,7 +141,7 @@ let index = function () { // add filterable click events. document.querySelectorAll("table.sortable .search-button").forEach((el) => { - el.addEventListener("click", (event) => { + el.addEventListener("click", () => { let column = el.dataset.column; // hide search buttons etc. el.classList.add('d-none'); diff --git a/resources/assets/v3/js/pages/dashboard/dashboard.js b/resources/assets/v3/js/pages/dashboard/dashboard.js index 934f8ecfcf..55f262d033 100644 --- a/resources/assets/v3/js/pages/dashboard/dashboard.js +++ b/resources/assets/v3/js/pages/dashboard/dashboard.js @@ -35,6 +35,10 @@ let index = function () { anonymous: false, loadingPiggyBanks: true, init() { + + console.log('I am translation'); + console.log(i18next.t(format(new Date(), "d MMMM yyyy 'o' HH:mm"))); + getVariable("anonymous").then((value) => { let start = new Date(window.store.get("start")); let end = new Date(window.store.get("end"));