Indigo (the default), Blue, Teal, Green, Amber, Rose and Violet in the Vibrant style and Graphite in the Neutral style are generated from config into the stylesheet. Admin settings opens with a colour profile card: a swatch previews the profile on the page, and Save Settings stores it as color_profile, which AppServiceProvider hands to the package's resolver, so every page, mail and error page wears it. An unknown profile is refused, and a saved one that disappears falls back to indigo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
127 lines
6.1 KiB
PHP
127 lines
6.1 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="__('Colour profile')" variant="outlined">
|
|
<x-scheme-picker wire:model="colorProfile" :hint="__('Choosing one previews it here. After saving, every page, mail and error page uses it.')" data-test="color-profile" />
|
|
</x-card>
|
|
|
|
<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" data-test="save-settings" />
|
|
</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>
|