Karbantartás menedzsment rendszer - 2. rész: Filament admin panel és a legegyszerűbb erőforrás

Attila | 2023. 09. 14. 18:46 | Olvasási idő: 4 perc

Címkék: #CRUD #Digitalizáció (Digitalization) #Eloquent #Érvényesítés (Validation) #Filament #Laravel #Többnyelvűsítés (Localization) #Űrlap (Form)

A rendszer építését logikusan, az alapoktól kezdve tesszük meg. Erőforrásokkal (resources) fogunk dolgozni, hogy hatékonyan tudjuk végrehajtani a CRUD műveleteket. Legelőször a berendezés típusokat kezelő erőforrást fogjuk felépíteni, és közben számos fogással megismerkedünk a Filament admin panel kezelésekor, programozásakor.
filament-admin-panel

A legegyszerűbb erőforrás: berendezés típus

Azért írom azt, hogy ez a legegyszerűbb erőforrásunk, mivel nem fog annyi mező tartalmazni, illetve csak a berendezések táblával lesz kapcsolatban: egy berendezés típushoz több berendezés is tartozhat majd. A műveletsor végrehajtás ugyanakkor a többi erőforrásnál is majd követhető utat mutat a számunkra.

Model és migrációs fájl

Először hozzuk létre a berendezés típusok model és migrációs fájlját. Ezzel gyakorlatilag az Eloquent ORM segítségével biztosítunk majd hozzáférést a berendezés típusokat tartalmazó tábla adataihoz:

php artisan make:model DeviceType -m

Két mezője lesz egy elnevezés és egy megjegyzés a szokásos mezőkön (id, timestamps) kívül. Íme a migrációs fájlja:

Schema::create('device_types', function (Blueprint $table) {
  $table->id();
  $table->string('name')->unique();
  $table->string('note')->nullable();
  $table->timestamps();
});

Továbbá a Model fájl bővítése ezzel:

protected $fillable = ['name', 'note'];

Következhet a migráció:

php artisan migrate

Egyelőre a kapcsolataival még nem kell foglalkoznunk, amíg a kapcsolat másik résztvevője (berendezések) nem került létrehozásra.

Filament erőforrás létrehozása

Hozzuk létre a berendezés típusok erőforrását:

php artisan make:filament-resource DeviceType

Az utasítás hatására az app / Filament / Resources mappában a következő új mappa és fájlok jöttek létre:

  • DeviceTypeResource.php
  • DeviceTypeResource (mappa)
    • Pages (mappa)
      • CreateDeviceType.php
      • EditDeviceType.php
      • ListDeviceType.php

A nevük elég beszédes, de meg fogjuk nézni őket külön-külön. A legfontosabb (mivel a legtöbb dolgot itt tudjuk majd beállítani) a konkrét erőforrás fájl (DeviceTypeResource.php).

Nézzük meg ennek tartalmát, hogy mit tartalmaz alapból:

  • tulajdonság mezői:
    • model fájl megnevezése (ezt használja majd az Eloquent műveletek végrehajtásához)
    • navigationIcon: a menüben ez az icon jelenik meg a neve mellett. A Filament alapértelmezetten a Heroicons nevű ikongyűjteményt használja, így ha egyszerűen le szeretnénk cserélni bárminek az ikonját, akkor ennek a gyűjtemények a tartalmában keresgéljünk: https://heroicons.com/
  • metódusai:
    • form(): ezzel a metódussal tudjuk meghatározni, hogy a létrehozási / szerkesztési (create / edit) űrlapon milyen típusú mezők jelenjenek meg és azoknak milyen validációs szabályoknak kell megfelelniük
    • table(): ezzel a metódussal tudjuk meghatározni, hogy az erőforrás lista nézetén (index) látható táblázat milyen oszlopokat (columns, mezőket) tartalmazzon és azok milyen sorrendben kövessék egymást, esetleg kereshetőek vagy rendezhetőek legyenek, továbbá a táblázat még részletesebb testreszabása, például hogy milyen szűrőket (filters) lehessen beállítani és milyen műveleteket lehessen innen a lista nézetből még elérni:
      • a táblázat soraiban (actions) adott erőforrás szerkesztése, törlése stb.
      • ha már több erőforrásunk van a táblázatban, akkor "tömeges" műveleteket (bulkActions) is végrehajthatunk rajtuk az egyes sorok kijelölése után például együtt törölhetjük őket,
      • ha még nincs erőforrásunk (emptyStateActions), akkor a táblázat helyén az új hozzáadása gomb elérhető.
    • getRelations(): ezzel tudjuk majd beállítani, hogy az erőforrás milyen más erőforrásokkal legyen kapcsolatban (hasonlóan a modellekhez) és a kapcsolatot hogyan kezelje a Filament,
    • getPages(): az erőforrások kezeléséhez tartozó útvonalakat lehet itt regisztrálni. Alapértelmezetten tartalmazza a lista, valamint a létrehozási (create) és szerkesztési (edit) útvonalakat.

A DeviceTypeResource / Pages mappa fájl nevei utalnak a funkcióikra: az itteni három fájl a create, edit, list (index) műveletek és nézetek testreszabását teszi lehetővé. Például a ListDeviceType.php fájlban a getHeaderActions() metódus visszatérésében található CreateAction miatt lesz az erőforrás lista nézetében a táblázat felett egy új erőforrás létrehozását elindító gomb.

Alapállapotban így néz ki a berendezés típusokat tartalmazó listanézet:

Innen indulunk ki, ennek fogjuk elvégezni a testreszabását, lokalizációját (amihez már van magyar fordítása, azt úgy mutatja). Kezdjük el!


Navigáció testreszabása

Alapbeállítások elvégzése

Cseréljük le az alapértelmezett ikont egy jobban passzolóra:

protected static ?string $navigationIcon = 'heroicon-o-wrench-screwdriver';

Soroljuk be csoportba a menüpontot már ne csak egy tulajdonság érték felülírásával, hanem egy segédmetódus segítségével, ami támogatja a többnyelvűsítést (innentől már használjuk is a többnyelvűsítés adta lehetőségeket, közvetlenül ezután a szekció után definiáljuk a szükséges szótárakat is):

public static function getNavigationGroup(): string
{
  return __('module_names.navigation_groups.administration');
}

Adjuk meg a Model-hez tartozó többnyelvűsített neveket is (egyes- és többesszámban egymás után):

public static function getModelLabel(): string
{
  return __('module_names.device_types.label');
}

public static function getPluralModelLabel(): string
{
  return __('module_names.device_types.plural_label');
}

Ezek még nem fognak helyesen működni, szükség van hozzájuk a szótárakra is.

Szótárak létrehozása

A projekt lang mappájában hozzunk létre egy en és egy hu nevű mappát is. Mindkét almappában helyezzük el a module_names.php fájlt. Az en mappában lévő module_names.php fájl tartalma:

<?php

return [
  'navigation_groups' => [
    'administration' => 'Administration',
  ],
  'device_types' => [
    'label' => 'Device type',
    'plural_label' => 'Device types',
  ],
];

A hu mappában lévő module_names.php fájl tartalma:

<?php

return [
  'navigation_groups' => [
    'administration' => 'Adminisztráció',
  ],
  'device_types' => [
    'label' => 'Berendezés típus',
    'plural_label' => 'Berendezés típusok',
  ],
];

Ez így már majdnem tökéletes, de még egy fordítás hiányzik ("Create a Berendezés típus to get started."), ami a Filament táblázatokhoz kapcsolódik. Az előző blogbejegyzésemben említettem, hogy akkor a panelek szótárait publikáltuk csak, most viszont már szükségünk van a táblázatokkal kapcsolatos szótárakra is, ha azokat is helyesen szeretnénk megkapni.

php artisan vendor:publish --tag=filament-tables-translations

A publikálás megtörtént, de ez még nem elég, úgyhogy valószínűleg hiányzik egy fordítás a Filament táblázatok magyar szótárából. Nyissuk meg a lang / vendor / filament-tables / hu / table.php fájlt és keressük meg az 'empty' szekciót. Nálam itt csak a 'heading' rész található meg, míg ugyanennek a fájlnak az en mappában lévő eleme egy 'description' elemet is tartalmaz, úgyhogy arra van itt is szükségünk:

'empty' => [
  'heading' => 'Nincs találat',
  'description' => 'Hozzon létre egy erőforrást (:model) a kezdéshez.',
],

Ha most frissítjük az oldalunkat a böngészőben, akkor az üres táblázatot tartalmazó lista nézet így már megfelelő lesz.

Ha a későbbiekben azt látjuk, hogy más címke fordítása is hiányzik a szótárból, akkor azt most már könnyedén kell tudnunk pótolni. Folytathatjuk a munkát a létrehozási és szerkesztési űrlappal.


Új erőforrás létrehozása és meglévő szerkesztése nézetek, űrlapok, funkciók

Ha az "Új Berendezés típus" gombra kattintunk, akkor jelenleg még nem jön be az űrlaphoz tartozó egy bemeneti mező sem, csak a műveleti gombok láthatóak.

A DeviceTypeResource.php form() metódusában definiáljuk azokat a bemeneti mezőket, amelyek a létrehozási és szerkesztési űrlapon is elengedhetetlenek az új erőforrás létrehozásához vagy a meglévő szerkesztéséhez.

A megfelelő validációra és design-ra már most figyeljünk, úgyhogy minden mezőnél külön-külön meghatározzuk a szabályokat, amelyeket a felhasználónak be kell tartani az érték megadásakor, valamint minden űrlapon lévő bemeneti elemet egy szekcióba fogunk foglalni. Így néz ki a form() metódus visszatérési értéke:

return $form
  ->schema([
    Forms\Components\Section::make()
      ->schema([
        Forms\Components\TextInput::make('name')->label(__('fields.name'))
          ->required()
          ->unique(ignoreRecord: true)
          ->maxLength(255),
        Forms\Components\TextInput::make('note')->label(__('fields.note'))
          ->maxLength(255),
      ])
  ]);

A szekcióban két űrlap elemet definiáltunk: mindkettő TextInput Filament komponens. A címkéjüket (bár még ez a szótár nem létezik) a label() metódusban többnyelvűsítéssel adtuk meg, majd meghatároztuk az adattáblában már definiált validációs kényszereket: kötelező mező (required), egyedi a táblában (unique), és maximális hosszúság. A unique() validációs metódusban meg kell adni, hogy az aktuálisan szerkesztett erőforrást ignorálja, tehát ne vegye figyelembe, amikor az egyediséget vizsgálja az adattáblában.

Hajtsuk végre a szótár hozzáadását, bővítését. Adjuk hozzá a lang mappában mindkét almappához (en, hu) a fields.php szótár fájlt. A magyar szótár tartalma kezdetben:

<?php

return [
  'name' => 'Név',
  'note' => 'Megjegyzés',
];

Az angol szótár tartalma ugyanez, csak a jobb oldali értékek különböznek az asszociatív tömbben: Name és Note. Végeredményként így néz ki a berendezés típus erőforrást létrehozó nézetünk tartalmi része:

Látható, hogy a név mező kitöltése kötelező (* jelzi). Hozzunk is létre egy berendezés típust, például a gépeket. A név megadása után a Létrehozás gomb megnyomásával létre is jön az új Gépek berendezés típusunk (jobb felül az ablakban fel is villan egy értesítés arról, hogy "Létrehozva") és a rendszer alapértelmezetten nem irányít vissza minket a lista (index) oldalra, hanem marad ugyanitt az űrlapnál, csak most már szerkeszteni és törölni tudjuk a Gépek erőforrásunkat.

Ha azt szeretnénk, hogy a létrehozás valamint a szerkesztés után a lista oldalra irányítsuk ki a felhasználót, akkor a DeviceTypeResource / Pages / CreateDeviceType.php és a mellette lévő EditDeviceType.php fájlokat kell szerkesztenünk. Mindkét fájlhoz ugyanazt a metódust kell hozzáadnunk:

protected function getRedirectUrl(): string
{
  return $this->getResource()::getUrl('index');
}

Ezzel visszajuttatjuk a felhasználót a lista oldalra létrehozás vagy szerkesztés után. Sikeres szerkesztés után jobb felül fel is villan egy értesítés, hogy "Mentve".


Berendezés típusok lista (index) nézet, táblázat, funkciók

A Gépek berendezés típus létrehozása után a lista nézetben nem látható maga a Gépek berendezés típus a táblázatban. Ez amiatt van, mert a DeviceTypeResource.php fájlban a table() metódusban lévő $table objektumnál az oszlopokat (columns) még nem definiáltuk. Ha ezt megtesszük, már látszódni is fog. A columns metódusban definiált tömb a következő elemeket tartalmazza:

Tables\Columns\TextColumn::make('id')
  ->searchable()->sortable(),
Tables\Columns\TextColumn::make('name')->label(__('fields.name'))
  ->searchable()->sortable(),
Tables\Columns\TextColumn::make('created_at')->label(__('fields.created_at'))
  ->dateTime('Y-m-d H:i')
  ->searchable()->sortable(),

A három szöveges oszlop (TextColumn) három szöveges mezőt fog megjeleníteni a device_types adattáblánkból: id, name, created_at. Az Id mező maradhat Id, a névnek már létezik a fordítása, a created_at mezőnek még hozzá kell adni a fields.php-kben lévő szótárakhoz ("Létrehozva" és "Created at"). Mindhárom mezőt kereshetővé (searchable) és rendezhetővé (sortable) tettünk így. A kereshetőség arra vonatkozik, hogy a táblázat felett jobbra lesz egy keresőmező, amibe ha beírunk valamit, akkor minden olyan oszlopban keresni fog, amire a searchable() metódust használtuk. Rendezni ABC sorrendben tudunk az oszlop nevére kattintással előre és hátrafelé. A created_at mezőnél még megadtuk a dátum formátumát a dateTime() metódus segítségével, emiatt például egy created at mezőben lévő dátum így fog kinézni: 2023-09-15 18:54

A lista nézet a táblázattal végeredményben így fog kinézni:

Alapértelmezetten az erőforrásoknál nem fog létrejönni "show" nézet, így amikor a táblázat adott sorára rákattintunk, automatikusan a szerkesztési űrlapját fogja létrehozni. Ha szeretnénk majd a "show" nézetet is legenerálni az erőforráshoz, arra is lesz lehetőségünk, de egyelőre itt a berendezés típusoknál erre nem lesz szükségünk, mivel majd csak az adminisztrátorok férhetnek hozzá, akik alapból szerkeszteni tudják majd a berendezés típusokat.


Widget

A vezérlőpultra (dashboard) különböző statisztikai információkat, trendeket mutató diagramokat stb. tudunk kitenni (a diagramokhoz a Chart.js osztálykönyvtárat használja a Filament, amelyet már én is több projektemnél, blogbejegyzésben alkalmaztam). Kezdetben helyezzünk el a vezérlőpulton egy kártyát, amit azt mutatja meg, hogy hány berendezés típus létezik a karbantartás menedzsment rendszerben.

php artisan make:filament-widget DeviceTypeOverview --stats-overview

Erőforrást nem kell megadni, csak üssünk entert és a következő kérdésnél adjuk meg, hogy admin, így az admin panel-en lesz elérhető majd a widget. Maga a fájl, ami a widget programozott hátterét tartalmazza itt található meg: app / Filament / Widgets / DeviceTypeOverview.php nyissuk is meg ezt a fájlt szerkesztésre! A getStats() metódus visszatérési tömbjéhez adjuk meg ezt:

Stat::make('DeviceType', DeviceType::query()->count())->label(__('module_names.device_types.plural_label')),

Ezzel meg tudjuk jeleníteni a vezérlőpulton a berendezés típusok számát. Mást nem is kell tennünk, mivel az app / Providers / Filament / AdminPanelProvider.php -ban definiálva van a visszatérési panelnél a discoverWidgets() metódus, úgyhogy rögtön látni fogja a létrehozott és beállított widget-ünket a rendszer, amit utána a vezérlőpulton már láthatunk is:

Ha a felhasználói vagy a filament dokumentációs widget-et el szeretnénk távolítani, akkor azt az imént említett AdminPanelProvider.php visszatérési paneljében a widgets() metódus tömbjében tehetjük meg egy törléssel vagy kommenteléssel.

Mára ennyi, ezzel összeállt egy teljes, működő Filament erőforrás a CRUD műveleteivel együtt!

A bejegyzésben végrehajtott programkód módosítások ebben a GitHub commit-ben érhetők el.


Dolgozzunk együtt: egyéni oktatás, mentorálás, fejlesztés, tanácsadás

Ha egyéni oktatás, mentorálás, vagy fejlesztési projekt kapcsán szeretnél segítséget kérni tőlem, esetleg együttműködni velem, akkor keress meg a weboldalamon található elérhetőségeken keresztül!