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
123 lines
5.8 KiB
PHP
123 lines
5.8 KiB
PHP
<div class="mx-auto max-w-2xl">
|
|
<h1 class="mb-6 type-headline-md">{{ __('System Settings') }}</h1>
|
|
|
|
<form wire:submit="saveSettings" class="grid gap-6">
|
|
<x-card :title="__('Branding')" variant="outlined">
|
|
<div class="grid gap-5">
|
|
<x-input wire:model="siteTitle" :label="__('Site Title')" :hint="__('Displayed as the heading on the upload page.')" />
|
|
|
|
<x-textarea wire:model="siteDescription" :label="__('Site Description')" :hint="__('Displayed below the title on the upload page.')" rows="3" />
|
|
|
|
<div class="grid gap-3">
|
|
@if ($currentLogo)
|
|
<div class="flex flex-wrap items-center gap-4">
|
|
<img src="{{ Storage::disk('public')->url($currentLogo) }}" alt="{{ __('Site Logo') }}" class="h-16 w-auto rounded-corner-sm" />
|
|
<x-button :label="__('Remove Logo')" icon="delete" color="error" wire:click="$set('confirmingLogoRemoval', true)" data-test="remove-logo" />
|
|
</div>
|
|
@endif
|
|
|
|
<x-file wire:model="siteLogo" :label="__('Logo')" accept="image/*,.svg,.svgz" :hint="__('Max 2MB. Recommended: PNG or SVG.')" />
|
|
|
|
@if ($siteLogo && is_object($siteLogo))
|
|
@if (str_contains($siteLogo->getMimeType(), 'svg'))
|
|
<p class="type-body-md text-on-surface-variant">{{ __('SVG selected: :name', ['name' => $siteLogo->getClientOriginalName()]) }}</p>
|
|
@else
|
|
<div>
|
|
<p class="type-label-lg text-on-surface-variant">{{ __('Preview:') }}</p>
|
|
<img src="{{ $siteLogo->temporaryUrl() }}" alt="{{ __('Logo preview') }}" class="mt-1 h-16 w-auto rounded-corner-sm" />
|
|
</div>
|
|
@endif
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</x-card>
|
|
|
|
<x-card :title="__('Upload Protection')" variant="outlined">
|
|
<div class="grid gap-3">
|
|
<x-password
|
|
wire:model="systemPassword"
|
|
:label="__('System Upload Password')"
|
|
:hint="__('Leave blank to keep current. Set a password to require it before uploading.')"
|
|
autocomplete="new-password"
|
|
/>
|
|
|
|
@if ($hasSystemPassword)
|
|
<div>
|
|
<x-button :label="__('Clear System Password')" icon="lock_reset" color="error" wire:click="$set('confirmingPasswordRemoval', true)" data-test="clear-system-password" />
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</x-card>
|
|
|
|
<x-card :title="__('Upload Limits')" variant="outlined">
|
|
<div class="grid gap-5">
|
|
<x-toggle
|
|
wire:model.live="allowNeverExpire"
|
|
:label="__('Allow shares to never expire')"
|
|
:hint="__('When disabled, users must select an expiration time.')"
|
|
right
|
|
/>
|
|
|
|
<x-select
|
|
wire:model="defaultExpiration"
|
|
:label="__('Default Expiration')"
|
|
:placeholder="$allowNeverExpire ? __('None') : null"
|
|
:options="[
|
|
['id' => '1h', 'name' => __('1 Hour')],
|
|
['id' => '24h', 'name' => __('24 Hours')],
|
|
['id' => '48h', 'name' => __('48 Hours')],
|
|
['id' => '7d', 'name' => __('7 Days')],
|
|
['id' => '14d', 'name' => __('14 Days')],
|
|
['id' => '30d', 'name' => __('30 Days')],
|
|
]"
|
|
/>
|
|
|
|
<x-input
|
|
wire:model="maxFileSize"
|
|
:label="__('Max file size (MB)')"
|
|
type="number"
|
|
min="1"
|
|
:max="$phpMaxUploadMb"
|
|
suffix="MB"
|
|
:hint="__('PHP limit: :max MB (upload_max_filesize / post_max_size)', ['max' => $phpMaxUploadMb])"
|
|
/>
|
|
|
|
<x-input wire:model="maxFilesPerShare" :label="__('Max files per share')" type="number" min="1" />
|
|
|
|
<x-input wire:model="maxSizePerShare" :label="__('Max total size per share (GB)')" type="number" min="1" suffix="GB" />
|
|
</div>
|
|
</x-card>
|
|
|
|
<x-card :title="__('Storage')" variant="outlined">
|
|
<x-input
|
|
wire:model="maxStorageQuota"
|
|
:label="__('Max storage quota (GB)')"
|
|
type="number"
|
|
min="1"
|
|
suffix="GB"
|
|
:hint="__('When reached, new uploads are blocked.')"
|
|
/>
|
|
</x-card>
|
|
|
|
<x-button type="submit" :label="__('Save Settings')" variant="filled" icon="check" spinner="saveSettings" class="w-full" />
|
|
</form>
|
|
|
|
<x-modal wire:model="confirmingLogoRemoval" :title="__('Remove the logo?')" icon="delete">
|
|
{{ __('The upload and download pages show the default mark again.') }}
|
|
|
|
<x-slot:actions>
|
|
<x-button :label="__('Cancel')" x-on:click="close()" />
|
|
<x-button :label="__('Remove')" danger wire:click="removeLogo" data-test="confirm-remove-logo" />
|
|
</x-slot:actions>
|
|
</x-modal>
|
|
|
|
<x-modal wire:model="confirmingPasswordRemoval" :title="__('Remove the system password?')" icon="lock_open">
|
|
{{ __('Anyone who can reach the upload page can upload files again.') }}
|
|
|
|
<x-slot:actions>
|
|
<x-button :label="__('Cancel')" x-on:click="close()" />
|
|
<x-button :label="__('Remove')" danger wire:click="clearSystemPassword" data-test="confirm-clear-system-password" />
|
|
</x-slot:actions>
|
|
</x-modal>
|
|
</div>
|