Move SealShare onto Livewire Material

Replaces maryUI and daisyUI with nonameweb/livewire-material: the Vibrant
indigo scheme, a system/light/dark theme under sealshare-theme, one top
app bar with the account menu, the upload drop zone and link-ready
moments, M3 fields, dialogs instead of wire:confirm, snackbars instead of
flashed messages, a sortable admin table, and the starter-kit cleanup.
Docker builds assets after Composer; CI drops the Flux step.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
This commit is contained in:
Andreas Reinhold / reini
2026-09-13 10:49:38 +02:00
co-authored by Claude Opus 5
parent 6d7120e8e2
commit c4a17b65c8
70 changed files with 3043 additions and 1680 deletions
+19 -1
View File
@@ -54,7 +54,9 @@ test('admin can delete share', function () {
Livewire::actingAs($admin)
->test(AdminDashboard::class)
->call('deleteShare', $shareId);
->set('deletingShareId', $shareId)
->call('deleteShare', $shareId)
->assertSet('deletingShareId', null);
expect(Share::query()->find($shareId))->toBeNull();
});
@@ -69,3 +71,19 @@ test('admin dashboard shows shares table', function () {
$response->assertOk();
$response->assertSee('testtoken12345678');
});
test('the shares table sorts only by its own columns', function () {
$admin = User::query()->where('is_admin', true)->first();
Share::factory()->create(['token' => 'aaaaaaaaaaaaaaaa', 'download_count' => 9]);
Share::factory()->create(['token' => 'zzzzzzzzzzzzzzzz', 'download_count' => 1]);
Livewire::actingAs($admin)
->test(AdminDashboard::class)
->set('sortBy', ['column' => 'download_count', 'direction' => 'asc'])
->assertSeeInOrder(['zzzzzzzzzzzzzzzz', 'aaaaaaaaaaaaaaaa'])
->set('sortBy', ['column' => 'token; drop table shares', 'direction' => 'sideways'])
->assertOk();
expect(Share::query()->count())->toBe(2);
});
+27 -2
View File
@@ -3,7 +3,9 @@
use App\Livewire\Admin\AdminSettings;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
test('admin settings requires authentication', function () {
@@ -41,7 +43,8 @@ test('admin can save settings', function () {
->set('maxSizePerShare', 5)
->set('defaultExpiration', '7d')
->call('saveSettings')
->assertHasNoErrors();
->assertHasNoErrors()
->assertDispatched('toast', type: 'success', title: 'Settings saved successfully.');
expect(Setting::get('max_file_size'))->toBe((string) (min(200, $phpMaxMb) * 1024 * 1024));
expect(Setting::get('max_storage_quota'))->toBe((string) (50 * 1024 * 1024 * 1024));
@@ -73,8 +76,11 @@ test('admin can clear system password', function () {
Livewire::actingAs($admin)
->test(AdminSettings::class)
->set('confirmingPasswordRemoval', true)
->call('clearSystemPassword')
->assertHasNoErrors();
->assertHasNoErrors()
->assertSet('confirmingPasswordRemoval', false)
->assertDispatched('toast', type: 'success', title: 'System password cleared.');
expect(Setting::get('system_password'))->toBeNull();
});
@@ -103,3 +109,22 @@ test('settings validation rejects invalid values', function () {
->call('saveSettings')
->assertHasErrors(['maxFileSize', 'maxStorageQuota']);
});
test('admin can remove the logo through its dialog', function () {
Storage::fake('public');
$admin = User::query()->where('is_admin', true)->first();
$path = UploadedFile::fake()->image('logo.png')->store('branding', 'public');
Setting::set('site_logo', $path);
Livewire::actingAs($admin)
->test(AdminSettings::class)
->assertSeeHtml('data-test="remove-logo"')
->set('confirmingLogoRemoval', true)
->call('removeLogo')
->assertSet('confirmingLogoRemoval', false)
->assertDispatched('toast', type: 'success', title: 'Logo removed.');
expect(Setting::get('site_logo'))->toBeNull();
Storage::disk('public')->assertMissing($path);
});