new admin design with mnodules
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Administration\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Modules\Audit\Models\AuditLog;
|
||||
use Modules\Media\Models\Media;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
final class DashboardController extends Controller
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
return view('administration::dashboard', [
|
||||
'userCount' => User::count(),
|
||||
'roleCount' => Schema::hasTable('roles') ? Role::count() : 0,
|
||||
'mediaCount' => Schema::hasTable('media') ? Media::count() : 0,
|
||||
'auditCount' => Schema::hasTable('audit_logs') ? AuditLog::count() : 0,
|
||||
'recentAudit' => Schema::hasTable('audit_logs') ? AuditLog::query()->latest('created_at')->limit(8)->get() : collect(),
|
||||
'modules' => $this->modules(),
|
||||
]);
|
||||
}
|
||||
|
||||
private function modules(): array
|
||||
{
|
||||
$statuses = json_decode((string) file_get_contents(base_path('modules_statuses.json')), true) ?: [];
|
||||
$modules = [];
|
||||
foreach (glob(base_path('Modules/*/module.json')) ?: [] as $manifest) {
|
||||
$data = json_decode((string) file_get_contents($manifest), true) ?: [];
|
||||
$name = $data['name'] ?? basename(dirname($manifest));
|
||||
$modules[] = ['name' => $name, 'version' => $data['version'] ?? '1.0.0', 'enabled' => (bool) ($statuses[$name] ?? false)];
|
||||
}
|
||||
usort($modules, fn ($a, $b) => strcasecmp($a['name'], $b['name']));
|
||||
return $modules;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Administration\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
final class ModuleController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$statuses = json_decode((string) file_get_contents(base_path('modules_statuses.json')), true) ?: [];
|
||||
$modules = collect(glob(base_path('Modules/*/module.json')) ?: [])->map(function (string $manifest) use ($statuses): array {
|
||||
$data = json_decode((string) file_get_contents($manifest), true) ?: [];
|
||||
$name = $data['name'] ?? basename(dirname($manifest));
|
||||
return [
|
||||
'name' => $name,
|
||||
'description' => $data['description'] ?? 'Laravel application module.',
|
||||
'version' => $data['version'] ?? '1.0.0',
|
||||
'enabled' => (bool) ($statuses[$name] ?? false),
|
||||
'providers' => $data['providers'] ?? [],
|
||||
];
|
||||
})->sortBy('name', SORT_NATURAL | SORT_FLAG_CASE)->values();
|
||||
|
||||
return view('administration::modules.index', compact('modules'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<x-layouts.app :title="__('Administration')">
|
||||
<div class="space-y-6">
|
||||
<div><h1 class="text-2xl font-semibold text-zinc-950 dark:text-zinc-100">Administration</h1><p class="mt-1 text-sm text-zinc-600 dark:text-zinc-400">Platform health and recent activity.</p></div>
|
||||
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
||||
@foreach([['Users',$userCount,'users'],['Roles',$roleCount,'shield-check'],['Media',$mediaCount,'photo'],['Audit events',$auditCount,'clipboard-document-list']] as [$label,$count,$icon])
|
||||
<div class="rounded-xl border border-zinc-200 bg-white p-5 shadow-sm dark:border-zinc-700 dark:bg-zinc-900"><flux:icon :name="$icon" class="size-5 text-zinc-500"/><div class="mt-4 text-3xl font-semibold">{{ $count }}</div><div class="text-sm text-zinc-500">{{ $label }}</div></div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="grid gap-6 xl:grid-cols-2">
|
||||
<div class="rounded-xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900"><div class="border-b border-zinc-200 px-5 py-4 font-semibold dark:border-zinc-700">Modules</div><div class="divide-y divide-zinc-200 dark:divide-zinc-800">@foreach($modules as $module)<div class="flex items-center justify-between px-5 py-3"><div><div class="font-medium">{{ $module['name'] }}</div><div class="text-xs text-zinc-500">v{{ $module['version'] }}</div></div><span class="rounded-full px-2.5 py-1 text-xs {{ $module['enabled'] ? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-950 dark:text-emerald-200' : 'bg-zinc-100 text-zinc-600 dark:bg-zinc-800 dark:text-zinc-300' }}">{{ $module['enabled'] ? 'Enabled' : 'Disabled' }}</span></div>@endforeach</div></div>
|
||||
<div class="rounded-xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-700 dark:bg-zinc-900"><div class="border-b border-zinc-200 px-5 py-4 font-semibold dark:border-zinc-700">Recent audit activity</div><div class="divide-y divide-zinc-200 dark:divide-zinc-800">@forelse($recentAudit as $log)<div class="px-5 py-3"><div class="font-medium">{{ $log->event }}</div><div class="text-xs text-zinc-500">{{ optional($log->created_at)->diffForHumans() }}</div></div>@empty<div class="px-5 py-8 text-center text-sm text-zinc-500">No audit events yet.</div>@endforelse</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</x-layouts.app>
|
||||
@@ -0,0 +1 @@
|
||||
<x-layouts.app :title="__('Modules')"><div class="space-y-6"><div><h1 class="text-2xl font-semibold">Modules</h1><p class="mt-1 text-sm text-zinc-500">Installed platform modules and runtime status.</p></div><div class="overflow-hidden rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900"><table class="min-w-full divide-y divide-zinc-200 text-sm dark:divide-zinc-700"><thead class="bg-zinc-50 text-left text-xs uppercase text-zinc-500 dark:bg-zinc-950"><tr><th class="px-4 py-3">Module</th><th class="px-4 py-3">Version</th><th class="px-4 py-3">Status</th><th class="px-4 py-3">Providers</th></tr></thead><tbody class="divide-y divide-zinc-200 dark:divide-zinc-800">@foreach($modules as $module)<tr><td class="px-4 py-3"><div class="font-medium">{{ $module['name'] }}</div><div class="text-xs text-zinc-500">{{ $module['description'] }}</div></td><td class="px-4 py-3">{{ $module['version'] }}</td><td class="px-4 py-3">{{ $module['enabled'] ? 'Enabled' : 'Disabled' }}</td><td class="px-4 py-3 text-xs text-zinc-500">{{ implode(', ', $module['providers']) ?: '—' }}</td></tr>@endforeach</tbody></table></div></div></x-layouts.app>
|
||||
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Modules\Administration\Http\Controllers\DashboardController;
|
||||
use Modules\Administration\Http\Controllers\ModuleController;
|
||||
|
||||
// Module routes are intentionally registered by each feature as it is enabled.
|
||||
Route::middleware(['auth', 'verified'])->prefix('administration')->name('administration.')->group(function (): void {
|
||||
Route::get('/', DashboardController::class)->name('dashboard');
|
||||
Route::get('/modules', [ModuleController::class, 'index'])->name('modules.index');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user