diff --git a/Modules/Documentation/Http/Controllers/DocumentationController.php b/Modules/Documentation/Http/Controllers/DocumentationController.php index 86927fb..c2f88c5 100644 --- a/Modules/Documentation/Http/Controllers/DocumentationController.php +++ b/Modules/Documentation/Http/Controllers/DocumentationController.php @@ -49,11 +49,42 @@ class DocumentationController extends Controller 'published' => DocumentationDocument::query()->published()->count(), 'drafts' => DocumentationDocument::query()->where('status', DocumentationDocument::STATUS_DRAFT)->count(), 'categories' => DocumentationCategory::query()->count(), + 'archived' => DocumentationDocument::onlyTrashed()->count(), ], 'statuses' => config('documentation.statuses', []), ]); } + /** + * Display soft-deleted documents. + */ + public function archived(Request $request): View + { + $query = DocumentationDocument::onlyTrashed() + ->with(['category', 'attachments']) + ->latest('deleted_at'); + + if ($request->filled('category')) { + $query->where('documentation_category_id', $request->integer('category')); + } + + if ($request->filled('search')) { + $search = '%'.$request->string('search')->trim()->toString().'%'; + + $query->where(function ($builder) use ($search): void { + $builder->where('title', 'like', $search) + ->orWhere('summary', 'like', $search) + ->orWhere('reference', 'like', $search) + ->orWhere('body', 'like', $search); + }); + } + + return view('documentation::documents.archived', [ + 'documents' => $query->paginate(15)->withQueryString(), + 'categories' => DocumentationCategory::query()->ordered()->get(), + ]); + } + /** * Show the create document form. */ @@ -146,11 +177,55 @@ class DocumentationController extends Controller } /** - * Remove a document. + * Archive a document using Laravel soft deletes. + * + * Stored files and attachment records are deliberately retained. They are + * only removed when an archived document is permanently deleted. */ - public function destroy(DocumentationDocument $document): RedirectResponse + public function destroy(Request $request, DocumentationDocument $document): RedirectResponse { - $document->load('attachments'); + $document->forceFill([ + 'status' => DocumentationDocument::STATUS_ARCHIVED, + 'updated_by' => $request->user()?->id, + ])->save(); + + $document->delete(); + + return redirect() + ->route('documentation.documents.index') + ->with('status', 'Document archived successfully.'); + } + + /** + * Restore a previously archived document. + */ + public function restore(Request $request, int $document): RedirectResponse + { + $document = DocumentationDocument::onlyTrashed()->findOrFail($document); + + $document->restore(); + + // Restored documents return to Draft so they cannot unexpectedly + // become publicly/operationally published again. + $document->forceFill([ + 'status' => DocumentationDocument::STATUS_DRAFT, + 'updated_by' => $request->user()?->id, + ])->save(); + + return redirect() + ->route('documentation.documents.archived') + ->with('status', 'Document restored as a draft.'); + } + + /** + * Permanently delete an archived document and all stored files. + */ + public function forceDestroy(int $document): RedirectResponse + { + $document = DocumentationDocument::onlyTrashed() + ->with('attachments') + ->findOrFail($document); + $this->deleteAttachment($document); foreach ($document->attachments as $attachment) { @@ -158,9 +233,11 @@ class DocumentationController extends Controller $attachment->delete(); } - $document->delete(); + $document->forceDelete(); - return redirect()->route('documentation.documents.index')->with('status', 'Document archived successfully.'); + return redirect() + ->route('documentation.documents.archived') + ->with('status', 'Document permanently deleted.'); } /** diff --git a/Modules/Documentation/Resources/views/documents/archived.blade.php b/Modules/Documentation/Resources/views/documents/archived.blade.php new file mode 100644 index 0000000..2b8e17f --- /dev/null +++ b/Modules/Documentation/Resources/views/documents/archived.blade.php @@ -0,0 +1,120 @@ +@extends('documentation::layouts.master') + +@section('title', 'Archived Documents') + +@section('content') +
| Document | +Category | +Version | +Archived | +Files | +Actions | +
|---|---|---|---|---|---|
|
+ {{ $document->title }}
+
+ {{ $document->reference ?: 'No reference' }} ยท
+ {{ $document->summary ?: 'No summary' }}
+
+ |
+ {{ $document->category?->name ?: 'Uncategorised' }} | +{{ $document->version }} | +{{ $document->deleted_at?->format('d M Y H:i') }} | ++ {{ ($document->attachment_name ? 1 : 0) + $document->attachments->count() }} + | +
+
+
+
+
+
+ |
+
| No archived documents found. | +|||||