Added maintenance type strings
This commit is contained in:
@@ -31,6 +31,9 @@ enum ActionType: string
|
||||
case DeleteSeats = 'delete seats';
|
||||
case AddSeats = 'add seats';
|
||||
|
||||
// Maintenances
|
||||
case MaintenanceComplete = 'completed';
|
||||
|
||||
// File Uploads
|
||||
case Uploaded = 'uploaded';
|
||||
case UploadDeleted = 'upload deleted';
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\FilterRequest;
|
||||
use App\Http\Transformers\MaintenanceTypesTransformer;
|
||||
use App\Models\MaintenanceType;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MaintenanceTypesController extends Controller
|
||||
{
|
||||
public function index(FilterRequest $request): JsonResponse|array
|
||||
{
|
||||
$this->authorize('view', MaintenanceType::class);
|
||||
|
||||
$types = MaintenanceType::select(['id', 'name', 'created_at', 'updated_at', 'deleted_at']);
|
||||
|
||||
if ($request->input('deleted') == 'true') {
|
||||
$types->onlyTrashed();
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$types->where('name', 'LIKE', '%'.$request->input('search').'%');
|
||||
}
|
||||
|
||||
if ($request->filled('name')) {
|
||||
$types->where('name', '=', $request->input('name'));
|
||||
}
|
||||
|
||||
$offset = ($request->input('offset') > $types->count()) ? $types->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), ['id', 'name', 'created_at', 'updated_at']) ? $request->input('sort') : 'name';
|
||||
|
||||
$total = $types->count();
|
||||
$types = $types->orderBy($sort, $order)->skip($offset)->take($limit)->get();
|
||||
|
||||
return (new MaintenanceTypesTransformer)->transformMaintenanceTypes($types, $total);
|
||||
}
|
||||
|
||||
public function show(MaintenanceType $maintenanceType): JsonResponse|array
|
||||
{
|
||||
$this->authorize('view', $maintenanceType);
|
||||
|
||||
return (new MaintenanceTypesTransformer)->transformMaintenanceType($maintenanceType);
|
||||
}
|
||||
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$this->authorize('create', MaintenanceType::class);
|
||||
|
||||
$type = new MaintenanceType;
|
||||
$type->name = $request->input('name');
|
||||
$type->created_by = auth()->id();
|
||||
|
||||
if ($type->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new MaintenanceTypesTransformer)->transformMaintenanceType($type), trans('admin/maintenance_types/message.create.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $type->getErrors()));
|
||||
}
|
||||
|
||||
public function update(Request $request, MaintenanceType $maintenanceType): JsonResponse
|
||||
{
|
||||
$this->authorize('update', $maintenanceType);
|
||||
|
||||
$maintenanceType->name = $request->input('name');
|
||||
|
||||
if ($maintenanceType->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new MaintenanceTypesTransformer)->transformMaintenanceType($maintenanceType), trans('admin/maintenance_types/message.update.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $maintenanceType->getErrors()));
|
||||
}
|
||||
|
||||
public function destroy(MaintenanceType $maintenanceType): JsonResponse
|
||||
{
|
||||
$this->authorize('delete', $maintenanceType);
|
||||
|
||||
$maintenanceType->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/maintenance_types/message.delete.success')));
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\FilterRequest;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Transformers\ActionlogsTransformer;
|
||||
use App\Http\Transformers\MaintenancesTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\Maintenance;
|
||||
@@ -39,7 +41,7 @@ class MaintenancesController extends Controller
|
||||
|
||||
$maintenances = Maintenance::select('maintenances.*')
|
||||
->whereHas('asset')
|
||||
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.status', 'adminuser', 'asset.assignedTo');
|
||||
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.status', 'adminuser', 'asset.assignedTo', 'maintenanceType', 'responsibleParty', 'completedByUser');
|
||||
|
||||
// This invokes the Searchable model trait scopeTextSearch and will handle input by search or by advanced search filter
|
||||
if ($request->filled('filter') || $request->filled('search')) {
|
||||
@@ -66,6 +68,14 @@ class MaintenancesController extends Controller
|
||||
$maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type'));
|
||||
}
|
||||
|
||||
if ($request->filled('maintenance_type_id')) {
|
||||
$maintenances->where('maintenance_type_id', '=', $request->input('maintenance_type_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('responsible_party_id')) {
|
||||
$maintenances->where('responsible_party_id', '=', $request->input('responsible_party_id'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $maintenances->count()) ? $maintenances->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
@@ -256,6 +266,33 @@ class MaintenancesController extends Controller
|
||||
|
||||
}
|
||||
|
||||
public function complete(Request $request, Maintenance $maintenance): JsonResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $maintenance->id, 'action' => trans('admin/maintenances/form.mark_complete')])));
|
||||
}
|
||||
|
||||
if ($maintenance->completed_at) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/maintenances/form.already_complete')));
|
||||
}
|
||||
|
||||
$maintenance->completed_at = now();
|
||||
$maintenance->completed_by = auth()->id();
|
||||
$maintenance->saveQuietly();
|
||||
|
||||
$logAction = new Actionlog;
|
||||
$logAction->item_type = Maintenance::class;
|
||||
$logAction->item_id = $maintenance->id;
|
||||
$logAction->target_type = Asset::class;
|
||||
$logAction->target_id = $maintenance->asset_id;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction(ActionType::MaintenanceComplete);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new MaintenancesTransformer)->transformMaintenance($maintenance->fresh()), trans('admin/maintenances/message.complete.success')));
|
||||
}
|
||||
|
||||
public function history(Request $request, Maintenance $maintenance): JsonResponse|array
|
||||
{
|
||||
$this->authorize('history', $maintenance);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\MaintenanceType;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class MaintenanceTypesController extends Controller
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
$this->authorize('index', MaintenanceType::class);
|
||||
|
||||
return view('maintenance-types.index');
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
$this->authorize('create', MaintenanceType::class);
|
||||
|
||||
return view('maintenance-types.edit')->with('item', new MaintenanceType);
|
||||
}
|
||||
|
||||
public function store(Request $request): RedirectResponse
|
||||
{
|
||||
$this->authorize('create', MaintenanceType::class);
|
||||
|
||||
$type = new MaintenanceType;
|
||||
$type->name = $request->input('name');
|
||||
$type->created_by = auth()->id();
|
||||
|
||||
if ($type->save()) {
|
||||
return redirect()->route('maintenance-types.index')
|
||||
->with('success', trans('admin/maintenance_types/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($type->getErrors());
|
||||
}
|
||||
|
||||
public function edit(MaintenanceType $maintenanceType): View
|
||||
{
|
||||
$this->authorize('update', $maintenanceType);
|
||||
|
||||
return view('maintenance-types.edit')->with('item', $maintenanceType);
|
||||
}
|
||||
|
||||
public function update(Request $request, MaintenanceType $maintenanceType): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $maintenanceType);
|
||||
|
||||
$maintenanceType->name = $request->input('name');
|
||||
|
||||
if ($maintenanceType->save()) {
|
||||
return redirect()->route('maintenance-types.index')
|
||||
->with('success', trans('admin/maintenance_types/message.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($maintenanceType->getErrors());
|
||||
}
|
||||
|
||||
public function destroy(MaintenanceType $maintenanceType): RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', $maintenanceType);
|
||||
|
||||
$maintenanceType->delete();
|
||||
|
||||
return redirect()->route('maintenance-types.index')
|
||||
->with('success', trans('admin/maintenance_types/message.delete.success'));
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,13 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\ActionType;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\MaintenanceType;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
@@ -57,6 +60,7 @@ class MaintenancesController extends Controller
|
||||
|
||||
return view('maintenances/edit')
|
||||
->with('maintenanceType', Maintenance::getImprovementOptions())
|
||||
->with('maintenanceTypes', MaintenanceType::orderBy('name')->get())
|
||||
->with('asset', $asset)
|
||||
->with('item', new Maintenance);
|
||||
}
|
||||
@@ -92,9 +96,11 @@ class MaintenancesController extends Controller
|
||||
// Save the asset maintenance data
|
||||
$maintenance->asset_id = $asset->id;
|
||||
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$maintenance->maintenance_type_id = $request->input('maintenance_type_id');
|
||||
$maintenance->name = $request->input('name');
|
||||
$maintenance->start_date = $request->input('start_date');
|
||||
$maintenance->completion_date = $request->input('completion_date');
|
||||
$maintenance->responsible_party_id = $request->input('responsible_party_id') ?: auth()->id();
|
||||
$maintenance->created_by = auth()->id();
|
||||
|
||||
if (($maintenance->completion_date !== null)
|
||||
@@ -141,6 +147,7 @@ class MaintenancesController extends Controller
|
||||
->with('selected_assets', $maintenance->asset->pluck('id')->toArray())
|
||||
->with('asset_ids', request()->input('asset_ids', []))
|
||||
->with('maintenanceType', Maintenance::getImprovementOptions())
|
||||
->with('maintenanceTypes', MaintenanceType::orderBy('name')->get())
|
||||
->with('item', $maintenance);
|
||||
}
|
||||
|
||||
@@ -169,9 +176,11 @@ class MaintenancesController extends Controller
|
||||
$maintenance->cost = $request->input('cost');
|
||||
$maintenance->notes = $request->input('notes');
|
||||
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$maintenance->maintenance_type_id = $request->input('maintenance_type_id');
|
||||
$maintenance->name = $request->input('name');
|
||||
$maintenance->start_date = $request->input('start_date');
|
||||
$maintenance->completion_date = $request->input('completion_date');
|
||||
$maintenance->responsible_party_id = $request->input('responsible_party_id');
|
||||
$maintenance->url = $request->input('url');
|
||||
|
||||
// Todo - put this in a getter/setter?
|
||||
@@ -253,6 +262,34 @@ class MaintenancesController extends Controller
|
||||
)->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a maintenance record as complete, logging who completed it and when.
|
||||
*/
|
||||
public function complete(Request $request, Maintenance $maintenance): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $maintenance->asset);
|
||||
|
||||
if ($maintenance->completed_at) {
|
||||
return redirect()->back()
|
||||
->with('warning', trans('admin/maintenances/form.already_complete'));
|
||||
}
|
||||
|
||||
$maintenance->completed_at = now();
|
||||
$maintenance->completed_by = auth()->id();
|
||||
$maintenance->saveQuietly();
|
||||
|
||||
$logAction = new Actionlog;
|
||||
$logAction->item_type = Maintenance::class;
|
||||
$logAction->item_id = $maintenance->id;
|
||||
$logAction->target_type = Asset::class;
|
||||
$logAction->target_id = $maintenance->asset_id;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->logaction(ActionType::MaintenanceComplete);
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/maintenances/message.complete.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an asset maintenance
|
||||
*
|
||||
|
||||
@@ -30,6 +30,7 @@ class ModalController extends Controller
|
||||
'kit-consumable',
|
||||
'kit-accessory',
|
||||
'location',
|
||||
'maintenance-type',
|
||||
'manufacturer',
|
||||
'model',
|
||||
'statuslabel',
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\MaintenanceType;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class MaintenanceTypesTransformer
|
||||
{
|
||||
public function transformMaintenanceTypes(Collection $types, int $total): array
|
||||
{
|
||||
$array = [];
|
||||
foreach ($types as $type) {
|
||||
$array[] = self::transformMaintenanceType($type);
|
||||
}
|
||||
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
public function transformMaintenanceType(MaintenanceType $type): array
|
||||
{
|
||||
return [
|
||||
'id' => (int) $type->id,
|
||||
'name' => e($type->name),
|
||||
'created_at' => Helper::getFormattedDateObject($type->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($type->updated_at, 'datetime'),
|
||||
'deleted_at' => Helper::getFormattedDateObject($type->deleted_at, 'datetime'),
|
||||
'available_actions' => [
|
||||
'update' => Gate::allows('update', $type),
|
||||
'delete' => $type->isDeletable(),
|
||||
'restore' => Gate::allows('delete', $type),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,24 @@ class MaintenancesTransformer
|
||||
'id' => (int) $assetmaintenance->adminuser->id,
|
||||
'name' => e($assetmaintenance->adminuser->display_name),
|
||||
] : null,
|
||||
'maintenance_type' => ($assetmaintenance->maintenanceType) ? [
|
||||
'id' => (int) $assetmaintenance->maintenanceType->id,
|
||||
'name' => e($assetmaintenance->maintenanceType->name),
|
||||
] : null,
|
||||
'maintenance_type_name' => $assetmaintenance->maintenanceType ? e($assetmaintenance->maintenanceType->name) : null,
|
||||
'responsible_party' => ($assetmaintenance->responsibleParty) ? [
|
||||
'id' => (int) $assetmaintenance->responsibleParty->id,
|
||||
'name' => e($assetmaintenance->responsibleParty->display_name),
|
||||
] : null,
|
||||
'checked_out_to_at_creation' => $assetmaintenance->checked_out_to_id ? [
|
||||
'id' => (int) $assetmaintenance->checked_out_to_id,
|
||||
'type' => $assetmaintenance->checked_out_to_type,
|
||||
] : null,
|
||||
'completed_at' => Helper::getFormattedDateObject($assetmaintenance->completed_at, 'datetime'),
|
||||
'completed_by' => ($assetmaintenance->completedByUser) ? [
|
||||
'id' => (int) $assetmaintenance->completedByUser->id,
|
||||
'name' => e($assetmaintenance->completedByUser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
|
||||
'is_warranty' => (bool) $assetmaintenance->is_warranty,
|
||||
@@ -91,6 +109,7 @@ class MaintenancesTransformer
|
||||
$permissions_array['available_actions'] = [
|
||||
'update' => (Gate::allows('update', Asset::class) && ((($assetmaintenance->asset) && $assetmaintenance->asset->deleted_at == ''))) ? true : false,
|
||||
'delete' => Gate::allows('delete', Asset::class),
|
||||
'complete' => Gate::allows('update', Asset::class) && ! $assetmaintenance->completed_at,
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
@@ -39,7 +39,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild
|
||||
protected $rules = [
|
||||
'asset_id' => 'required|integer',
|
||||
'supplier_id' => 'nullable|integer',
|
||||
'asset_maintenance_type' => 'required',
|
||||
'maintenance_type_id' => 'required|integer|exists:maintenance_types,id',
|
||||
'name' => 'required|max:100',
|
||||
'is_warranty' => 'boolean',
|
||||
'start_date' => 'required|date_format:Y-m-d',
|
||||
@@ -47,6 +47,8 @@ class Maintenance extends SnipeModel implements ICompanyableChild
|
||||
'notes' => 'string|nullable',
|
||||
'cost' => 'numeric|nullable|gte:0|max:99999999999999999.99',
|
||||
'url' => 'nullable|url|max:255',
|
||||
'responsible_party_id' => 'nullable|integer|exists:users,id',
|
||||
'completed_by' => 'nullable|integer|exists:users,id',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -59,6 +61,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild
|
||||
'asset_id',
|
||||
'supplier_id',
|
||||
'asset_maintenance_type',
|
||||
'maintenance_type_id',
|
||||
'is_warranty',
|
||||
'start_date',
|
||||
'completion_date',
|
||||
@@ -66,6 +69,11 @@ class Maintenance extends SnipeModel implements ICompanyableChild
|
||||
'notes',
|
||||
'cost',
|
||||
'url',
|
||||
'checked_out_to_id',
|
||||
'checked_out_to_type',
|
||||
'responsible_party_id',
|
||||
'completed_at',
|
||||
'completed_by',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
@@ -204,6 +212,28 @@ class Maintenance extends SnipeModel implements ICompanyableChild
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function maintenanceType()
|
||||
{
|
||||
return $this->belongsTo(MaintenanceType::class, 'maintenance_type_id');
|
||||
}
|
||||
|
||||
public function responsibleParty()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'responsible_party_id')
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function completedByUser()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'completed_by')
|
||||
->withTrashed();
|
||||
}
|
||||
|
||||
public function checkedOutTo()
|
||||
{
|
||||
return $this->morphTo('checked_out_to');
|
||||
}
|
||||
|
||||
public function getDisplayNameAttribute()
|
||||
{
|
||||
return $this->name;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class MaintenanceType extends SnipeModel
|
||||
{
|
||||
use HasFactory;
|
||||
use Presentable;
|
||||
use SoftDeletes;
|
||||
use ValidatingTrait;
|
||||
|
||||
protected $table = 'maintenance_types';
|
||||
|
||||
protected $rules = [
|
||||
'name' => 'required|max:100|unique:maintenance_types,name,NULL,id,deleted_at,NULL',
|
||||
];
|
||||
|
||||
protected $injectUniqueIdentifier = true;
|
||||
|
||||
protected $fillable = ['name'];
|
||||
|
||||
public function isDeletable(): bool
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->deleted_at == '');
|
||||
}
|
||||
|
||||
public function maintenances()
|
||||
{
|
||||
return $this->hasMany(Maintenance::class, 'maintenance_type_id');
|
||||
}
|
||||
|
||||
public function getDisplayNameAttribute(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
@@ -5,9 +5,23 @@ namespace App\Observers;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\MaintenanceType;
|
||||
|
||||
class MaintenanceObserver
|
||||
{
|
||||
/**
|
||||
* Capture the asset's current checkout state before the maintenance record is saved.
|
||||
*/
|
||||
public function creating(Maintenance $maintenance): void
|
||||
{
|
||||
if ($maintenance->asset_id && $asset = Asset::find($maintenance->asset_id)) {
|
||||
$maintenance->checked_out_to_id = $asset->assigned_to;
|
||||
$maintenance->checked_out_to_type = $asset->assigned_type;
|
||||
}
|
||||
|
||||
$this->syncLegacyMaintenanceType($maintenance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the User created event.
|
||||
*
|
||||
@@ -15,6 +29,8 @@ class MaintenanceObserver
|
||||
*/
|
||||
public function updating(Maintenance $maintenance)
|
||||
{
|
||||
$this->syncLegacyMaintenanceType($maintenance);
|
||||
|
||||
$changed = [];
|
||||
|
||||
foreach ($maintenance->getRawOriginal() as $key => $value) {
|
||||
@@ -47,6 +63,16 @@ class MaintenanceObserver
|
||||
$logAction->logaction('update');
|
||||
}
|
||||
|
||||
private function syncLegacyMaintenanceType(Maintenance $maintenance): void
|
||||
{
|
||||
if ($maintenance->maintenance_type_id && ! $maintenance->asset_maintenance_type) {
|
||||
$type = MaintenanceType::find($maintenance->maintenance_type_id);
|
||||
if ($type) {
|
||||
$maintenance->asset_maintenance_type = $type->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listen to the Component created event when
|
||||
* a new component is created.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
class MaintenanceTypePolicy extends SnipePermissionsPolicy
|
||||
{
|
||||
protected function columnName()
|
||||
{
|
||||
return 'maintenances';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
class MaintenanceTypePresenter extends Presenter
|
||||
{
|
||||
public static function dataTableLayout(): string
|
||||
{
|
||||
$layout = [
|
||||
[
|
||||
'field' => 'id',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.id'),
|
||||
'visible' => false,
|
||||
], [
|
||||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'visible' => true,
|
||||
], [
|
||||
'field' => 'created_at',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.created_at'),
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'updated_at',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.updated_at'),
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'actions',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
'visible' => true,
|
||||
'formatter' => 'maintenanceTypesActionsFormatter',
|
||||
'printIgnore' => true,
|
||||
],
|
||||
];
|
||||
|
||||
return json_encode($layout);
|
||||
}
|
||||
}
|
||||
@@ -88,7 +88,7 @@ class MaintenancesPresenter extends Presenter
|
||||
'switchable' => true,
|
||||
'title' => trans('general.model_no'),
|
||||
'visible' => true,
|
||||
],[
|
||||
], [
|
||||
'field' => 'assigned_to',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
@@ -110,11 +110,51 @@ class MaintenancesPresenter extends Presenter
|
||||
'sortable' => true,
|
||||
'title' => trans('general.location'),
|
||||
'formatter' => 'locationsLinkObjFormatter',
|
||||
], [
|
||||
'field' => 'maintenance_type_name',
|
||||
'searchable' => true,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/maintenances/form.asset_maintenance_type'),
|
||||
'visible' => true,
|
||||
], [
|
||||
'field' => 'asset_maintenance_type',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/maintenances/form.asset_maintenance_type'),
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/maintenances/form.asset_maintenance_type').' (legacy)',
|
||||
'visible' => false,
|
||||
], [
|
||||
'field' => 'responsible_party',
|
||||
'searchable' => true,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/maintenances/form.responsible_party'),
|
||||
'visible' => false,
|
||||
'formatter' => 'usersLinkObjFormatter',
|
||||
], [
|
||||
'field' => 'checked_out_to_at_creation',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/maintenances/form.checked_out_to_at_creation'),
|
||||
'visible' => false,
|
||||
], [
|
||||
'field' => 'completed_at',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/maintenances/form.completed_at'),
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'completed_by',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/maintenances/form.completed_by'),
|
||||
'visible' => false,
|
||||
'formatter' => 'usersLinkObjFormatter',
|
||||
], [
|
||||
'field' => 'start_date',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -16,6 +16,7 @@ use App\Models\Depreciation;
|
||||
use App\Models\License;
|
||||
use App\Models\Location;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\MaintenanceType;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\PredefinedKit;
|
||||
use App\Models\Statuslabel;
|
||||
@@ -35,6 +36,7 @@ use App\Policies\DepreciationPolicy;
|
||||
use App\Policies\LicensePolicy;
|
||||
use App\Policies\LocationPolicy;
|
||||
use App\Policies\MaintenancePolicy;
|
||||
use App\Policies\MaintenanceTypePolicy;
|
||||
use App\Policies\ManufacturerPolicy;
|
||||
use App\Policies\PredefinedKitPolicy;
|
||||
use App\Policies\StatuslabelPolicy;
|
||||
@@ -71,6 +73,7 @@ class AuthServiceProvider extends ServiceProvider
|
||||
License::class => LicensePolicy::class,
|
||||
Location::class => LocationPolicy::class,
|
||||
Maintenance::class => MaintenancePolicy::class,
|
||||
MaintenanceType::class => MaintenanceTypePolicy::class,
|
||||
PredefinedKit::class => PredefinedKitPolicy::class,
|
||||
Statuslabel::class => StatuslabelPolicy::class,
|
||||
Supplier::class => SupplierPolicy::class,
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Database\Factories;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\MaintenanceType;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
@@ -24,10 +25,13 @@ class MaintenanceFactory extends Factory
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
$maintenanceType = MaintenanceType::factory()->create();
|
||||
|
||||
return [
|
||||
'asset_id' => Asset::factory()->laptopZenbook(),
|
||||
'supplier_id' => Supplier::factory(),
|
||||
'asset_maintenance_type' => $this->faker->randomElement(['maintenance', 'repair', 'upgrade']),
|
||||
'maintenance_type_id' => $maintenanceType->id,
|
||||
'asset_maintenance_type' => $maintenanceType->name,
|
||||
'name' => $this->faker->sentence(3),
|
||||
'start_date' => $this->faker->date(),
|
||||
'is_warranty' => $this->faker->boolean(),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\MaintenanceType;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class MaintenanceTypeFactory extends Factory
|
||||
{
|
||||
protected $model = MaintenanceType::class;
|
||||
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => $this->faker->unique()->words(2, true),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// Create maintenance_types lookup table
|
||||
Schema::create('maintenance_types', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name', 100);
|
||||
$table->unsignedBigInteger('created_by')->nullable();
|
||||
$table->softDeletes();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
// Seed with the 8 built-in types
|
||||
$now = now();
|
||||
$types = [
|
||||
'Maintenance',
|
||||
'Repair',
|
||||
'Upgrade',
|
||||
'PAT Test',
|
||||
'Calibration',
|
||||
'Software Support',
|
||||
'Hardware Support',
|
||||
'Configuration Change',
|
||||
];
|
||||
|
||||
foreach ($types as $name) {
|
||||
DB::table('maintenance_types')->insert([
|
||||
'name' => $name,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
// Add new tracking columns and the maintenance_type FK to maintenances
|
||||
Schema::table('maintenances', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('maintenance_type_id')->nullable();
|
||||
$table->unsignedBigInteger('checked_out_to_id')->nullable();
|
||||
$table->string('checked_out_to_type')->nullable();
|
||||
$table->unsignedBigInteger('responsible_party_id')->nullable();
|
||||
$table->timestamp('completed_at')->nullable();
|
||||
$table->unsignedBigInteger('completed_by')->nullable();
|
||||
});
|
||||
|
||||
// Map existing string values to new type IDs (best-effort, case-insensitive)
|
||||
$typeMap = [
|
||||
'maintenance' => 'Maintenance',
|
||||
'repair' => 'Repair',
|
||||
'upgrade' => 'Upgrade',
|
||||
'pat_test' => 'PAT Test',
|
||||
'calibration' => 'Calibration',
|
||||
'software_support' => 'Software Support',
|
||||
'hardware_support' => 'Hardware Support',
|
||||
'configuration_change' => 'Configuration Change',
|
||||
];
|
||||
|
||||
foreach ($typeMap as $oldValue => $newName) {
|
||||
$newId = DB::table('maintenance_types')->where('name', $newName)->value('id');
|
||||
if ($newId) {
|
||||
DB::table('maintenances')
|
||||
->where('asset_maintenance_type', $oldValue)
|
||||
->update(['maintenance_type_id' => $newId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('maintenances', function (Blueprint $table) {
|
||||
$table->dropColumn([
|
||||
'maintenance_type_id',
|
||||
'checked_out_to_id',
|
||||
'checked_out_to_type',
|
||||
'responsible_party_id',
|
||||
'completed_at',
|
||||
'completed_by',
|
||||
]);
|
||||
});
|
||||
|
||||
Schema::dropIfExists('maintenance_types');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'maintenance_types' => 'Maintenance Types',
|
||||
'create' => 'Create Maintenance Type',
|
||||
'update' => 'Update Maintenance Type',
|
||||
];
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'not_found' => 'Maintenance type not found.',
|
||||
'create' => [
|
||||
'error' => 'Maintenance type was not created, please try again.',
|
||||
'success' => 'Maintenance type created successfully.',
|
||||
],
|
||||
'update' => [
|
||||
'error' => 'Maintenance type was not updated, please try again.',
|
||||
'success' => 'Maintenance type updated successfully.',
|
||||
],
|
||||
'delete' => [
|
||||
'confirm' => 'Are you sure you wish to delete this maintenance type?',
|
||||
'error' => 'There was an issue deleting this maintenance type. Please try again.',
|
||||
'success' => 'The maintenance type was deleted successfully.',
|
||||
],
|
||||
'complete' => [
|
||||
'success' => 'Maintenance marked as complete.',
|
||||
'error' => 'There was an issue marking this maintenance as complete. Please try again.',
|
||||
],
|
||||
];
|
||||
@@ -18,4 +18,8 @@ return [
|
||||
'asset_maintenance_incomplete' => 'Not Completed Yet',
|
||||
'warranty' => 'Warranty',
|
||||
'not_warranty' => 'Not Warranty',
|
||||
'complete' => [
|
||||
'success' => 'Maintenance marked as complete.',
|
||||
'error' => 'There was an issue marking this maintenance as complete. Please try again.',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -209,6 +209,7 @@ return [
|
||||
'logout' => 'Logout',
|
||||
'lookup_by_tag' => 'Lookup by Asset Tag',
|
||||
'maintenances' => 'Maintenances',
|
||||
'maintenance_complete' => 'Maintenance Complete',
|
||||
'manage_api_keys' => 'Manage API keys',
|
||||
'manufacturer' => 'Manufacturer',
|
||||
'manufacturers' => 'Manufacturers',
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
@section('content')
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
@if ($item->id)
|
||||
<form class="form-horizontal" method="post" action="{{ route('maintenances.update', $item->id) }}" autocomplete="off" enctype="multipart/form-data">
|
||||
{{ method_field('PUT') }}
|
||||
@@ -106,7 +106,36 @@
|
||||
|
||||
@include ('partials.forms.edit.maintenance_type')
|
||||
|
||||
<!-- Start Date -->
|
||||
<!-- Responsible Party -->
|
||||
<div class="form-group {{ $errors->has('responsible_party_id') ? ' has-error' : '' }}">
|
||||
<label for="responsible_party_id" class="col-md-3 control-label">
|
||||
{{ trans('admin/maintenances/form.responsible_party') }}
|
||||
</label>
|
||||
<div class="col-md-7">
|
||||
<select
|
||||
class="js-data-ajax select2"
|
||||
data-endpoint="users"
|
||||
name="responsible_party_id"
|
||||
id="responsible_party_id"
|
||||
data-placeholder="{{ trans('general.select_user') }}"
|
||||
aria-label="responsible_party_id"
|
||||
style="width: 100%;"
|
||||
>
|
||||
@if ($item->responsibleParty)
|
||||
<option value="{{ $item->responsibleParty->id }}" selected="selected">
|
||||
{{ $item->responsibleParty->display_name }}
|
||||
</option>
|
||||
@elseif (! $item->id)
|
||||
<option value="{{ auth()->id() }}" selected="selected">
|
||||
{{ auth()->user()->display_name }}
|
||||
</option>
|
||||
@endif
|
||||
</select>
|
||||
{!! $errors->first('responsible_party_id', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Start Date -->
|
||||
<div class="form-group {{ $errors->has('start_date') ? ' has-error' : '' }}">
|
||||
<label for="start_date" class="col-md-3 control-label">
|
||||
{{ trans('admin/maintenances/form.start_date') }}
|
||||
@@ -157,16 +186,18 @@
|
||||
<!-- Asset Maintenance Cost -->
|
||||
<div class="form-group {{ $errors->has('cost') ? ' has-error' : '' }}">
|
||||
<label for="cost" class="col-md-3 control-label">{{ trans('admin/maintenances/form.cost') }}</label>
|
||||
<div class="col-md-3 text-right">
|
||||
<div class="input-group">
|
||||
<div class="col-md-9">
|
||||
<div class="input-group col-md-5" style="padding-left: 0px;">
|
||||
<input class="form-control" type="text" inputmode="decimal" pattern="[\d.,]+" name="cost" aria-label="cost" id="cost" value="{{ old('cost', \App\Helpers\Helper::formatCurrencyOutput($item->cost)) }}" maxlength="25" data-msg-pattern="{{ trans('general.purchase_cost_invalid') }}"/>
|
||||
<span class="input-group-addon">
|
||||
@if (($item->asset) && ($item->asset->location) && ($item->asset->location->currency!=''))
|
||||
@if (($item->asset) && ($item->asset->location) && ($item->asset->location->currency != ''))
|
||||
{{ $item->asset->location->currency }}
|
||||
@else
|
||||
{{ $snipeSettings->default_currency }}
|
||||
@endif
|
||||
</span>
|
||||
<input class="form-control" type="text" inputmode="decimal" pattern="[\d.,]+" name="cost" aria-label="cost" id="cost" value="{{ old('cost', \App\Helpers\Helper::formatCurrencyOutput($item->cost)) }}" maxlength="25" data-msg-pattern="{{ trans('general.purchase_cost_invalid') }}"/>
|
||||
</div>
|
||||
<div class="col-md-9" style="padding-left: 0px;">
|
||||
{!! $errors->first('cost', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
<p class="help-block">{{ trans('general.purchase_cost_format_help', ['format' => $snipeSettings->digit_separator]) }}</p>
|
||||
</div>
|
||||
|
||||
@@ -28,23 +28,31 @@
|
||||
@section('moar_scripts')
|
||||
@include ('partials.bootstrap-table', ['exportFile' => 'maintenances-export', 'search' => true])
|
||||
<script nonce="{{ csrf_token() }}">
|
||||
function maintenanceActions(value, row) {
|
||||
function maintenancesActionsFormatter(value, row) {
|
||||
var actions = '<nobr>';
|
||||
if ((row) && (row.available_actions.update === true)) {
|
||||
actions += '<a href="{{ config('app.url') }}/hardware/maintenances/' + row.id + '/edit" class="btn btn-sm btn-warning" data-tooltip="true" title="Update"><i class="fas fa-pencil-alt"></i></a> ';
|
||||
}
|
||||
actions += '</nobr>'
|
||||
if ((row) && (row.available_actions.delete === true)) {
|
||||
actions += '<a href="{{ config('app.url') }}/hardware/maintenances/' + row.id + '" '
|
||||
+ ' class="btn btn-danger btn-sm delete-asset" data-tooltip="true" '
|
||||
+ ' data-toggle="modal" '
|
||||
+ ' data-content="{{ trans('general.sure_to_delete') }} ' + row.name + '?" '
|
||||
+ ' data-title="{{ trans('general.delete') }}" onClick="return false;">'
|
||||
+ '<i class="fas fa-trash"></i></a></nobr>';
|
||||
|
||||
if ((row.available_actions) && (row.available_actions.update === true)) {
|
||||
actions += '<a href="{{ config('app.url') }}/hardware/maintenances/' + row.id + '/edit" class="actions btn btn-sm btn-warning hidden-print" data-tooltip="true" title="{{ trans('general.update') }}"><x-icon type="edit" class="fa-fw" /><span class="sr-only">{{ trans('general.update') }}</span></a> ';
|
||||
}
|
||||
|
||||
if ((row.available_actions) && (row.available_actions.complete === true)) {
|
||||
actions += '<form style="display:inline;" method="POST" action="{{ config('app.url') }}/hardware/maintenances/' + row.id + '/complete">';
|
||||
actions += '{{ csrf_field() }}';
|
||||
actions += '<button type="submit" class="actions btn btn-sm btn-success hidden-print" data-tooltip="true" title="{{ trans('admin/maintenances/form.mark_complete') }}"><x-icon type="checkmark" class="fa-fw" /><span class="sr-only">{{ trans('admin/maintenances/form.mark_complete') }}</span></button> ';
|
||||
actions += '</form>';
|
||||
}
|
||||
|
||||
if ((row.available_actions) && (row.available_actions.delete === true)) {
|
||||
actions += '<a href="{{ config('app.url') }}/hardware/maintenances/' + row.id + '" '
|
||||
+ ' class="actions btn btn-danger btn-sm delete-asset hidden-print" data-tooltip="true" '
|
||||
+ ' data-toggle="modal" data-icon="fa-trash"'
|
||||
+ ' data-content="{{ trans('general.sure_to_delete') }}: ' + row.name + '?" '
|
||||
+ ' data-title="{{ trans('general.delete') }}" onClick="return false;">'
|
||||
+ '<x-icon type="delete" class="fa-fw" /><span class="sr-only">{{ trans('general.delete') }}</span></a> ';
|
||||
}
|
||||
|
||||
actions += '</nobr>';
|
||||
return actions;
|
||||
}
|
||||
|
||||
</script>
|
||||
@stop
|
||||
|
||||
@@ -111,8 +111,36 @@ use Carbon\Carbon;
|
||||
<x-icon type="x" class="text-danger"/>
|
||||
{{ trans('general.no') }}
|
||||
@endif
|
||||
|
||||
</x-data-row>
|
||||
|
||||
@if ($maintenance->responsibleParty)
|
||||
<x-data-row :label="trans('admin/maintenances/form.responsible_party')">
|
||||
{!! $maintenance->responsibleParty->present()->nameUrl() !!}
|
||||
</x-data-row>
|
||||
@endif
|
||||
|
||||
@if ($maintenance->checked_out_to_id)
|
||||
<x-data-row :label="trans('admin/maintenances/form.checked_out_to_at_creation')">
|
||||
{{ $maintenance->checked_out_to_type ? class_basename($maintenance->checked_out_to_type) : '' }}
|
||||
#{{ $maintenance->checked_out_to_id }}
|
||||
|
||||
<p class="help-block">
|
||||
{{ trans('admin/maintenances/form.checked_out_to_at_creation') }}
|
||||
</p>
|
||||
</x-data-row>
|
||||
@endif
|
||||
|
||||
@if ($maintenance->completed_at)
|
||||
<x-data-row :label="trans('admin/maintenances/form.completed_at')">
|
||||
{{ Helper::getFormattedDateObject($maintenance->completed_at, 'datetime', false) }}
|
||||
</x-data-row>
|
||||
@if ($maintenance->completedByUser)
|
||||
<x-data-row :label="trans('admin/maintenances/form.completed_by')">
|
||||
{!! $maintenance->completedByUser->present()->nameUrl() !!}
|
||||
</x-data-row>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
</x-page-data>
|
||||
<!-- ./ definition list content -->
|
||||
<div class="clearfix"></div>
|
||||
@@ -178,6 +206,22 @@ use Carbon\Carbon;
|
||||
|
||||
<x-slot:buttons>
|
||||
<x-button.edit :item="$maintenance" :route="route('maintenances.edit', $maintenance->id)" />
|
||||
@if (! $maintenance->completed_at)
|
||||
@can('update', $maintenance->asset)
|
||||
<form method="POST" action="{{ route('maintenances.complete', $maintenance->id) }}" style="display:inline;">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-success btn-sm" data-tooltip="true" title="{{ trans('admin/maintenances/form.mark_complete') }}">
|
||||
<x-icon type="checkmark" class="fa-fw"/>
|
||||
<span class="sr-only">{{ trans('admin/maintenances/form.mark_complete') }}</span>
|
||||
</button>
|
||||
</form>
|
||||
@endcan
|
||||
@else
|
||||
<span class="btn btn-sm btn-default disabled" data-tooltip="true" title="{{ trans('admin/maintenances/form.already_complete') }}: {{ Helper::getFormattedDateObject($maintenance->completed_at, 'datetime', false) }}">
|
||||
<x-icon type="checkmark" class="fa-fw"/>
|
||||
<span class="sr-only">{{ trans('admin/maintenances/form.already_complete') }}</span>
|
||||
</span>
|
||||
@endif
|
||||
<x-button.delete :item="$maintenance" />
|
||||
</x-slot:buttons>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user