Skip to content

Commit

Permalink
5.1.0 (#107)
Browse files Browse the repository at this point in the history
* Added ability to chain a `->when(bool $condition)` method to an instantiated head action, in order to enable it conditionally
* Added a new built-in `RedirectHeadAction`, that will be used by the pre-configured `CreateHeadAction`
* Added an optional `bool $openInNewWindow = false` to the `CreateHeadAction`
* Added a new [JavaScript snippet](/README.md#set-up-a-few-lines-of-javascript) to handle head action link opening in tab: you'll have to add it if you want to benefit from this new ability
  • Loading branch information
Okipa authored Oct 25, 2022
1 parent b2807c5 commit fe6a3dc
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 22 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ jobs:
- name: Code analysis
if: matrix.php == '8.1' && matrix.laravel == '9.*'
run: |
# Remove this line once Larastan and Livewire are working well together
sed -i -e 's#.*protected \$enablesPackageDiscoveries.*#&\nprotected function overrideApplicationBindings($app){return["livewire"=>"Livewire\\\\LivewireManager"];}#' vendor/nunomaduro/larastan/src/ApplicationResolver.php
vendor/bin/pint --test -vvv
vendor/bin/phpmd config,src,tests text phpmd.xml
vendor/bin/phpstan analyse
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## [5.1.0](https://github.com/Okipa/laravel-table/compare/5.0.2...5.1.0)

2022-10-25

* Added ability to chain a `->when(bool $condition)` method to an instantiated head action, in order to enable it conditionally
* Added a new built-in `RedirectHeadAction`, that will be used by the pre-configured `CreateHeadAction`
* Added an optional `bool $openInNewWindow = false` to the `CreateHeadAction`
* Added a new [JavaScript snippet](/README.md#set-up-a-few-lines-of-javascript) to handle head action link opening in tab: you'll have to add it if you want to benefit from this new ability

## [5.0.2](https://github.com/Okipa/laravel-table/compare/5.0.1...5.0.2)

2022-10-07
Expand Down
28 changes: 22 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,11 +473,18 @@ Configure a table action that will be displayed as a button positioned at the ri
If no head action is declared, the dedicated slot for it in the table head will remain empty.

This package provides the following built-in head actions:
* `CreateHeadAction`:
* Requires a `string $createUrl` argument on instantiation
* `RedirectHeadAction`:
* Requires `string $url`, `string $label`, `string $icon`, `array $class = ['btn', 'btn-success']` and `bool $openInNewWindow = false` arguments on instantiation
* Redirects to the model create page from a click on a `Create` button
* `CreateHeadAction`:
* Requires `string $createUrl` and `bool $openInNewWindow = false` arguments on instantiation
* Instantiate a pre-configured `RedirectHeadAction` with the given `$createUrl` as URL, `__('Create')` as label and `config('laravel-table.icon.create')` as icon

To use it, you'll have to pass an instance of it to the `headAction` method.
To use one of them, you'll have to pass an instance of it to the `headAction` method.

You'll be able to chain the following method to your head action:
* `when(bool $condition): Okipa\LaravelTable\Abstracts\AbstractHeadAction`
* Determines whether the head action should be enabled

```php
namespace App\Tables;
Expand All @@ -493,7 +500,8 @@ class UsersTable extends AbstractTableConfiguration
{
return Table::make()
->model(User::class)
->headAction(new CreateHeadAction(route('user.create')));
// Create head action will not be available when authenticated user is not allowed to create users
->headAction((new CreateHeadAction(route('user.create')))->when(Auth::user()->cannot('create_users')));
}
}
```
Expand Down Expand Up @@ -549,9 +557,9 @@ This package provides the built-in following bulk actions:

To use them, you'll have to pass a closure parameter to the `bulkActions` method. This closure will allow you to manipulate a `Illuminate\Database\Eloquent $model` argument and has to return an array containing bulk action instances.

You'll ben able to chain the following methods to your bulk actions:
You'll be able to chain the following methods to your bulk actions:
* `when(bool $condition): Okipa\LaravelTable\Abstracts\AbstractBulkAction`
* Determines if action should be available on table rows
* Determines whether the bulk action should be enabled on the table rows
* `confirmationQuestion(string|false $confirmationQuestion): Okipa\LaravelTable\Abstracts\AbstractBulkAction`
* Overrides the default action confirmation message
* `feedbackMessage(string|false $feedbackMessage): Okipa\LaravelTable\Abstracts\AbstractBulkAction`:
Expand Down Expand Up @@ -1185,6 +1193,14 @@ Livewire.on('laraveltable:action:feedback', (feedbackMessage) => {
});
```

Finally, in order to allow head `RedirectHeadAction` and `CreateHeadAction` to open link in new tab, you'll also have to add the following JS snippet:

```javascript
Livewire.on('laraveltable:link:open:newtab', (url) => {
window.open(url, '_blank').focus();
});
```

### Trigger Livewire events on table load

You may want to trigger some events on table load, in order to load UI third party JS libraries for example.
Expand Down
14 changes: 14 additions & 0 deletions src/Abstracts/AbstractHeadAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,26 @@ abstract class AbstractHeadAction
{
public string $rowActionClass;

protected bool $isAllowed = true;

abstract protected function class(): array;

abstract protected function icon(): string;

abstract protected function title(): string;

public function when(bool $condition): self
{
$this->isAllowed = $condition;

return $this;
}

public function isAllowed(): bool
{
return $this->isAllowed;
}

/** @return mixed|void */
abstract public function action(Component $livewire);

Expand Down
23 changes: 14 additions & 9 deletions src/HeadActions/CreateHeadAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,40 @@

namespace Okipa\LaravelTable\HeadActions;

use Illuminate\Http\RedirectResponse;
use Livewire\Component;
use Livewire\Redirector;
use Okipa\LaravelTable\Abstracts\AbstractHeadAction;

class CreateHeadAction extends AbstractHeadAction
{
public function __construct(public string $createUrl)
protected RedirectHeadAction $redirectHeadAction;

public function __construct(public string $createUrl, bool $openInNewWindow = false)
{
//
$this->redirectHeadAction = new RedirectHeadAction(
url: $createUrl,
label: __('Create'),
icon: config('laravel-table.icon.create'),
openInNewWindow: $openInNewWindow
);
}

protected function class(): array
{
return ['btn', 'btn-success'];
return $this->redirectHeadAction->class();
}

protected function title(): string
{
return __('Create');
return $this->redirectHeadAction->title();
}

protected function icon(): string
{
return config('laravel-table.icon.create');
return $this->redirectHeadAction->icon();
}

public function action(Component $livewire): RedirectResponse|Redirector
public function action(Component $livewire): void
{
return redirect()->to($this->createUrl);
$this->redirectHeadAction->action($livewire);
}
}
41 changes: 41 additions & 0 deletions src/HeadActions/RedirectHeadAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Okipa\LaravelTable\HeadActions;

use Livewire\Component;
use Okipa\LaravelTable\Abstracts\AbstractHeadAction;

class RedirectHeadAction extends AbstractHeadAction
{
public function __construct(
public string $url,
public string $label,
public string $icon,
public array $class = ['btn', 'btn-success'],
public bool $openInNewWindow = false,
) {
//
}

protected function class(): array
{
return $this->class;
}

protected function title(): string
{
return __($this->label);
}

protected function icon(): string
{
return $this->icon;
}

public function action(Component $livewire): void
{
$this->openInNewWindow
? $livewire->emit('laraveltable:link:open:newtab', $this->url)
: redirect()->to($this->url);
}
}
12 changes: 10 additions & 2 deletions src/Livewire/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class Table extends Component

public bool $resetFilters = false;

public array|null $headActionArray;
public array $headActionArray;

public bool $selectAll = false;

Expand Down Expand Up @@ -233,7 +233,15 @@ public function sortBy(string $columnKey): void

public function headAction(): mixed
{
return AbstractHeadAction::make($this->headActionArray)->action($this);
if (! $this->headActionArray) {
return null;
}
$headActionInstance = AbstractHeadAction::make($this->headActionArray);
if (! $headActionInstance->isAllowed()) {
return null;
}

return $headActionInstance->action($this);
}

public function updatedSelectAll(): void
Expand Down
13 changes: 10 additions & 3 deletions src/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -354,16 +354,20 @@ public function getFilterClosures(array $filtersArray, array $selectedFilters):
return $filterClosures;
}

public function getHeadActionArray(): array|null
public function getHeadActionArray(): array
{
if (! $this->headAction) {
return null;
return [];
}
$this->headAction->setup();
if (! $this->headAction->isAllowed()) {
return [];
}

return (array) $this->headAction;
}

/** @throws \JsonException */
public function getRowClass(): array
{
$tableRowClass = [];
Expand All @@ -374,7 +378,10 @@ public function getRowClass(): array
$tableRowClass[$model->laravel_table_unique_identifier] = ($this->rowClassesClosure)($model);
}

return $tableRowClass;
return json_decode(json_encode(
$tableRowClass,
JSON_THROW_ON_ERROR
), true, 512, JSON_THROW_ON_ERROR);
}

/** @throws \JsonException */
Expand Down
34 changes: 34 additions & 0 deletions tests/Unit/Bootstrap5/TableHeadActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,38 @@ protected function columns(): array
->call('headAction')
->assertRedirect(route('user.create'));
}

/** @test */
public function it_can_allow_head_action_conditionally(): void
{
app('router')->get('/user/create', ['as' => 'user.create']);
Config::set('laravel-table.icon.create', 'create-icon');
$config = new class extends AbstractTableConfiguration
{
protected function table(): Table
{
return Table::make()->model(User::class)
->headAction((new CreateHeadAction(route('user.create'), true))->when(false));
}

protected function columns(): array
{
return [
Column::make('name'),
];
}
};
Livewire::test(\Okipa\LaravelTable\Livewire\Table::class, ['config' => $config::class])
->call('init')
->assertDontSeeHtml([
'<a wire:click.prevent="headAction()"',
' class="btn btn-success"',
' href=""',
' title="Create">',
'create-icon Create',
'</a>',
])
->call('headAction')
->assertNotEmitted('laraveltable:link:open:newtab');
}
}

0 comments on commit fe6a3dc

Please sign in to comment.