From 975133f7ec6a597fcfa213affc4ecdceb21c8c14 Mon Sep 17 00:00:00 2001 From: Pascal Baljet Date: Thu, 22 Dec 2022 13:05:07 +0100 Subject: [PATCH 1/3] WIP --- app/app/Http/UserTableView.php | 6 ++++ app/app/Models/User.php | 5 +++ app/database/factories/UserFactory.php | 1 + app/database/seeders/DatabaseSeeder.php | 6 ++-- lib/Components/Form.vue | 19 +++++++---- lib/Components/Table.vue | 24 ++++++++++++-- resources/views/form/input.blade.php | 1 + resources/views/form/select.blade.php | 1 + resources/views/table/body.blade.php | 2 +- resources/views/table/filters.blade.php | 36 +++++++++------------ resources/views/table/table.blade.php | 1 + src/ServiceProvider.php | 8 +++++ src/SpladeCore.php | 14 ++++++++ src/SpladeQueryBuilder.php | 42 ++++++++++++++++++++++-- src/Table/Column.php | 3 ++ src/Table/Filter.php | 3 ++ src/Table/HasColumns.php | 4 ++- src/Table/HasFilters.php | 43 ++++++++++++++++++++++++- 18 files changed, 182 insertions(+), 37 deletions(-) diff --git a/app/app/Http/UserTableView.php b/app/app/Http/UserTableView.php index 6c61f711..ce28bb80 100644 --- a/app/app/Http/UserTableView.php +++ b/app/app/Http/UserTableView.php @@ -6,6 +6,7 @@ use App\Tables\SpatieUsers; use App\Tables\SpladeUsers; use Illuminate\Support\Collection; +use ProtoneMedia\Splade\Facades\Splade; use ProtoneMedia\Splade\SpladeTable; use Spatie\QueryBuilder\AllowedFilter; use Spatie\QueryBuilder\QueryBuilder; @@ -55,6 +56,8 @@ public function spatieWrapped($paginateMethod) public function splade($paginateMethod) { + Splade::setFrontendTimezone(fn () => 'Europe/Amsterdam'); + return view('table.users', [ 'users' => SpladeTable::for(User::class) ->withGlobalSearch(columns: ['name', 'email']) @@ -62,7 +65,10 @@ public function splade($paginateMethod) ->column(key: 'name', searchable: true, sortable: true, canBeHidden: false) ->column(key: 'email', searchable: true, sortable: true) ->column(key: 'language_code', label: 'Language') + ->column(key: 'created_at', label: 'Created UTC', numeric: true) + ->column(key: 'created_at_amsterdam', label: 'Created Europe/Amsterdam', numeric: true) ->column(label: 'Actions') + ->dateRangeFilter(key: 'created_at') ->selectFilter(key: 'language_code', options: [ 'en' => 'English', 'nl' => 'Dutch', diff --git a/app/app/Models/User.php b/app/app/Models/User.php index 17686f7a..a391b0ef 100644 --- a/app/app/Models/User.php +++ b/app/app/Models/User.php @@ -45,6 +45,11 @@ class User extends Authenticatable implements HasMedia 'is_admin' => 'boolean', ]; + public function getCreatedAtAmsterdamAttribute() + { + return $this->created_at->clone()->timezone('Europe/Amsterdam')->format('Y-m-d H:i:s'); + } + public function tags() { return $this->belongsToMany(Tag::class); diff --git a/app/database/factories/UserFactory.php b/app/database/factories/UserFactory.php index 4b5b2769..ffd688b9 100644 --- a/app/database/factories/UserFactory.php +++ b/app/database/factories/UserFactory.php @@ -24,6 +24,7 @@ public function definition() 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), 'language_code' => fake()->randomElement(['en', 'nl']), + 'created_at' => fake()->dateTimeBetween('-1 years'), ]; } diff --git a/app/database/seeders/DatabaseSeeder.php b/app/database/seeders/DatabaseSeeder.php index 9bc4411c..7c50f4e5 100644 --- a/app/database/seeders/DatabaseSeeder.php +++ b/app/database/seeders/DatabaseSeeder.php @@ -9,6 +9,7 @@ use Database\Factories\TagFactory; use Database\Factories\UserFactory; use Illuminate\Database\Seeder; +use Illuminate\Support\Carbon; class DatabaseSeeder extends Seeder { @@ -25,8 +26,9 @@ public function run() /** @var User $user */ $firstUser = UserFactory::new()->create([ - 'name' => 'Test User', - 'email' => 'test@example.com', + 'name' => 'Test User', + 'email' => 'test@example.com', + 'created_at' => Carbon::createFromFormat('Y-m-d H:i:s', '2022-12-01 00:00:00', 'Europe/Amsterdam')->timezone('UTC'), ]); static::giveUserMedia($firstUser); diff --git a/lib/Components/Form.vue b/lib/Components/Form.vue index 615cb4b0..8f90399f 100644 --- a/lib/Components/Form.vue +++ b/lib/Components/Form.vue @@ -107,7 +107,7 @@ export default { }, }, - emits: ["success", "error"], + emits: ["success", "error", "change"], data() { return { @@ -183,11 +183,18 @@ export default { this.missingAttributes = []; // Create watchers - if(this.submitOnChange === true) { - this.$watch("values", () => { - this.$nextTick(() => this.request()); - }, { deep: true }); - }else if(isArray(this.submitOnChange)) { + + this.$watch("values", () => { + this.$nextTick(() => { + this.$emit("change", this.values); + + if(this.submitOnChange === true){ + this.request(); + } + }); + }, { deep: true }); + + if(isArray(this.submitOnChange)) { this.submitOnChange.forEach((key) => { this.$watch(`values.${key}`, () => { this.$nextTick(() => this.request()); diff --git a/lib/Components/Table.vue b/lib/Components/Table.vue index 62a06767..af42c3f4 100644 --- a/lib/Components/Table.vue +++ b/lib/Components/Table.vue @@ -45,7 +45,15 @@ export default { type: Number, required: false, default: 0 - } + }, + + filterValues: { + type: Object, + required: false, + default() { + return {}; + } + }, }, data() { @@ -55,7 +63,8 @@ export default { forcedVisibleSearchInputs: [], debounceUpdateQuery: null, isLoading: false, - processingAction: false + processingAction: false, + preventReload: false, }; }, @@ -143,6 +152,14 @@ export default { }, methods: { + updateFilterValues(values) { + forOwn(values, (value, key) => { + if(this.filterValues[key] != value) { + this.updateQuery(`filter[${key}]`, value); + } + }); + }, + visitLink(url, type, $event) { if($event?.target?.tagName === "A" || $event?.target?.tagName === "BUTTON") { return; @@ -359,6 +376,8 @@ export default { queryString += "&"; } + value=encodeURIComponent(value); + queryString += `${key}=${value}`; }); @@ -463,6 +482,7 @@ export default { performBulkAction: this.performBulkAction, processingAction: this.processingAction, isLoading: this.isLoading, + updateFilterValues: this.updateFilterValues, }); }, }; diff --git a/resources/views/form/input.blade.php b/resources/views/form/input.blade.php index 9b959cd5..e021eef3 100644 --- a/resources/views/form/input.blade.php +++ b/resources/views/form/input.blade.php @@ -21,6 +21,7 @@ 'min-w-0 flex-1 rounded-none' => $append || $prepend, 'rounded-l-md' => $append && !$prepend, 'rounded-r-md' => !$append && $prepend, + 'text-sm' => $attributes->classHas('text-sm') ])->merge([ 'name' => $name, 'type' => $type, diff --git a/resources/views/form/select.blade.php b/resources/views/form/select.blade.php index f86831b0..5f6b4da5 100644 --- a/resources/views/form/select.blade.php +++ b/resources/views/form/select.blade.php @@ -19,6 +19,7 @@
- @foreach($filter->options() as $optionKey => $option) - - @endforeach - - @endif +
+ @if($filter->type === \ProtoneMedia\Splade\Table\Filter::TYPE_DATE_RANGE) + + @elseif($filter->type === \ProtoneMedia\Splade\Table\Filter::TYPE_SELECT) + + @endif +
- - @endforeach + @endforeach + \ No newline at end of file diff --git a/resources/views/table/table.blade.php b/resources/views/table/table.blade.php index 96df86ba..5c802e39 100644 --- a/resources/views/table/table.blade.php +++ b/resources/views/table/table.blade.php @@ -5,6 +5,7 @@ :default-visible-toggleable-columns="@js($table->defaultVisibleToggleableColumns())" :items-on-this-page="@js($table->totalOnThisPage())" :items-on-all-pages="@js($table->totalOnAllPages())" + :filter-values="@js($table->filterValues())" >