Built-In Actions
PandaBear sudah menyediakan action yang umum dibutuhkan oleh hampir semua resource, seperti:
- melihat data;
- mengedit data;
- membuat data baru;
- menghapus data;
- memulihkan data;
- menghapus permanen;
- menggandakan data;
- mengimpor data;
- mengekspor data;
- serta action untuk relation.
Setiap action tersedia sebagai factory statis yang mengembalikan object PandaPanel\Actions\Action yang sudah dikonfigurasi.
Artinya, ketika Anda menambahkan built-in action ke dalam schema, action tersebut sudah memiliki:
- nama;
- label;
- icon;
- variant;
- teks konfirmasi;
- dan pemeriksaan authorization yang terhubung ke policy milik resource.
Built-in action dibuat sebagai factory, bukan subclass khusus.
Hal ini penting karena object yang dikembalikan tetap merupakan Action biasa. Semua konfigurasi masih dapat diubah menggunakan method chaining, dan endpoint tidak memberikan perlakuan khusus terhadap built-in action tersebut.
Contoh minimal yang dapat digunakan
<?php
declare(strict_types=1);
namespace App\Panels\Admin\Resources\Posts\Tables;
use App\Panels\Admin\Resources\Posts\PostResource;
use PandaPanel\Actions\CreateAction;
use PandaPanel\Actions\DeleteAction;
use PandaPanel\Actions\DeleteBulkAction;
use PandaPanel\Actions\EditAction;
use PandaPanel\Actions\ViewAction;
use PandaPanel\Tables\Columns\TextColumn;
use PandaPanel\Tables\TableSchema;
final class PostsTable
{
public static function configure(TableSchema $table): TableSchema
{
return $table
->columns([
TextColumn::make('title')
->searchable()
->sortable(),
])
->headerActions([
CreateAction::make(PostResource::class),
])
->recordActions([
ViewAction::make(PostResource::class),
EditAction::make(PostResource::class),
DeleteAction::make(PostResource::class),
])
->bulkActions([
DeleteBulkAction::make(PostResource::class),
]);
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Contoh di atas sudah membentuk table CRUD yang lengkap.
Anda tidak perlu menambahkan konfigurasi lain agar tombol-tombol tersebut dapat bekerja dan tetap mengikuti policy milik resource.
Daftar built-in action
Semua factory berikut berada di namespace:
PandaPanel\Actionsdan menerima class resource yang akan diproses.
use Closure;
use PandaPanel\Actions\Action;
CreateAction::make(string $resource): Action
CreateAction::modal(string $resource): Action
ViewAction::make(string $resource): Action
EditAction::make(string $resource): Action
DeleteAction::make(string $resource): Action
DeleteBulkAction::make(string $resource): Action
RestoreAction::make(string $resource): Action
RestoreBulkAction::make(string $resource): Action
ForceDeleteAction::make(string $resource): Action
ForceDeleteBulkAction::make(string $resource): Action
ReplicateAction::make(
string $resource,
array $except = [],
?Closure $using = null
): Action
ExportAction::make(string $exporter, string $resource): Action
ExportAction::bulk(string $exporter, string $resource): Action
ImportAction::make(string $importer, string $resource): Action2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Record Actions
Record action adalah action yang bekerja pada satu record tertentu.
Contohnya:
View
Edit
Delete
Restore
Replicate2
3
4
5
Konfigurasi bawaan
| Factory | Name | Label | Icon | Variant | Type |
|---|---|---|---|---|---|
ViewAction | view | View | eye | ghost | link |
EditAction | edit | Edit | pencil | ghost | link |
DeleteAction | delete | Delete | trash-2 | destructive | callback |
RestoreAction | restore | Restore | rotate-ccw | outline | callback |
ForceDeleteAction | forceDelete | Delete permanently | trash-2 | destructive | callback |
ReplicateAction | replicate | Replicate | copy | outline | callback |
Visibility dan authorization
| Factory | Ditampilkan ketika | Authorization | Konfirmasi | Pesan sukses |
|---|---|---|---|---|
ViewAction | halaman view tersedia di Resource::pages() | canView($record) | tidak | — |
EditAction | halaman edit tersedia di Resource::pages() | canEdit($record) | tidak | — |
DeleteAction | selalu | canDelete($record) | ya | Record deleted. |
RestoreAction | record berada dalam kondisi trashed | canRestore($record) | tidak | Record restored. |
ForceDeleteAction | record berada dalam kondisi trashed | canForceDelete($record) | ya | Record permanently deleted. |
ReplicateAction | selalu | canCreate() dan canView($record) | ya | Record replicated. |
ViewAction dan EditAction adalah link.
Karena itu, tidak ada request POST atau callback action yang dijalankan secara langsung. Route tujuan akan melakukan authorization kembali ketika halaman tersebut dibuka.
RestoreAction dan ForceDeleteAction menggunakan:
PandaPanel\Support\TrashedRecord::isTrashed()untuk memeriksa apakah record sedang berada dalam kondisi trashed.
Dengan begitu, table dapat menentukan action yang sesuai berdasarkan kondisi record.
Table Actions
Table action adalah action yang bekerja pada level table, bukan pada satu record tertentu.
Contohnya:
Create
Import
Export2
3
Konfigurasi bawaan
| Factory | Name | Label | Icon | Variant | Type |
|---|---|---|---|---|---|
CreateAction::make() | create | New {resource label} | plus | default | link |
CreateAction::modal() | create | New {resource label} | plus | default | form |
ExportAction::make() | export | Export | download | outline | form |
ImportAction::make() | import | Import | upload | outline | form |
CreateAction::make()
CreateAction::make(PostResource::class)Action ini membuat link menuju:
Resource::url('create')Jika resource tidak memiliki halaman create, action ini tidak akan ditampilkan.
CreateAction::modal()
CreateAction::modal(PostResource::class)Berbeda dari CreateAction::make(), versi modal() tidak membawa user ke halaman baru.
Action ini akan:
- membuka form milik resource di dalam dialog;
- melakukan validasi melalui schema form resource;
- menyimpan data melalui table handler.
Baik versi halaman maupun modal menggunakan:
Resource::form()Artinya, keduanya menggunakan schema validasi dan mekanisme form yang sama.
Karena itu, versi halaman dan modal tidak seharusnya memiliki aturan validasi yang berbeda.
Action modal seperti create, import, dan export dapat didefinisikan pada:
headerActions()
toolbarActions()
emptyStateActions()2
3
Ketiganya akan diproses melalui scope table.
Bulk Actions
Bulk action digunakan untuk menjalankan satu operasi terhadap banyak record sekaligus.
Contohnya:
Delete selected
Restore selected
Export selected2
3
Konfigurasi bawaan
| Factory | Name | Label | Icon | Variant | Konfirmasi |
|---|---|---|---|---|---|
DeleteBulkAction | delete | Delete selected | trash-2 | destructive | ya |
RestoreBulkAction | restore | Restore selected | rotate-ccw | outline | tidak |
ForceDeleteBulkAction | forceDelete | Delete selected permanently | trash-2 | destructive | ya |
ExportAction::bulk() | export | Export | download | outline | membuka form |
Authorization bulk action
| Factory | Ability umum | Ability per record | Pesan sukses |
|---|---|---|---|
DeleteBulkAction | canDeleteAny() | canDelete($record) | Selected records deleted. |
RestoreBulkAction | canRestoreAny() | canRestore($record) | Selected records restored. |
ForceDeleteBulkAction | canForceDeleteAny() | canForceDelete($record) | Selected records permanently deleted. |
ExportAction::bulk() | canViewAny() | — | Your export is ready. |
DeleteBulkAction, RestoreBulkAction, dan ForceDeleteBulkAction memiliki pola kerja yang sama.
Urutannya:
- sistem memeriksa ability umum sebelum record tertentu tersedia;
- setelah record dipilih dan dimuat, sistem memeriksa authorization untuk setiap record;
- jika semua record diizinkan, seluruh operasi dijalankan dalam satu transaksi database.
Operasi tersebut menggunakan:
DB::transaction()secara eksplisit.
Hal ini dilakukan agar bulk operation benar-benar bersifat:
semua berhasil atau semuanya dibatalkan.
Perilaku tersebut tidak bergantung pada konfigurasi transaction default milik panel.
Mengubah konfigurasi built-in action
Factory built-in action tetap mengembalikan object Action.
Karena itu, Anda dapat melanjutkan konfigurasi menggunakan method chaining.
Contoh:
use App\Panels\Admin\Resources\Posts\PostResource;
use PandaPanel\Actions\DeleteAction;
use PandaPanel\Actions\Enums\ActionVariant;
use PandaPanel\Actions\ViewAction;
ViewAction::make(PostResource::class)
->icon('info')
->label('Details');
DeleteAction::make(PostResource::class)
->icon('trash')
->variant(ActionVariant::Ghost)
->requiresConfirmation(
heading: 'Delete this post?',
description: 'Comments on it are deleted too.',
button: 'Delete it',
)
->successMessage('Post deleted.');2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Konfigurasi yang diberikan paling akhir akan digunakan.
Artinya, Anda juga dapat mengganti handler bawaan.
use Illuminate\Database\Eloquent\Model;
DeleteAction::make(PostResource::class)
->action(
static function (Model $record): void {
$record
->forceFill([
'status' => 'archived',
])
->save();
}
);2
3
4
5
6
7
8
9
10
11
12
Namun, ada hal penting yang perlu diperhatikan.
Jika Anda hanya mengganti:
->action(...)authorization bawaan dari factory tidak ikut berubah.
Pada contoh sebelumnya, action tersebut masih dilindungi oleh:
canDelete($record)padahal operasi sebenarnya sudah tidak lagi melakukan delete.
Karena itu, jika operation berubah secara semantik, authorization juga harus disesuaikan.
Contohnya:
DeleteAction::make(PostResource::class)
->authorize(
static fn (Model $record): bool =>
PostResource::canEdit($record)
)
->action(
static function (Model $record): void {
$record
->forceFill([
'status' => 'archived',
])
->save();
}
);2
3
4
5
6
7
8
9
10
11
12
13
14
Dengan begitu, permission yang diperiksa sesuai dengan operasi yang sebenarnya dilakukan.
Import dan Export
Contoh konfigurasi import dan export:
use App\Panels\Admin\Resources\Users\Exports\UserExporter;
use App\Panels\Admin\Resources\Users\Imports\UserImporter;
use App\Panels\Admin\Resources\Users\UserResource;
use PandaPanel\Actions\ExportAction;
use PandaPanel\Actions\ImportAction;
$table
->headerActions([
ImportAction::make(
UserImporter::class,
UserResource::class,
),
// Mengekspor daftar yang sudah difilter.
ExportAction::make(
UserExporter::class,
UserResource::class,
),
])
->bulkActions([
// Mengekspor record yang sedang dipilih.
ExportAction::bulk(
UserExporter::class,
UserResource::class,
),
]);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Import dan export menerima nama class, bukan closure.
Hal ini diperlukan karena proses import/export dapat dijalankan melalui queue pada proses yang berbeda dari HTTP request awal.
Closure tidak dapat dibawa secara aman ke proses queue tersebut, sedangkan nama class dapat direferensikan kembali oleh worker.
Pelajari lebih lanjut pada:
Relation Actions
Namespace:
PandaPanel\Actions\Relationsmenyediakan konsep yang sama untuk relation manager.
Perbedaannya, relation action bekerja menggunakan:
- manager class;
- owner record;
- dan resource terkait.
Contoh signature:
use Illuminate\Database\Eloquent\Model;
use PandaPanel\Actions\Action;
// Semua action berikut berada di PandaPanel\Actions\Relations.
AssociateAction::make(
string $resource,
string $manager,
Model $owner
): Action
AttachAction::make(
string $resource,
string $manager,
Model $owner
): Action
CreateRelatedAction::make(
string $resource,
string $manager,
Model $owner
): Action
EditRelatedAction::make(
string $resource,
string $manager,
Model $owner
): Action
DeleteRelatedAction::make(
string $manager,
Model $owner
): Action
DetachAction::make(
string $manager,
Model $owner
): Action
DetachBulkAction::make(
string $manager,
Model $owner
): Action
DissociateAction::make(
string $manager,
Model $owner
): Action
RestoreAction::make(
string $manager,
Model $owner
): Action
RestoreBulkAction::make(
string $manager,
Model $owner
): Action
ForceDeleteAction::make(
string $manager,
Model $owner
): Action
ForceDeleteBulkAction::make(
string $manager,
Model $owner
): Action2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
Action untuk:
- create;
- attach;
- associate;
ditentukan melalui:
PandaPanel\Resources\RelationTablebukan dideklarasikan ulang pada setiap relation manager.
Alasannya, action tersebut berkaitan dengan jenis relasi itu sendiri.
Contohnya, relation hasMany tidak seharusnya menawarkan action attach.
Dengan menentukan action berdasarkan tipe relation, PandaBear dapat mencegah relation manager menampilkan action yang tidak sesuai dengan hubungan Eloquent yang digunakan.
Pelajari lebih lanjut pada:
Catatan penting
Nama action dapat sama
DeleteAction dan DeleteBulkAction sama-sama menggunakan nama:
deleteBegitu juga resource RestoreAction dan relation RestoreAction sama-sama menggunakan:
restoreHal ini memang dirancang seperti itu.
Action-action tersebut berada di scope atau set yang berbeda, dan setiap set memiliki whitelist sendiri.
Karena itu, nama yang sama pada scope berbeda tidak menimbulkan konflik.
Namun, jika dua action dengan nama yang sama berada di dalam satu set yang sama, PandaBear akan melempar:
PanelSchemaException::duplicateActions()RestoreAction membutuhkan soft delete
Agar RestoreAction dapat digunakan, resource harus mendukung soft delete.
Jika tidak, trashed record tidak dapat ditemukan.
Selain itu, table juga harus memiliki:
PandaPanel\Tables\Filters\TrashedFilterTanpa filter tersebut, record yang sudah dihapus tidak akan muncul di table sehingga tidak ada row tempat RestoreAction dapat ditampilkan.
CreateAction::modal() menggunakan forceFill()
CreateAction::modal() menulis nilai model menggunakan:
forceFill()Data tersebut sebelumnya sudah:
- divalidasi;
- diproses oleh schema form;
- didehidrasi menjadi data yang akan disimpan.
Schema form bertindak sebagai whitelist data.
Karena itu, $fillable pada model tidak diperiksa pada proses ini.
Jika proses pembuatan data bukan sekadar insert biasa, ganti mekanisme penyimpanannya menggunakan:
->tableAction(...)Label factory berasal dari resource
Contohnya, CreateAction membuat label dengan pola:
New {resource label}Label resource diperoleh dari:
Resource::label()Kemudian nilainya diproses menggunakan:
mb_strtolower()Artinya, ketika label resource berubah, label tombol create juga ikut berubah secara otomatis.
ReplicateAction membutuhkan dua ability
ReplicateAction memeriksa:
canCreate()dan:
canView($record)Hal ini diperlukan karena melakukan replicate berarti:
- user harus diizinkan melihat record sumber;
- user juga harus diizinkan membuat record baru.
Izin untuk melihat sebuah record tidak otomatis berarti user boleh membuat salinannya.