From 25fa9e2e0f076e74d2403a2c89b45c6d7a171643 Mon Sep 17 00:00:00 2001 From: Joe <104938042+lrljoe@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:24:39 +0000 Subject: [PATCH 1/5] Add WireLinkColumn --- CHANGELOG.md | 4 ++ docs/columns/other-column-types.md | 35 +++++++++++++ .../views/includes/columns/wirelink.blade.php | 9 ++++ src/Views/Columns/WireLinkColumn.php | 45 ++++++++++++++++ .../WireLinkColumnConfiguration.php | 7 +++ src/Views/Traits/Core/HasActionCallback.php | 29 +++++++++++ src/Views/Traits/Core/HasConfirmation.php | 28 ++++++++++ .../Traits/Helpers/WireLinkColumnHelpers.php | 7 +++ tests/Views/Columns/WireLinkColumnTest.php | 51 +++++++++++++++++++ 9 files changed, 215 insertions(+) create mode 100644 resources/views/includes/columns/wirelink.blade.php create mode 100644 src/Views/Columns/WireLinkColumn.php create mode 100644 src/Views/Traits/Configuration/WireLinkColumnConfiguration.php create mode 100644 src/Views/Traits/Core/HasActionCallback.php create mode 100644 src/Views/Traits/Core/HasConfirmation.php create mode 100644 src/Views/Traits/Helpers/WireLinkColumnHelpers.php create mode 100644 tests/Views/Columns/WireLinkColumnTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d137430cf..23aceebc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to `laravel-livewire-tables` will be documented in this file +## [v3.2.1] - 2023-02-19 +### New Features +- Creation of new WireLink Column + ## [v3.2.0] - 2023-01-04 ### Tweaks - Migration to new Core Traits, and de-duplication of code by @lrljoe in https://github.com/rappasoft/laravel-livewire-tables/pull/1623 diff --git a/docs/columns/other-column-types.md b/docs/columns/other-column-types.md index dc80da449..0d15ab564 100644 --- a/docs/columns/other-column-types.md +++ b/docs/columns/other-column-types.md @@ -191,6 +191,41 @@ LinkColumn::make('Action') ]), ``` +## WireLinkColumn Columns + +WireLink columns provide a way to display Wired Links in your table without having to use `format()` or partial views, with or without a Confirmation Message + +WireLinkColumn requires title, and an "action", which must be a valid LiveWire method in the current class, or a global method + +Without a Confirmation Message +```php + WireLinkColumn::make("Delete Item") + ->title(fn($row) => 'Delete Item') + ->action(fn($row) => 'delete("'.$row->id.'")'), +``` + +You may also pass a string to "confirmMessage", which will utilise LiveWire 3's "wire:confirm" approach to display a confirmation modal. + +```php + WireLinkColumn::make("Delete Item") + ->title(fn($row) => 'Delete Item') + ->confirmMessage('Are you sure you want to delete this item?') + ->action(fn($row) => 'delete("'.$row->id.'")') + ->attributes(fn($row) => [ + 'class' => 'btn btn-danger', + ]), +``` + +And you may also pass an array of attributes, which will be applied to the "button" element used within the Column +```php + WireLinkColumn::make("Delete Item") + ->title(fn($row) => 'Delete Item') + ->action(fn($row) => 'delete("'.$row->id.'")') + ->attributes(fn($row) => [ + 'class' => 'btn btn-danger', + ]), +``` + ## Button Group Columns Button group columns let you provide an array of LinkColumns to display in a single cell. diff --git a/resources/views/includes/columns/wirelink.blade.php b/resources/views/includes/columns/wirelink.blade.php new file mode 100644 index 000000000..191ba5f1d --- /dev/null +++ b/resources/views/includes/columns/wirelink.blade.php @@ -0,0 +1,9 @@ + diff --git a/src/Views/Columns/WireLinkColumn.php b/src/Views/Columns/WireLinkColumn.php new file mode 100644 index 000000000..11f8c11cd --- /dev/null +++ b/src/Views/Columns/WireLinkColumn.php @@ -0,0 +1,45 @@ +label(fn () => null); + } + + public function getContents(Model $row): null|string|\Illuminate\Support\HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View + { + if (! $this->hasTitleCallback()) { + throw new DataTableConfigurationException('You must specify a title callback for a WireLink column.'); + } + + if (! $this->hasActionCallback()) { + throw new DataTableConfigurationException('You must specify an action callback for a WireLink column.'); + } + + return view($this->getView()) + ->withColumn($this) + ->withTitle(app()->call($this->getTitleCallback(), ['row' => $row])) + ->withPath(app()->call($this->getActionCallback(), ['row' => $row])) + ->withAttributes($this->hasAttributesCallback() ? app()->call($this->getAttributesCallback(), ['row' => $row]) : []); + } +} diff --git a/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php b/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php new file mode 100644 index 000000000..5928593c7 --- /dev/null +++ b/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php @@ -0,0 +1,7 @@ +actionCallback = $callback; + + return $this; + } + + public function getActionCallback(): ?callable + { + return $this->actionCallback; + } + + public function hasActionCallback(): bool + { + return $this->actionCallback !== null; + } + +} diff --git a/src/Views/Traits/Core/HasConfirmation.php b/src/Views/Traits/Core/HasConfirmation.php new file mode 100644 index 000000000..deb7f802f --- /dev/null +++ b/src/Views/Traits/Core/HasConfirmation.php @@ -0,0 +1,28 @@ +confirmMessage = $confirmMessage; + + return $this; + } + + public function hasConfirmMessage(): bool + { + return isset($this->confirmMessage); + } + + public function getConfirmMessage(): string + { + return $this->confirmMessage; + } +} diff --git a/src/Views/Traits/Helpers/WireLinkColumnHelpers.php b/src/Views/Traits/Helpers/WireLinkColumnHelpers.php new file mode 100644 index 000000000..f98f239b6 --- /dev/null +++ b/src/Views/Traits/Helpers/WireLinkColumnHelpers.php @@ -0,0 +1,7 @@ +assertSame('Name', $column->getTitle()); + } + + /** @test */ + public function can_not_infer_field_name_from_title_if_no_from(): void + { + $column = WireLinkColumn::make('My Title'); + + $this->assertNull($column->getField()); + } + + /** @test */ + public function can_not_render_field_if_no_title_callback(): void + { + $this->expectException(DataTableConfigurationException::class); + + WireLinkColumn::make('Name')->getContents(Pet::find(1)); + } + + /** @test */ + public function can_not_render_field_if_no_location_callback(): void + { + $this->expectException(DataTableConfigurationException::class); + + WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->getContents(Pet::find(1)); + } + + /** @test */ + public function can_render_field_if_title_and_location_callback(): void + { + $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->location(fn ($row) => 'test'.$row->id)->getContents(Pet::find(1)); + + $this->assertNotEmpty($column); + } +} From d4b6330baa0bb5de6e14eef6954063c2dca97ccf Mon Sep 17 00:00:00 2001 From: Joe <104938042+lrljoe@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:37:02 +0000 Subject: [PATCH 2/5] Add Tests for ConfirmMessage --- tests/Views/Columns/WireLinkColumnTest.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tests/Views/Columns/WireLinkColumnTest.php b/tests/Views/Columns/WireLinkColumnTest.php index fe78977d6..96c0ad1a7 100644 --- a/tests/Views/Columns/WireLinkColumnTest.php +++ b/tests/Views/Columns/WireLinkColumnTest.php @@ -7,7 +7,7 @@ use Rappasoft\LaravelLivewireTables\Tests\TestCase; use Rappasoft\LaravelLivewireTables\Views\Columns\WireLinkColumn; -class tests/Views/Columns/LinkColumnTest.php extends TestCase +class WireLinkColumnTest extends TestCase { /** @test */ public function can_set_the_column_title(): void @@ -34,7 +34,7 @@ public function can_not_render_field_if_no_title_callback(): void } /** @test */ - public function can_not_render_field_if_no_location_callback(): void + public function can_not_render_field_if_no_action_callback(): void { $this->expectException(DataTableConfigurationException::class); @@ -42,10 +42,19 @@ public function can_not_render_field_if_no_location_callback(): void } /** @test */ - public function can_render_field_if_title_and_location_callback(): void + public function can_render_field_if_title_and_action_callback(): void { - $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->location(fn ($row) => 'test'.$row->id)->getContents(Pet::find(1)); + $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); $this->assertNotEmpty($column); } + + /** @test */ + public function can_render_field_if_confirm_set(): void + { + $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); + + $this->assertNotEmpty($column); + } + } From d4065b82d834391fe06db23c603fcb22118ba4f9 Mon Sep 17 00:00:00 2001 From: lrljoe Date: Tue, 20 Feb 2024 00:37:27 +0000 Subject: [PATCH 3/5] Fix styling --- src/Traits/Helpers/TableAttributeHelpers.php | 12 +-- src/Views/Columns/WireLinkColumn.php | 90 +++++++++---------- .../WireLinkColumnConfiguration.php | 14 +-- src/Views/Traits/Core/HasActionCallback.php | 57 ++++++------ src/Views/Traits/Core/HasConfirmation.php | 56 ++++++------ .../Traits/Helpers/WireLinkColumnHelpers.php | 14 +-- tests/Views/Columns/WireLinkColumnTest.php | 5 +- 7 files changed, 123 insertions(+), 125 deletions(-) diff --git a/src/Traits/Helpers/TableAttributeHelpers.php b/src/Traits/Helpers/TableAttributeHelpers.php index 25a970628..3da2da12e 100644 --- a/src/Traits/Helpers/TableAttributeHelpers.php +++ b/src/Traits/Helpers/TableAttributeHelpers.php @@ -16,7 +16,7 @@ public function getComponentWrapperAttributes(): array } /** - * @return array + * @return array */ public function getTableWrapperAttributes(): array { @@ -24,7 +24,7 @@ public function getTableWrapperAttributes(): array } /** - * @return array + * @return array */ public function getTableAttributes(): array { @@ -32,7 +32,7 @@ public function getTableAttributes(): array } /** - * @return array + * @return array */ public function getTheadAttributes(): array { @@ -40,7 +40,7 @@ public function getTheadAttributes(): array } /** - * @return array + * @return array */ public function getTbodyAttributes(): array { @@ -48,7 +48,7 @@ public function getTbodyAttributes(): array } /** - * @return array + * @return array */ public function getThAttributes(Column $column): array { @@ -56,7 +56,7 @@ public function getThAttributes(Column $column): array } /** - * @return array + * @return array */ public function getThSortButtonAttributes(Column $column): array { diff --git a/src/Views/Columns/WireLinkColumn.php b/src/Views/Columns/WireLinkColumn.php index 11f8c11cd..91665f288 100644 --- a/src/Views/Columns/WireLinkColumn.php +++ b/src/Views/Columns/WireLinkColumn.php @@ -1,45 +1,45 @@ -label(fn () => null); - } - - public function getContents(Model $row): null|string|\Illuminate\Support\HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View - { - if (! $this->hasTitleCallback()) { - throw new DataTableConfigurationException('You must specify a title callback for a WireLink column.'); - } - - if (! $this->hasActionCallback()) { - throw new DataTableConfigurationException('You must specify an action callback for a WireLink column.'); - } - - return view($this->getView()) - ->withColumn($this) - ->withTitle(app()->call($this->getTitleCallback(), ['row' => $row])) - ->withPath(app()->call($this->getActionCallback(), ['row' => $row])) - ->withAttributes($this->hasAttributesCallback() ? app()->call($this->getAttributesCallback(), ['row' => $row]) : []); - } -} +label(fn () => null); + } + + public function getContents(Model $row): null|string|\Illuminate\Support\HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View + { + if (! $this->hasTitleCallback()) { + throw new DataTableConfigurationException('You must specify a title callback for a WireLink column.'); + } + + if (! $this->hasActionCallback()) { + throw new DataTableConfigurationException('You must specify an action callback for a WireLink column.'); + } + + return view($this->getView()) + ->withColumn($this) + ->withTitle(app()->call($this->getTitleCallback(), ['row' => $row])) + ->withPath(app()->call($this->getActionCallback(), ['row' => $row])) + ->withAttributes($this->hasAttributesCallback() ? app()->call($this->getAttributesCallback(), ['row' => $row]) : []); + } +} diff --git a/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php b/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php index 5928593c7..b2aa49683 100644 --- a/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php +++ b/src/Views/Traits/Configuration/WireLinkColumnConfiguration.php @@ -1,7 +1,7 @@ -actionCallback = $callback; - - return $this; - } - - public function getActionCallback(): ?callable - { - return $this->actionCallback; - } - - public function hasActionCallback(): bool - { - return $this->actionCallback !== null; - } - -} +actionCallback = $callback; + + return $this; + } + + public function getActionCallback(): ?callable + { + return $this->actionCallback; + } + + public function hasActionCallback(): bool + { + return $this->actionCallback !== null; + } +} diff --git a/src/Views/Traits/Core/HasConfirmation.php b/src/Views/Traits/Core/HasConfirmation.php index deb7f802f..9a8597947 100644 --- a/src/Views/Traits/Core/HasConfirmation.php +++ b/src/Views/Traits/Core/HasConfirmation.php @@ -1,28 +1,28 @@ -confirmMessage = $confirmMessage; - - return $this; - } - - public function hasConfirmMessage(): bool - { - return isset($this->confirmMessage); - } - - public function getConfirmMessage(): string - { - return $this->confirmMessage; - } -} +confirmMessage = $confirmMessage; + + return $this; + } + + public function hasConfirmMessage(): bool + { + return isset($this->confirmMessage); + } + + public function getConfirmMessage(): string + { + return $this->confirmMessage; + } +} diff --git a/src/Views/Traits/Helpers/WireLinkColumnHelpers.php b/src/Views/Traits/Helpers/WireLinkColumnHelpers.php index f98f239b6..d342db23a 100644 --- a/src/Views/Traits/Helpers/WireLinkColumnHelpers.php +++ b/src/Views/Traits/Helpers/WireLinkColumnHelpers.php @@ -1,7 +1,7 @@ -title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); + $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); $this->assertNotEmpty($column); } @@ -52,9 +52,8 @@ public function can_render_field_if_title_and_action_callback(): void /** @test */ public function can_render_field_if_confirm_set(): void { - $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); + $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); $this->assertNotEmpty($column); } - } From c853810c21c1ef4a186a0da4c25bc92c8eec296f Mon Sep 17 00:00:00 2001 From: Joe <104938042+lrljoe@users.noreply.github.com> Date: Tue, 20 Feb 2024 00:39:17 +0000 Subject: [PATCH 4/5] Update Tests to use WireLinkColumn --- tests/Views/Columns/WireLinkColumnTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Views/Columns/WireLinkColumnTest.php b/tests/Views/Columns/WireLinkColumnTest.php index 9a75540b9..c9c4e1416 100644 --- a/tests/Views/Columns/WireLinkColumnTest.php +++ b/tests/Views/Columns/WireLinkColumnTest.php @@ -44,7 +44,7 @@ public function can_not_render_field_if_no_action_callback(): void /** @test */ public function can_render_field_if_title_and_action_callback(): void { - $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); + $column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); $this->assertNotEmpty($column); } @@ -52,7 +52,7 @@ public function can_render_field_if_title_and_action_callback(): void /** @test */ public function can_render_field_if_confirm_set(): void { - $column = LinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); + $column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); $this->assertNotEmpty($column); } From 0868d51f6183c0c8f843dbe28681ccfd2d18d62d Mon Sep 17 00:00:00 2001 From: lrljoe Date: Tue, 20 Feb 2024 00:39:41 +0000 Subject: [PATCH 5/5] Fix styling --- tests/Views/Columns/WireLinkColumnTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Views/Columns/WireLinkColumnTest.php b/tests/Views/Columns/WireLinkColumnTest.php index c9c4e1416..58981302f 100644 --- a/tests/Views/Columns/WireLinkColumnTest.php +++ b/tests/Views/Columns/WireLinkColumnTest.php @@ -44,7 +44,7 @@ public function can_not_render_field_if_no_action_callback(): void /** @test */ public function can_render_field_if_title_and_action_callback(): void { - $column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); + $column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->getContents(Pet::find(1)); $this->assertNotEmpty($column); } @@ -52,7 +52,7 @@ public function can_render_field_if_title_and_action_callback(): void /** @test */ public function can_render_field_if_confirm_set(): void { - $column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); + $column = WireLinkColumn::make('Name')->title(fn ($row) => 'Edit')->action(fn ($row) => 'delete("'.$row->id.'")')->confirmMessage('Test')->getContents(Pet::find(1)); $this->assertNotEmpty($column); }