added support for legacy tickets, fixed switching of modes and also style updates

This commit is contained in:
Mark Gregory
2026-09-28 15:21:32 +01:00
parent fd6646c1ee
commit 0fb4223bfc
30 changed files with 162 additions and 186 deletions
@@ -5,31 +5,19 @@ declare(strict_types=1);
namespace Modules\Documentation\Console;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Modules\Documentation\Models\DocumentationCategory;
use Modules\Documentation\Models\DocumentationDocument;
use SplFileInfo;
use Symfony\Component\Finder\Finder;
use Throwable;
final class ImportDocumentationCommand extends Command
{
/**
* The console command signature.
*/
protected $signature = 'helpdesk:import-documentation
{path? : Directory containing Markdown files; defaults to the bundled Sentinel documentation}
@@ -39,21 +27,14 @@ final class ImportDocumentationCommand extends Command
{--fresh : Remove previously imported documents in this category before importing}';
/**
* The console command description.
*/
protected $description = 'Import Markdown documentation into the Helpdesk Documentation module.';
/**
* Execute the console command.
*/
public function handle(): int
{
$path = $this->resolvePath();
@@ -164,7 +145,7 @@ final class ImportDocumentationCommand extends Command
$this->importFile($category, $file, $path);
++$imported;
$imported++;
$progress->advance();
@@ -198,7 +179,7 @@ final class ImportDocumentationCommand extends Command
$this->components->error(
'Documentation import failed: ' . $exception->getMessage(),
'Documentation import failed: '.$exception->getMessage(),
);
@@ -217,13 +198,9 @@ final class ImportDocumentationCommand extends Command
}
/**
* Resolve the requested documentation source directory.
*/
private function resolvePath(): string
{
$argument = $this->argument('path');
@@ -247,17 +224,13 @@ final class ImportDocumentationCommand extends Command
}
/**
* Find Markdown files recursively.
*
* @return list<SplFileInfo>
*/
private function markdownFiles(string $path): array
{
$finder = Finder::create()
@@ -273,7 +246,6 @@ final class ImportDocumentationCommand extends Command
->sortByName();
/** @var list<SplFileInfo> $files */
$files = iterator_to_array($finder, false);
return $files;
@@ -281,11 +253,8 @@ final class ImportDocumentationCommand extends Command
}
/**
* Import one Markdown document.
*/
private function importFile(
DocumentationCategory $category,
@@ -301,7 +270,6 @@ final class ImportDocumentationCommand extends Command
if ($realPath === false || ! is_readable($realPath)) {
throw new \RuntimeException(
sprintf('Unable to read documentation file: %s', $file->getPathname()),
);
@@ -313,7 +281,6 @@ final class ImportDocumentationCommand extends Command
if ($body === false) {
throw new \RuntimeException(
sprintf('Unable to read documentation file: %s', $realPath),
);
@@ -360,7 +327,7 @@ final class ImportDocumentationCommand extends Command
'status' => DocumentationDocument::STATUS_PUBLISHED,
'is_featured' => strtolower($file->getBasename('.' . $file->getExtension())) === 'index',
'is_featured' => strtolower($file->getBasename('.'.$file->getExtension())) === 'index',
'version' => '1.0.0',
@@ -377,13 +344,9 @@ final class ImportDocumentationCommand extends Command
}
/**
* Extract the first Markdown H1 heading.
*/
private function extractTitle(string $body, SplFileInfo $file): string
{
if (preg_match('/^\s*#\s+(.+?)\s*$/m', $body, $matches) === 1) {
@@ -417,13 +380,9 @@ final class ImportDocumentationCommand extends Command
}
/**
* Extract a useful summary from the first normal Markdown paragraph.
*/
private function extractSummary(string $body): ?string
{
$lines = preg_split('/\R/', $body);
@@ -507,13 +466,9 @@ final class ImportDocumentationCommand extends Command
}
/**
* Generate a stable globally unique slug from the source path.
*/
private function makeSlug(string $relativePath, string $title): string
{
$withoutExtension = preg_replace(
@@ -536,7 +491,7 @@ final class ImportDocumentationCommand extends Command
if ($slug === '') {
$slug = 'document-' . substr(sha1($relativePath), 0, 12);
$slug = 'document-'.substr(sha1($relativePath), 0, 12);
}
@@ -545,13 +500,9 @@ final class ImportDocumentationCommand extends Command
}
/**
* Remove a UTF-8 byte-order mark.
*/
private function stripBom(string $contents): string
{
if (str_starts_with($contents, "\xEF\xBB\xBF")) {
@@ -563,6 +514,4 @@ final class ImportDocumentationCommand extends Command
return $contents;
}
}
@@ -31,7 +31,7 @@ class DocumentationController extends Controller
}
if ($request->filled('search')) {
$search = '%' . $request->string('search')->trim()->toString() . '%';
$search = '%'.$request->string('search')->trim()->toString().'%';
$query->where(function ($builder) use ($search): void {
$builder->where('title', 'like', $search)
->orWhere('summary', 'like', $search)
@@ -33,9 +33,9 @@ class StoreDocumentationDocumentRequest extends FormRequest
'is_featured' => ['nullable', 'boolean'],
'version' => ['required', 'string', 'max:50'],
'reference' => ['nullable', 'string', 'max:100'],
'attachment' => ['nullable', 'file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
'attachment' => ['nullable', 'file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
'attachments' => ['nullable', 'array'],
'attachments.*' => ['file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
'attachments.*' => ['file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
];
}
}
@@ -36,9 +36,9 @@ class UpdateDocumentationDocumentRequest extends FormRequest
'is_featured' => ['nullable', 'boolean'],
'version' => ['required', 'string', 'max:50'],
'reference' => ['nullable', 'string', 'max:100'],
'attachment' => ['nullable', 'file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
'attachment' => ['nullable', 'file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
'attachments' => ['nullable', 'array'],
'attachments.*' => ['file', 'max:' . config('documentation.max_upload_kb', 20480), 'mimes:' . implode(',', config('documentation.allowed_upload_mimes', []))],
'attachments.*' => ['file', 'max:'.config('documentation.max_upload_kb', 20480), 'mimes:'.implode(',', config('documentation.allowed_upload_mimes', []))],
'remove_attachment' => ['nullable', 'boolean'],
];
}
@@ -7,13 +7,13 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* @property int $id
* @property int $documentation_document_id
* @property string $disk
* @property string $path
* @property string $original_name
* @property int $id
* @property int $documentation_document_id
* @property string $disk
* @property string $path
* @property string $original_name
* @property string|null $mime_type
* @property int|null $size
* @property int|null $size
*/
class DocumentationAttachment extends Model
{
@@ -57,13 +57,13 @@ class DocumentationAttachment extends Model
}
if ($bytes < 1024) {
return $bytes . ' B';
return $bytes.' B';
}
if ($bytes < 1048576) {
return number_format($bytes / 1024, 1) . ' KB';
return number_format($bytes / 1024, 1).' KB';
}
return number_format($bytes / 1048576, 1) . ' MB';
return number_format($bytes / 1048576, 1).' MB';
}
}
@@ -9,14 +9,14 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
/**
* @property int $id
* @property string $name
* @property string $slug
* @property int $id
* @property string $name
* @property string $slug
* @property string|null $icon
* @property string $colour
* @property string $colour
* @property string|null $description
* @property int $sort_order
* @property bool $is_active
* @property int $sort_order
* @property bool $is_active
*/
class DocumentationCategory extends Model
{
@@ -66,8 +66,7 @@ class DocumentationCategory extends Model
/**
* Active category scope.
*
* @param Builder<DocumentationCategory> $query
*
* @param Builder<DocumentationCategory> $query
* @return Builder<DocumentationCategory>
*/
public function scopeActive(Builder $query): Builder
@@ -78,8 +77,7 @@ class DocumentationCategory extends Model
/**
* Ordered category scope.
*
* @param Builder<DocumentationCategory> $query
*
* @param Builder<DocumentationCategory> $query
* @return Builder<DocumentationCategory>
*/
public function scopeOrdered(Builder $query): Builder
@@ -11,15 +11,15 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
/**
* @property int $id
* @property int|null $documentation_category_id
* @property string $title
* @property string $slug
* @property int $id
* @property int|null $documentation_category_id
* @property string $title
* @property string $slug
* @property string|null $summary
* @property string|null $body
* @property string $status
* @property bool $is_featured
* @property string $version
* @property string $status
* @property bool $is_featured
* @property string $version
* @property string|null $reference
* @property-read string $rendered_body
*/
@@ -101,8 +101,7 @@ class DocumentationDocument extends Model
/**
* Published document scope.
*
* @param Builder<DocumentationDocument> $query
*
* @param Builder<DocumentationDocument> $query
* @return Builder<DocumentationDocument>
*/
public function scopePublished(Builder $query): Builder
@@ -113,8 +112,7 @@ class DocumentationDocument extends Model
/**
* Featured document scope.
*
* @param Builder<DocumentationDocument> $query
*
* @param Builder<DocumentationDocument> $query
* @return Builder<DocumentationDocument>
*/
public function scopeFeatured(Builder $query): Builder
@@ -140,7 +138,7 @@ class DocumentationDocument extends Model
]);
}
return '<p>' . nl2br(e($body), false) . '</p>';
return '<p>'.nl2br(e($body), false).'</p>';
}
/**
@@ -7,6 +7,7 @@ namespace Modules\Documentation\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\ServiceProvider;
use Modules\Documentation\Console\ImportDocumentationCommand;
final class DocumentationServiceProvider extends ServiceProvider
{
@@ -43,7 +44,7 @@ final class DocumentationServiceProvider extends ServiceProvider
}
$this->commands([
\Modules\Documentation\Console\ImportDocumentationCommand::class,
ImportDocumentationCommand::class,
]);
}
@@ -62,12 +63,12 @@ final class DocumentationServiceProvider extends ServiceProvider
$paths = [$sourcePath];
foreach (Config::get('view.paths', []) as $path) {
if (is_dir($path . '/modules/documentation')) {
array_unshift($paths, $path . '/modules/documentation');
if (is_dir($path.'/modules/documentation')) {
array_unshift($paths, $path.'/modules/documentation');
}
}
$this->loadViewsFrom($paths, 'documentation');
Blade::anonymousComponentPath($sourcePath . '/components', 'documentation');
Blade::anonymousComponentPath($sourcePath.'/components', 'documentation');
}
}
@@ -7,7 +7,6 @@ namespace Modules\Documentation\Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Modules\Documentation\Models\DocumentationAttachment;
use Modules\Documentation\Models\DocumentationDocument;
use Tests\TestCase;
@@ -17,8 +17,7 @@ class DocumentationModuleTest extends TestCase
/**
* Add a CSRF token for projects that keep web middleware enabled during tests.
*
* @param array<string, mixed> $payload
*
* @param array<string, mixed> $payload
* @return array<string, mixed>
*/
private function csrfPayload(array $payload): array
@@ -16,6 +16,7 @@ use Throwable;
final class ImportLegacyHelpdeskCommand extends Command
{
protected $signature = 'helpdesk:import-legacy {--connection= : Laravel database connection containing the old tickets tables} {--fresh : Clear previously imported legacy records first}';
protected $description = 'Import the old Helpdesk tickets and categories into the read-only Legacy System';
public function handle(): int
@@ -33,6 +34,7 @@ final class ImportLegacyHelpdeskCommand extends Command
foreach (['tickets', 'tickets_categories'] as $table) {
if (! $schema->hasTable($table)) {
$this->error("Source table {$table} was not found on connection [{$connectionName}].");
return self::FAILURE;
}
}
@@ -49,6 +51,7 @@ final class ImportLegacyHelpdeskCommand extends Command
$this->refreshCategoryCounts();
$this->info(sprintf('Legacy import complete: %d tickets, %d categories, %d comments.', LegacyTicket::count(), LegacyCategory::count(), LegacyComment::count()));
return self::SUCCESS;
}
@@ -72,7 +75,7 @@ final class ImportLegacyHelpdeskCommand extends Command
'user' => $this->lookup($source, $schema, 'users'),
];
$source->table('tickets')->orderBy('id')->chunk(250, function ($rows) use ($columns, $lookups): void {
$source->table('tickets')->orderBy('id')->chunk(250, function ($rows) use ($lookups): void {
foreach ($rows as $row) {
$data = (array) $row;
LegacyTicket::updateOrCreate(['legacy_id' => $row->id], [
@@ -99,7 +102,9 @@ final class ImportLegacyHelpdeskCommand extends Command
private function importComments(ConnectionInterface $source, $schema): void
{
if (! $schema->hasTable('tickets_comments')) return;
if (! $schema->hasTable('tickets_comments')) {
return;
}
$users = $this->lookup($source, $schema, 'users');
$source->table('tickets_comments')->orderBy('id')->chunk(500, function ($rows) use ($users): void {
foreach ($rows as $row) {
@@ -118,11 +123,19 @@ final class ImportLegacyHelpdeskCommand extends Command
private function lookup(ConnectionInterface $source, $schema, string $table): array
{
if (! $schema->hasTable($table)) return [];
if (! $schema->hasTable($table)) {
return [];
}
$columns = $schema->getColumnListing($table);
$nameColumn = in_array('name', $columns, true) ? 'name' : (in_array('username', $columns, true) ? 'username' : null);
if ($nameColumn === null) return [];
try { return $source->table($table)->pluck($nameColumn, 'id')->map(fn ($v) => (string) $v)->all(); } catch (Throwable) { return []; }
if ($nameColumn === null) {
return [];
}
try {
return $source->table($table)->pluck($nameColumn, 'id')->map(fn ($v) => (string) $v)->all();
} catch (Throwable) {
return [];
}
}
private function refreshCategoryCounts(): void
@@ -6,7 +6,8 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
return new class extends Migration
{
public function up(): void
{
Schema::create('helpdesk_legacy_categories', function (Blueprint $table): void {
@@ -39,6 +39,7 @@ final class LegacySystemController
public function show(LegacyTicket $ticket): View
{
$ticket->load('comments');
return view('helpdesk::legacy.show', compact('ticket'));
}
@@ -26,8 +26,11 @@ final class ArchivedTicketIndex extends Component
public string $search = '';
public bool $deleteModalOpen = false;
public ?int $pendingDeleteTicketId = null;
public ?string $pendingDeleteTicketReference = null;
public ?string $pendingDeleteTicketSubject = null;
public function updatedSearch(): void
@@ -75,6 +78,7 @@ final class ArchivedTicketIndex extends Component
{
if ($this->pendingDeleteTicketId === null) {
$this->resetDeleteState();
return;
}
@@ -17,7 +17,9 @@ final class HelpdeskDashboardWidget extends Component
public function updatedDays(): void
{
if (! in_array($this->days, [7, 14, 30], true)) $this->days = 7;
if (! in_array($this->days, [7, 14, 30], true)) {
$this->days = 7;
}
}
public function render(): View
@@ -33,6 +35,7 @@ final class HelpdeskDashboardWidget extends Component
$trendRows = (clone $base)->where('created_at', '>=', now()->subDays($this->days - 1)->startOfDay())->get(['created_at', 'completed_at']);
$trend = collect($period)->map(function ($date) use ($trendRows): array {
$day = $date->toDateString();
return [
'label' => $date->format('M j'),
'created' => $trendRows->filter(fn ($ticket) => optional($ticket->created_at)->toDateString() === $day)->count(),
+63 -51
View File
@@ -39,17 +39,29 @@ final class SettingsManager extends Component
public bool $teamModalOpen = false;
public bool $statusModalOpen = false;
public bool $priorityModalOpen = false;
public bool $categoryModalOpen = false;
public bool $projectModalOpen = false;
public bool $boardModalOpen = false;
public bool $repositoryModalOpen = false;
public bool $workflowModalOpen = false;
public bool $cannedModalOpen = false;
public bool $slaModalOpen = false;
public bool $automationModalOpen = false;
public bool $checklistModalOpen = false;
public bool $tagModalOpen = false;
public bool $productModalOpen = false;
/** @var array<string, mixed> */
@@ -1041,57 +1053,57 @@ final class SettingsManager extends Component
return view()->file(
resource_path('themes/backend/views/modules/helpdesk/livewire/settings-manager.blade.php'),
[
'statuses' => $this->orderedStatuses(),
'priorities' => $this->orderedPriorities(),
'categories' => $this->orderedCategories(),
'teams' => $this->orderedTeams(),
'teamUsers' => User::query()
->orderBy('name')
->get(['id', 'name', 'email', 'helpdesk_agent', 'helpdesk_admin']),
'projects' => $this->orderedProjects(),
'boardOwners' => User::query()->where(static function ($query): void {
$query->where('helpdesk_agent', true)->orWhere('helpdesk_admin', true);
})->orderBy('name')->get(['id', 'name', 'email']),
'boards' => KanbanBoard::query()
->with(['statuses', 'owner:id,name,email'])
->withCount('tickets')
->orderBy('sort_order')
->orderBy('name')
->paginate(10, ['*'], 'boardsPage'),
'repositories' => GitRepository::query()
->with(['project'])
->withCount(['commits', 'webhookLogs'])
->orderBy('name')
->paginate(10, ['*'], 'gitPage'),
'workflowTemplates' => WorkflowTemplate::query()
->orderBy('event')
->orderBy('name')
->paginate(10, ['*'], 'workflowPage'),
'cannedResponses' => CannedResponse::query()
->with(['category', 'team'])
->orderBy('sort_order')
->orderBy('name')
->paginate(10, ['*'], 'cannedPage'),
'slaPolicies' => SlaPolicy::query()
->with(['priority', 'category'])
->orderByDesc('is_default')
->orderBy('name')
->paginate(10, ['*'], 'slaPage'),
'automationRules' => AutomationRule::query()
->orderBy('sort_order')
->orderBy('name')
->paginate(10, ['*'], 'rulesPage'),
'products' => Product::query()
->withCount('tickets')
->orderBy('name')
->paginate(10, ['*'], 'productsPage'),
'tags' => Tag::query()
->orderBy('name')
->paginate(10, ['*'], 'tagsPage'),
'checklistTemplates' => ChecklistTemplate::query()
->orderBy('name')
->paginate(10, ['*'], 'checksPage'),
'colourOptions' => Color::options(),
'statuses' => $this->orderedStatuses(),
'priorities' => $this->orderedPriorities(),
'categories' => $this->orderedCategories(),
'teams' => $this->orderedTeams(),
'teamUsers' => User::query()
->orderBy('name')
->get(['id', 'name', 'email', 'helpdesk_agent', 'helpdesk_admin']),
'projects' => $this->orderedProjects(),
'boardOwners' => User::query()->where(static function ($query): void {
$query->where('helpdesk_agent', true)->orWhere('helpdesk_admin', true);
})->orderBy('name')->get(['id', 'name', 'email']),
'boards' => KanbanBoard::query()
->with(['statuses', 'owner:id,name,email'])
->withCount('tickets')
->orderBy('sort_order')
->orderBy('name')
->paginate(10, ['*'], 'boardsPage'),
'repositories' => GitRepository::query()
->with(['project'])
->withCount(['commits', 'webhookLogs'])
->orderBy('name')
->paginate(10, ['*'], 'gitPage'),
'workflowTemplates' => WorkflowTemplate::query()
->orderBy('event')
->orderBy('name')
->paginate(10, ['*'], 'workflowPage'),
'cannedResponses' => CannedResponse::query()
->with(['category', 'team'])
->orderBy('sort_order')
->orderBy('name')
->paginate(10, ['*'], 'cannedPage'),
'slaPolicies' => SlaPolicy::query()
->with(['priority', 'category'])
->orderByDesc('is_default')
->orderBy('name')
->paginate(10, ['*'], 'slaPage'),
'automationRules' => AutomationRule::query()
->orderBy('sort_order')
->orderBy('name')
->paginate(10, ['*'], 'rulesPage'),
'products' => Product::query()
->withCount('tickets')
->orderBy('name')
->paginate(10, ['*'], 'productsPage'),
'tags' => Tag::query()
->orderBy('name')
->paginate(10, ['*'], 'tagsPage'),
'checklistTemplates' => ChecklistTemplate::query()
->orderBy('name')
->paginate(10, ['*'], 'checksPage'),
'colourOptions' => Color::options(),
]
);
}
@@ -9,5 +9,6 @@ use Illuminate\Database\Eloquent\Model;
final class LegacyCategory extends Model
{
protected $table = 'helpdesk_legacy_categories';
protected $guarded = [];
}
@@ -9,6 +9,8 @@ use Illuminate\Database\Eloquent\Model;
final class LegacyComment extends Model
{
protected $table = 'helpdesk_legacy_comments';
protected $guarded = [];
protected $casts = ['legacy_created_at' => 'datetime', 'legacy_updated_at' => 'datetime'];
}
+2
View File
@@ -10,7 +10,9 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
final class LegacyTicket extends Model
{
protected $table = 'helpdesk_legacy_tickets';
protected $guarded = [];
protected $casts = ['legacy_data' => 'array', 'legacy_created_at' => 'datetime', 'legacy_updated_at' => 'datetime', 'completed_at' => 'datetime', 'archived_at' => 'datetime'];
public function comments(): HasMany
-1
View File
@@ -5,7 +5,6 @@ declare(strict_types=1);
namespace Modules\Helpdesk\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
-1
View File
@@ -62,7 +62,6 @@ final class Ticket extends Model
return $this->belongsTo(User::class, 'user_id');
}
/**
* Compatibility alias for the requester.
*
@@ -11,7 +11,6 @@ use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use RuntimeException;
use Throwable;
final class HelpdeskSyncService
{
@@ -262,7 +261,7 @@ final class HelpdeskSyncService
}
/**
* @param list<string> $tables
* @param list<string> $tables
* @return list<string>
*/
private function existingTables(array $tables): array
@@ -293,7 +292,7 @@ final class HelpdeskSyncService
}
/**
* @param array<string, list<array<string, mixed>>> $tables
* @param array<string, list<array<string, mixed>>> $tables
* @return list<array<string, mixed>>
*/
private function exportUsers(array $tables): array
@@ -357,7 +356,7 @@ final class HelpdeskSyncService
}
/**
* @param list<array<string, mixed>> $users
* @param list<array<string, mixed>> $users
* @return array<int, int>
*/
private function importUsers(array $users): array
@@ -436,8 +435,8 @@ final class HelpdeskSyncService
}
/**
* @param list<array<string, mixed>> $rows
* @param array<int, int> $userMap
* @param list<array<string, mixed>> $rows
* @param array<int, int> $userMap
*/
private function importTable(string $table, array $rows, array $userMap, bool $mirror): void
{
@@ -481,8 +480,8 @@ final class HelpdeskSyncService
}
/**
* @param array<string, mixed> $row
* @param array<int, int> $userMap
* @param array<string, mixed> $row
* @param array<int, int> $userMap
* @return array<string, mixed>
*/
private function remapUserColumns(array $row, array $userMap): array
@@ -503,7 +502,7 @@ final class HelpdeskSyncService
}
/**
* @param array<string, mixed> $row
* @param array<string, mixed> $row
* @return array<string, mixed>
*/
private function compositeKey(string $table, array $row): array
@@ -533,7 +532,7 @@ final class HelpdeskSyncService
}
/**
* @param list<array<string, mixed>> $attachments
* @param list<array<string, mixed>> $attachments
* @return list<array<string, mixed>>
*/
private function exportAttachmentFiles(array $attachments): array
@@ -569,7 +568,7 @@ final class HelpdeskSyncService
}
/**
* @param list<array<string, mixed>> $files
* @param list<array<string, mixed>> $files
*/
private function importAttachmentFiles(array $files): int
{
@@ -120,7 +120,7 @@ final class UserController extends Controller
public function createRole(): View
{
return view('modules.user-management.role-form', [
'role' => new Role(),
'role' => new Role,
'permissions' => Permission::query()->orderBy('name')->get(),
]);
}
@@ -165,7 +165,7 @@ final class UserController extends Controller
public function createPermission(): View
{
return view('modules.user-management.permission-form', ['permission' => new Permission()]);
return view('modules.user-management.permission-form', ['permission' => new Permission]);
}
public function storePermission(Request $request): RedirectResponse
-1
View File
@@ -18,5 +18,4 @@ class Appearance extends Component
resource_path('themes/backend/views/livewire/settings/appearance.blade.php')
);
}
}
+2 -2
View File
@@ -2,9 +2,9 @@
namespace App\Livewire\Settings;
use Illuminate\Contracts\View\View;
use App\Concerns\PasswordValidationRules;
use App\Livewire\Actions\Logout;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
@@ -27,11 +27,11 @@ class DeleteUserForm extends Component
$this->redirect('/', navigate: true);
}
public function render(): View
{
return view()->file(
resource_path('themes/backend/views/livewire/settings/delete-user-form.blade.php')
);
}
}
+3 -3
View File
@@ -2,13 +2,13 @@
namespace App\Livewire\Settings;
use Illuminate\Contracts\View\View;
use App\Concerns\ProfileValidationRules;
use Flux\Flux;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Title;
use Livewire\Component;
@@ -83,6 +83,7 @@ class Profile extends Component
return ! $user instanceof MustVerifyEmail || $user->hasVerifiedEmail();
}
#[Layout('layouts.app')]
public function render(): View
{
@@ -90,5 +91,4 @@ class Profile extends Component
resource_path('themes/backend/views/livewire/settings/profile.blade.php')
);
}
}
+3 -3
View File
@@ -2,10 +2,10 @@
namespace App\Livewire\Settings;
use Illuminate\Contracts\View\View;
use App\Concerns\PasswordValidationRules;
use Exception;
use Flux\Flux;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\ValidationException;
use Laravel\Fortify\Actions\ConfirmTwoFactorAuthentication;
@@ -14,8 +14,8 @@ use Laravel\Fortify\Actions\EnableTwoFactorAuthentication;
use Laravel\Fortify\Features;
use Laravel\Fortify\Fortify;
use Laravel\Passkeys\Actions\DeletePasskey;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Title;
use Livewire\Attributes\Validate;
@@ -311,6 +311,7 @@ class Security extends Component
'buttonText' => __('Continue'),
];
}
#[Layout('layouts.app')]
public function render(): View
{
@@ -318,5 +319,4 @@ class Security extends Component
resource_path('themes/backend/views/livewire/settings/security.blade.php')
);
}
}
@@ -2,8 +2,8 @@
namespace App\Livewire\Settings\TwoFactor;
use Illuminate\Contracts\View\View;
use Exception;
use Illuminate\Contracts\View\View;
use Laravel\Fortify\Actions\GenerateNewRecoveryCodes;
use Livewire\Attributes\Locked;
use Livewire\Component;
@@ -49,11 +49,11 @@ class RecoveryCodes extends Component
}
}
}
public function render(): View
{
return view()->file(
resource_path('themes/backend/views/livewire/settings/two-factor/recovery-codes.blade.php')
);
}
}
+1 -3
View File
@@ -6,6 +6,7 @@ use Database\Factories\UserFactory;
use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Carbon;
@@ -14,7 +15,6 @@ use Laravel\Fortify\Contracts\PasskeyUser;
use Laravel\Fortify\PasskeyAuthenticatable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Modules\UserManagement\Models\Role;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* @property int $id
@@ -50,8 +50,6 @@ class User extends Authenticatable implements PasskeyUser
: $initials;
}
public function gravatarUrl(int $size = 160): string
{
$email = strtolower(trim((string) $this->email));
-1
View File
@@ -34,7 +34,6 @@ host('mpba')
->set('branch', 'main')
->set('deploy_path', '/var/www/helpdesk_mpba');
/*
* Install the root npm tree, then every module that owns its own lock file,
* then run ONE root Vite build. Because Vite is compiling a module source file,