Bevezetés
Az egyik célunkat szeretnénk elérni a
munkalapok feldolgozása során. Az volt az elvárás, hogy a gépkezelők
tudjanak bejelenteni hibákat a berendezésekkel kapcsolatban és ezeket
strukturáltan tudja eltárolni a Karbantartás Menedzsment Rendszer. Ezt
még azzal is kiegészítjük, hogy a karbantartó szerepkörű felhasználok
meg tudják határozni, hogy az a hiba mennyire okoz problémát, illetve
ebből adódóan mennyire sürgős a javítása. Nyilván az a legsürgősebb
javítási feladat, ami miatt esetleg megállhatna a termelés. A
karbantartók tehát sürgősségi szintet, határidőt is tudnak definiálni
majd a munkalapokon. Ezen felül a munkalapok segítségével több mindent
is nyomon lehet majd követni a rendszer segítségével:
- Mi volt a konkrét hiba a berendezésen?
- Lehet digitális fényképet feltölteni a hibákról.
- A hibabejelentő személyeket eltároljuk, de rajtuk kívül a hiba javítását elvállaló karbantartó személyét is.
- Láthatjuk majd, hogy a hiba bejelentésétől kezdve mennyi időre volt szükség az egyes hiba típusonként a javításra.
- Tudni fogjuk, hogy melyik berendezéssel mennyi és milyen típusú
(sürgősségű) hibák adódtak, ez a későbbiekben adatelemzésnél nagyon
hasznos lehet a számunkra.
- De a felsoroltakon kívül, számos lehetőségünk lesz majd még az adatelemzésre a rendszerben.
Tervezés
szempontjából a munkalapokat tároló adattábla (bal felül: worksheets)
így illeszkedhet be az adatbázis szerkezetébe: az adatbázis diagram most
releváns részei:
Megjegyzés:
a Spatie Laravel Permission csomagnak éppen a munkám során jött ki a
legfrissebb fő verziója (6-os), így azt érdemes frissíteni úgy, hogy a
composer.json fájlban a "require" szekcióba beírjuk ezt a megfelelő
helyre: "spatie/laravel-permission": "^6.0" majd után composer update paranccsal érvényre is juttatjuk a legfrissebb csomagverziók használatát.
Munkalap - Worksheet
Migrációs fájl
Hozzuk létre a Model-t és a migrációs fájlt (controller-re és factory-ra nincs most még szükségünk):
php artisan make:model Worksheet -m
Építsük fel az adattábla szerkezetét a migrációs fájlban:
public function up(): void
{
Schema::create('worksheets', function (Blueprint $table) {
$table->id();
$table->enum('priority', ['Normál', 'Sürgős', 'Leálláskor'])->default('Normál');
$table->text('description');
$table->date('due_date')->nullable();
$table->date('finish_date')->nullable();
$table->foreignId('device_id')->constrained()->onUpdate('no action')->onDelete('no action');
$table->unsignedBigInteger('creator_id');
$table->foreign('creator_id')->references('id')->on('users')->onUpdate('no action')->onDelete('no action');
$table->unsignedBigInteger('repairer_id')->nullable();
$table->foreign('repairer_id')->references('id')->on('users')->onUpdate('no action')->onDelete('no action');
$table->text('attachments');
$table->text('comment')->nullable();
$table->timestamps();
});
}
Magyarázatok:
- A
sürgősségi szinteket (priority) enum, vagyis felsorolás oszloptípussal
definiáljuk (ami akkor hasznos, ha egy aránylag szűk értékkészletből
adódnak az adott mező lehetséges értékei, mint például, ha a napok vagy a
hónapok, esetleg a szerepkörök nevét szeretnénk így tárolni), ennek a
mezőnek a kitöltése mindig kötelező, de alapértelmezetten Normál szintet
határozunk meg a hibáknak.
- A hibáról teszünk be egy szöveges
leírást (description), ami kötelező, de az oszlopszerkezet végén egy nem
kötelező megjegyzést (comment) is lehet hozzáfűzni majd a munkalaphoz.
- Amikor
a gépkezelő létrehozza a munkalapot (hiba észrevétele után), akkor ő
még nem tudja, vagyis nem határozhatja meg, hogy milyen határidővel
(due_date) történjen meg a hiba javítása, illetve a bejelentéskor még
azt sem tudja jelezni, hogy mikor is fog megtörténni a tényleges
kijavítás (finish_date).
- Idegen kulcs mezők:
- Minden
munkalap egy berendezéshez fog tartozni, ennek megfelelően egy adott
berendezéshez kötjük a munkalapot az adatbázisban. Berendezés törlésénél
és frissítésénél a munkalapoknál ne történjen változás. Ezen a ponton
érdemes elgondolkodni azon, hogy a berendezés típusoknál,
berendezéseknél, dokumentumoknál is "átálljunk" a soft delete funkció
alkalmazására, vagyis arra, hogy ne törlődjenek véglegesen az elemeink
az adattáblákból, hanem csak "törlésre" jelölhessük ki őket, amit aztán
az adminisztrátorok esetleg vissza is tudjanak majd állítani, ha mégsem
szeretnénk törölni őket. Egyelőre viszont itt azt a logikát kövessük,
hogy ne történjen semmi (no action), ha a külső kulcsos hivatkozott
elemmel valami történne (frissítésre vagy törlésre kerülne).
- A
felhasználók táblához két "irányból" is kapcsolódjunk: az egyik a
munkalapot létrehozó felhasználó legyen, a másik pedig a karbantartást
elvégző személy legyen.
- A hibáról mellékelt képet, képeket (akár többet!) az attachments mezőben fogjuk eltárolni.
Futtathatjuk a migrálást:
php artisan migrate
Model osztály és a kiegészítő felsorolás (enum) osztály
A
migrációs fájl alapján gyűjtsük össze, hogy milyen mezőket kell
engednünk kitölteni! A $fillable mező tömbjét bővítsük ki az alábbiak
szerint:
protected $fillable = [
'priority',
'description',
'due_date',
'finish_date',
'device_id',
'creator_id',
'repairer_id',
'attachments',
'comment',
];
Két
mező "kasztolását" (adatbázis mezőjének a típusát másképp használjuk a
PHP programozás során, mindezt automatikusan) végezzük el a Model
osztályban:
- priority: adattáblában enum típus, de mi egy PHP,
Laravel és Filament specifikus osztállyal definiáljuk ezt a
programkódunkban (további információ erről itt: https://laravel.com/docs/10.x/eloquent-mutators#enum-casting).
- attachments: adattáblában szöveges érték, de mi kezeljük tömbként.
protected $casts = [
'priority' => WorksheetPriority::class,
'attachments' => 'array',
];
A
WorksheetPriority-t az app / Enums új könyvtárban kell majd létrehozni
WorksheetPriority.php fájlnévvel, amit itt a Worksheet Model osztályban
importálni is kell. A WorksheetPriority.php osztály tartalmát úgy kell
összeállítani, hogy előtte a Filament specifikus dolgokat áttekintjük a
dokumentációban: https://filamentphp.com/docs/3.x/support/enums Az új WorksheetPriority.php fájl tartalmaz ezekután:
<?php
namespace App\Enums;
use Filament\Support\Contracts\HasIcon;
use Filament\Support\Contracts\HasLabel;
use Filament\Support\Contracts\HasColor;
enum WorksheetPriority: string implements HasLabel, HasColor, HasIcon
{
case NORMAL = 'Normál';
case SURGOS = 'Sürgős';
case LEALLASKOR = 'Leálláskor';
public function getLabel(): ?string
{
return match ($this) {
self::NORMAL => 'Normál',
self::SURGOS => 'Sürgős',
self::LEALLASKOR => 'Leálláskor',
};
}
public function getColor(): string|array|null
{
return match ($this) {
self::NORMAL => 'warning',
self::SURGOS => 'danger',
self::LEALLASKOR => 'gray',
};
}
public function getIcon(): ?string
{
return match ($this) {
self::NORMAL => 'heroicon-m-exclamation-circle',
self::SURGOS => 'heroicon-m-exclamation-triangle',
self::LEALLASKOR => 'heroicon-m-sun',
};
}
}
Az
osztályon belül definiáljuk a három sürgősségi szintet, mint prioritási
lehetőséget. A metódusokkal pedig definiáljuk a címke nevét
(getLabel()), a színét (getColor()) és végül az ikonját (getIcon()),
amik majd látszódni fognak a Filament erőforrás táblázatában.
Eloquent kapcsolatok mindkét oldalról (Worksheet és Device / User)
Kössük hozzá először a Worksheet Model osztályt a "társaihoz"! Mindegyik kapcsolat 1-n típusú.
public function device(): BelongsTo
{
return $this->belongsTo(Device::class);
}
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'creator_id');
}
public function repairer(): BelongsTo
{
return $this->belongsTo(User::class, 'repairer_id');
}
A BelongsTo
osztályt importálni kell a fájl tetején, az odaírt kommentek pedig
beszédesek, hogy melyik-melyik kapcsolatért felelős.
Másik oldalról, mindezt a Device osztályban:
public function worksheets(): HasMany
{
return $this->hasMany(Worksheet::class);
}
Majd a User osztályban:
public function creators_worksheets(): HasMany
{
return $this->hasMany(Worksheet::class, 'creator_id');
}
public function repairers_worksheets(): HasMany
{
return $this->hasMany(Worksheet::class, 'repairer_id');
}
A HasMany osztályt importálni kell a fájl tetején.
Munkalap (Worksheet) erőforrás
Hozzuk
létre a munkalap erőforrást úgy, hogy generáljuk a létrehozott
adattáblájanak szerkezete alapján. Azonban, ha megpróbálnánk ezt így
létrehozni, akkor figyelmeztetést kapnánk, mivel alapértelmezetten a
rendszer nem ismeri az enum adattábla típust.
Maga
az erőforrás létrejönne, viszont nem töltené fel tartalommal az űrlap
és táblázat megjelenítő és beállító metódusokat. Emiatt néhány
módosítást végre kell hajtanunk a megfelelő működéshez. Nyissuk meg az app / Providers / AppServiceProvider.php fájlt és annak a boot() metódusát bővítsük:
DB::connection()
->getDoctrineSchemaManager()
->getDatabasePlatform()
->registerDoctrineTypeMapping('enum', 'string');
Hozzá pedig importáljuk be a DB facade-ot a fájl elején: use Illuminate\Support\Facades\DB;
Utána telepítsük a doctrine/dbal csomagot a generálás zökkenőmentessé tétele miatt:
composer require doctrine/dbal --dev
Majd következhet az erőforrás létrehozása generálással (adattábla alapján):
php artisan make:filament-resource Worksheet --generate
Így a form() és table() metódusok és lényegi tartalommal töltődtek fel az újonnan létrejövő WorksheetResource.php fájlban.
Alapbeállítások
Bővítsük ki a WorksheetResource osztályt az alábbi alapbeállításokkal:
protected static ?string $navigationIcon = 'heroicon-o-document-plus';
public static function getNavigationGroup(): string
{
return __('module_names.navigation_groups.failure_report');
}
protected static ?int $navigationSort = 7;
public static function getModelLabel(): string
{
return __('module_names.worksheets.label');
}
public static function getPluralModelLabel(): string
{
return __('module_names.worksheets.plural_label');
}
A hiányzó
fordítás részeket a module names szótárban bővítsük ki: a
'navigation_groups'-hoz adjuk hozzá a 'failure_report'-ot 'Failure
report' névvel angolul és 'Hibabejelentés' névvel magyarul. Továbbá egy
'worksheets' szekciót a 'documents'-hez hasonlóan.
A megszokott
módon pedig a CreateWorksheet és EditWorksheet osztályokhoz adjuk hozzá a
getRedirectUrl() metódust, amellyel a mentés után elirányítjuk a
felhasználót a munkalapok index oldalára.
Űrlap
Az
űrlap lesz a feladatban a legbonyolultabb: azért is ez, mivel különböző
fajta ellenőrzéseket, érvényesítéseket kell a bemeneti elemekhez
illeszteni, illetve a bemutató további részében jogosultságokhoz is
kötjük majd az egyes elemek kitöltésének / szerkesztésének
engedélyezését, így ami ebben az alfejezetben elkészül űrlap, az még nem
a végleges megoldása lesz ennek. Itt van az űrlap első változata,
alatta pedig az egyes mezők magyarázatai következnek:
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Section::make()->schema([
Forms\Components\Select::make('device_id')->label(__('module_names.devices.label'))
->relationship('device', 'name')
->required(),
Forms\Components\Select::make('creator_id')->label(__('fields.creator'))
->relationship('creator', 'name')
->required(),
Forms\Components\Select::make('repairer_id')->label(__('fields.repairer'))
->options(User::role('repairer')->get()->pluck('name', 'id')),
Forms\Components\Select::make('priority')->label(__('fields.priority'))
->options(WorksheetPriority::class)
->default('Normal')
->required(),
Forms\Components\Textarea::make('description')->label(__('fields.description'))
->required()
->maxLength(65535)
->columnSpanFull(),
Forms\Components\DatePicker::make('due_date')->label(__('fields.due_date'))
->minDate(now()),
Forms\Components\DatePicker::make('finish_date')->label(__('fields.finish_date'))
->minDate(now())
->default(now()),
Forms\Components\FileUpload::make('attachments')->label(__('fields.attachments'))
->required()
->multiple()
->preserveFilenames()
->openable()
->downloadable()
->columnSpanFull(),
Forms\Components\Textarea::make('comment')->label(__('fields.note'))
->maxLength(65535)
->columnSpanFull(),
])
]);
}
Részletezések:
- Az egész űrlapot, ahogy korábban is tettük, egy szekcióba foglaljuk.
- Minden munkalapot egy berendezéshez kapcsolunk, ez kötelezően kitöltendő mező.
- A karbantartói lenyíló listában csak azokat a felhasználókat jelenítjük meg, akik karbantartói szerepkörrel rendelkeznek.
- A prioritások a WorksheetPriority Enum osztályból érkeznek, alapból Normál priorítást állítunk be.
- A hiba leírása kötelező mező.
- Határidő és befejezés dátuma mezőknél minimum az aktuális napi dátumot állítjuk be az ellenőrzésben.
- A
fájl csatolása itt alapvetően a képeket jelenti, amit az operátor (vagy
más gépkezelő személy) a hibáról készíthet és feltölthet. Több képet is
mellékelhet itt, amelyek utána megnyithatóak és letölthetőek lesznek.
- Az
űrlap végén lévő egyéni megjegyzés nem kötelező, de a hiba
bejelentőjének itt adunk lehetőséget arra, hogy leírhassa a saját
véleményét a hibáról, vagy karbantartási javaslatot írjon a címzettnek.
Tipp:
ha úgy szeretnénk beállítani, hogy lehessen késés is a karbantartásnál,
vagyis a befejezés dátuma későbbi legyen, mint a megadott határidő,
akkor ezt is érdemes lekezelni valahogy. Például ha későbbi a befejezés
dátuma, mint a határidő dátuma, akkor automatikusan kerüljön majd
kiszűrésre, hogy ez egy késedelmes feladat; esetleg legyen egy külön
opció (bool) eltárolva az adattáblában, hogy késős-e a feladat, mert
akkor be tudunk állítani egy maximális dátumot a befejezés dátumára, ami
a határidő lesz és csak akkor engedünk ennél későbbi dátumot beállítani
neki, ha átváltja a kapcsolót a karbantartó, hogy ez már egy késedelmes
javítás dokumentálása.
Táblázat
A táblázatban a hibás
berendezés nevét, a hiba rövid leírását, a karbantartás prioritását és a
létrehozás dátumát (idejét) helyezzük el láthatóan, a többi mező is
maradhat, viszont alapértelmezetten rejtsük el őket. Az erőforrás
automatikus generálása már jó néhányat mezőt elhelyezett a table()
columns()-t érintő metódus visszatérési tömbjében ezek közül, úgyhogy
nagyjából csak válogatásra és esetleg pontosításra van szükségünk.
Tables\Columns\TextColumn::make('id')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('created_at')->label(__('fields.created_at'))
->dateTime('Y-m-d H:i')
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('device.name')->label(__('module_names.devices.label'))
->numeric()
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('description')->label(__('fields.description'))
->limit(30)
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('priority')->label(__('fields.priority'))
->searchable()
->sortable(),
Tables\Columns\TextColumn::make('creator.name')->label(__('fields.creator'))
->numeric()
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('repairer.name')->label(__('fields.repairer'))
->numeric()
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('due_date')->label(__('fields.due_date'))
->date('Y-m-d')
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('finish_date')->label(__('fields.finish_date'))
->date('Y-m-d')
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')->label(__('fields.updated_at'))
->dateTime('Y-m-d H:i')
->searchable()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Az
itt látható oszlop tulajdonságokat már mind ismerjük, kivétel talán a
description (leírás) oszlopnál látható limit() segédmetódust, amelyben
30 karakterben maximalizáltuk azt a hosszt, amelyet a táblázat megmutat
nekünk a hiba leírásáról. Ha ennél többet szeretnénk megmutatni, akkor
át kell állítani a paraméter értékét, de ha valaki az adatsor értékeinek
megtekintésére kattint, akkor úgyis részletesen láthatja a mezők
értékeit. Ehhez azonban hozzuk létre a munkalapok megtekintés nézetét:
php artisan make:filament-page ViewWorksheet --resource=WorksheetResource --type=ViewRecord
Így létrejön a WorksheetResource / Pages mappában a ViewWorksheet.php fájl.
Ha pedig a WorksheetResource.php getPages() metódusának visszatérési tömbjéhez hozzáadjuk az alábbi kiemelt sort:
return [
'index' => Pages\ListWorksheets::route('/'),
'create' => Pages\CreateWorksheet::route('/create'),
'view' => Pages\ViewWorksheet::route('/{record}'),
'edit' => Pages\EditWorksheet::route('/{record}/edit'),
];
Így most már a table() metódusban a visszatérési
$table objektum actions() metódusához hozzáadhatjuk (elsőként) a
ViewAction-t és akkor a táblázatos nézetben egyből fel fog tűnni a
Megtekintés link a sorokban.
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
Szeretnénk viszont megfordítani a sorrendet, így
adjuk hozzá a table() metódus visszatérési $table tömbjéhez ezt a
metódushívást (első paraméter az, hogy melyik oszlop szerint rendezzünk,
alapértelmezetten növekvőben, hacsak nem adjuk meg a második
paraméterben, hogy visszafelé rendezzük):
->defaultSort('created_at', 'desc')
Így a legfrissebb munkalapok fognak legelőször látszódni a táblázatban. Az eredmény itt látható mintaadatok felvitele után:
A prioritás szerinti szűrőket (tab-okat) helyezzük el még a táblázat
felett. A prioritás értékei a WorksheetPriority enum osztály alapján
kerülnek meghatározásra. A ListWorksheets.php -hoz adjuk hozzá még a tab-os szűrőt és az alapértelmezetten aktív tab-ot.
public function getTabs(): array
{
$tabs = [
'all' => Tab::make()->label(__('fields.all'))
->icon('heroicon-o-list-bullet')
->badge(Worksheet::query()->count()),
];
$priorities = array_column(WorksheetPriority::cases(), 'value');
foreach ($priorities as $priority) {
$tabs[$priority] = Tab::make()->label($priority)
->modifyQueryUsing(
fn (Builder $query) => $query
->where('priority', $priority)
)
->badge(
Worksheet::query()
->where('priority', $priority)
->count()
)
->icon(WorksheetPriority::tryFrom($priority)?->getIcon());
}
return $tabs;
}
public ?string $activeTab = 'all';
A
WorksheetPriority Enum osztályt használtuk ehhez, így nyertük ki a
prioritások értékeit, aztán pedig az értékeknek megfelelő címkéket és
ikonokat. Így most már a prioritás szerinti szűrők is működnek:
Engedélyeztetés
A
munkalapok menedzselése során különösen fontos, hogy pontosan
átgondoljuk, melyik mezőhöz ki férhet hozzá, ki láthatja, illetve ki
szerkesztheti és mikor.
WorksheetPolicy
Hozzuk létre, ahogy már korábban is tettük:
php artisan make:policy WorksheetPolicy --model=Worksheet
Az osztály lényegi tartalma pedig:
public function viewAny(User $user): bool
{
return $user->can('read worksheets');
}
public function view(User $user, Worksheet $worksheet): bool
{
return $user->can('read worksheets');
}
public function create(User $user): bool
{
return $user->can('create worksheets');
}
public function update(User $user, Worksheet $worksheet): bool
{
return $user->can('update worksheets');
}
public function delete(User $user, Worksheet $worksheet): bool
{
return $user->can('delete worksheets');
}
Az újonnan létrehozott WorksheetPolicy osztályt érdemes már most bekötni a rendszerbe az AuthServiceProvider osztály $policies tömbjének bővítésével:
Worksheet::class => WorksheetPolicy::class,
Az importálásokról sem feledkezzünk meg az osztály előtt (Worksheet, WorksheetPolicy).
Ahogy
említettem, érdemes átgondolni, hogy kinek mit engedélyezünk. A törlést
leginkább csak az adminisztrátor felhasználóknak. A frissítést a
karbantartóknak és az adminisztrátoroknak. A létrehozásnál már szóba
jönnek az operátorok is, akiknek lehetőséget kell erre adni. Mindezeket a
beállításokat az adminisztrációs felületen az adminisztrátor
felhasználó végre tudja hajtani:
- Hozzá kell adni ezeket az új jogosultságokat a rendszerhez, majd ...
- a szerepkörök szerkesztésénél, új jogosultságokkal kell ellátni a szerepköröket az itt leírtak szerint: admin: mind a négy új jogosultság (create, read, update, delete worksheets), karbantartónál három új jogosultság (create, read, update worksheets), operátornál két új jogosultság (create, read worksheets).
Táblázat v2 !?
Inkább ne... Felmerülhet az az "issue", hogy ha az adott felhasználó, aki listázza a munkalapokat, nem rendelkezik "update worksheets" jogosultsággal, tehát nem karbantartó és nem adminisztrátor, csak operátor, akkor neki csak azt engedjük meg, hogy a saját maga által létrehozott munkalapokat láthassa. Ez azonban annyiból nem lenne jó, hogy akár különböző operátorok, ugyanahhoz a berendezéshez, ugyanazt a problémát többször, egymástól függetlenül lejelentik a karbantartóknak. Ezt természetesen nem szeretnénk.
Ha valaki mégis megtenné ezt, vagy valamilyen hasonló szűrést alkalmazna, akkor azt a WorksheetResource osztályban kellene definiálnia:
public static function getEloquentQuery(): Builder
{
if (!auth()->user()->can('update worksheets')) {
return parent::getEloquentQuery()->where('creator_id', auth()->user()->id);
}
return parent::getEloquentQuery();
}
Űrlap v2
Az űrlapot viszont módosítanunk kell több bemenetnél is:
- device_id: berendezést engedjünk kiválasztani a bejelentő operátornak is, módosítani úgysem tudja létrehozás után csak a karbantartó és az adminisztrátor.
- creator_id: a létrehozó személy azonosítója. Alapértelmezetten állítsuk be úgy, hogy ha operátor a létrehozó, akkor ő maga legyen ide elhelyezve és ne lehessen ezt módosítani, ha karbantartó vagy admin, akkor pedig ne legyen alapértelmezett értéke és módosítható legyen a számukra az értéke.
- repairer_id: a karbantartó személyének kiválasztását tiltsuk is le az operátoroknak. Ezt a mezőt csak a karbantartó és az admin tudja módosítani, beállítani.
- description: leírást meg kell adnia létrehozáskor az operátornak, utána szerkeszteni már nem fogja tudni.
- priority: prioritást engedjünk kiválasztani a bejelentő operátornak is, módosítani úgysem
tudja létrehozás után csak a karbantartó és az adminisztrátor.
- due_date: javítási határidőt az operátor ne szabhasson meg a karbantartóknak, úgyhogy ennek a mezőnek a hozzáférését limitálni kell az operátor számára, neki ne is jelenítsük meg!
- finish_date: az operátorok elől ezt már ne rejtsük el (láthassák, hogy mikor történt meg a javítás), viszont ne tudják szerkeszteni ezt a mezőt.
- attachments: csak képet lehessen feltölteni és egy újdonságot is kipróbálhatunk! Ha a feltöltött kép fölé visszük az egeret, akkor alul megjelenik egy ceruza menüpont, amelyet kiválaszthatunk és szerkeszthetővé válik az a kép, amit esetleg a hibáról lefotóztunk.
- note: a megjegyzés mezőnél nincs szükség további megszorításokra.
Mindezeket a beállításokat így végezhetjük el a form() metódusban:
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Section::make()->schema([
Forms\Components\Select::make('device_id')->label(__('module_names.devices.label'))
->relationship('device', 'name')
->required(),
Forms\Components\Select::make('creator_id')->label(__('fields.creator'))
->relationship('creator', 'name')
->default(!auth()->user()->can('update worksheets') ? auth()->user()->id : null)
->disabled(!auth()->user()->can('update worksheets') ? true : false)
->required(),
Forms\Components\Select::make('repairer_id')->label(__('fields.repairer'))
->options(User::role('repairer')->get()->pluck('name', 'id'))
->disabled(!auth()->user()->can('update worksheets')),
Forms\Components\Select::make('priority')->label(__('fields.priority'))
->options(WorksheetPriority::class)
->default('Normal')
->required(),
Forms\Components\Textarea::make('description')->label(__('fields.description'))
->required()
->maxLength(65535)
->columnSpanFull(),
Forms\Components\DatePicker::make('due_date')->label(__('fields.due_date'))
->hidden( ! auth()->user()->can('update worksheets'))
->minDate(now()),
Forms\Components\DatePicker::make('finish_date')->label(__('fields.finish_date'))
->disabled(!auth()->user()->can('update worksheets'))
->minDate(now())
->default(now()),
Forms\Components\FileUpload::make('attachments')->label(__('fields.attachments'))
->required()
->image()
->imageEditor()
->imageEditorAspectRatios([
null,
'16:9',
'4:3',
'1:1',
])
->imageEditorEmptyFillColor('#000000')
->imageEditorViewportWidth('1920')
->imageEditorViewportHeight('1080')
->multiple()
->preserveFilenames()
->openable()
->downloadable()
->columnSpanFull(),
Forms\Components\Textarea::make('comment')->label(__('fields.note'))
->maxLength(65535)
->columnSpanFull(),
])
]);
}
A kép szerkesztési modal ablak így néz ki:
Az utóbbi módosításokkal több mezőt (creator_id, repairer_id, finish_date) is letiltottunk az operátor számára, és valamit el is rejtettünk előle, miközben valamelyik mezőnek a kitöltése kötelező a worksheets adattábla kényszerei miatt. Ezeket a kiegészítéseket a CreateWorksheet és EditWorksheet osztályokban tudjuk megtenni ahhoz, hogy ne okozhasson problémát az adattábla feltöltésekor vagy módosításakor. Kényszerek szempontjából csak a creator_id-vel kell foglalkoznunk, a többi mezző nem problémás. CreateWorksheet osztály új metódusa:
protected function mutateFormDataBeforeCreate(array $data): array
{
if (!isset($data['creator_id']))
$data['creator_id'] = auth()->user()->id;
return $data;
}
Ha nincs beállítva a creator_id mező, mert az operátoroknak le van tiltva ennek módosítása már a létrehozáskor, akkor beállítjuk ennek az értéket az adattábla feltöltése előtt.
Ugyanezt kellene megtennünk szerkesztéskor is, viszont csak karbantartók és adminisztrátorok tudják szerkeszteni a munkalapot, akiknél ez a mező nincs letiltva az űrlapon, emiatt nem kell módosítanunk az EditWorksheet osztályt.
Összegzés, továbblépés
Ebben a részben a munkalapokkal foglalkoztam. Elég részletes űrlapot definiáltam nekik, amelyet aztán számos új technikával vérteztem fel validálási és engedélyeztetési oldalról. A fejezetben található programkód módosításokat ebben a GitHub commit-ben lehet megtalálni. (Megjegyzés: a Filament-et is érdemes felfrissíteni, ha már régebben használtuk, úgyhogy ezeket a módosításokat - csak CSS és JS fájlokat - is tartalmazza a GitHub commit.)
A munkalapokkal kapcsolatos rész nem ért itt még véget, folytatom még a finomhangolást, illetve rátérek a munkalapok kapcsolataira. Ezáltal látható lesz a berendezések "kórtörténete" (hiba- és javítási listája), a felhasználók látni fogják a saját munkalapjaikat, hogy hogyan alakult az általuk jelentett hiba javítása, kezelése. Majd rátérek még a widget-ekre is, hiszen a munkalapok sok értékes információt tartalmazhatnak a karbantartási részleg számára és a döntéshozóknak is.
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!