Alpha flag for file storage settings (#6044)

## Summary
- Added "Alpha" badge to the File Storage & Sharing nav item in the
settings sidebar
- Added "Alpha" badge to the File Storage & Sharing page title
- Removed the old inline "(Alpha)" text from the Enable Group Signing
label
- Restructured all toggle cards so the switch is anchored to the right
of each row
- Tightened spacing between cards for a more compact layout
- Extended `ConfigNavItem` interface with optional `badge` and
`badgeColor` fields for reuse elsewhere
<img width="1696" height="1057" alt="image"
src="https://github.com/user-attachments/assets/77ac8276-ed65-4cae-8470-65de8f56dd74"
/>
This commit is contained in:
ConnorYoh
2026-04-01 17:18:48 +01:00
committed by GitHub
parent 74153b6deb
commit 801cc8a5f4
4 changed files with 112 additions and 85 deletions

View File

@@ -1,5 +1,5 @@
import React, { useMemo, useState, useEffect, useCallback, useRef } from 'react';
import { Modal, Text, ActionIcon, Tooltip, Group } from '@mantine/core';
import { Badge, Modal, Text, ActionIcon, Tooltip, Group } from '@mantine/core';
import { useNavigate, useLocation } from 'react-router-dom';
import LocalIcon from '@app/components/shared/LocalIcon';
import { useConfigNavSections } from '@app/components/shared/config/configNavSections';
@@ -186,6 +186,11 @@ const AppConfigModalInner: React.FC<AppConfigModalProps> = ({ opened, onClose })
<Text size="sm" fw={500} style={{ color }}>
{item.label}
</Text>
{item.badge && (
<Badge size="xs" variant="light" color={item.badgeColor ?? 'orange'} style={{ flexShrink: 0 }}>
{item.badge}
</Badge>
)}
{showPlanWarning && (
<LocalIcon
icon="warning-rounded"

View File

@@ -11,6 +11,8 @@ export interface ConfigNavItem {
component: React.ReactNode;
disabled?: boolean;
disabledTooltip?: string;
badge?: string;
badgeColor?: string;
}
export interface ConfigNavSection {

View File

@@ -105,7 +105,9 @@ export const useConfigNavSections = (
icon: 'storage-rounded',
component: <AdminStorageSharingSection />,
disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined,
badge: t('toolPanel.alpha', 'Alpha'),
badgeColor: 'orange',
},
{
key: 'adminEndpoints',

View File

@@ -1,6 +1,6 @@
import { useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Anchor, Group, Loader, Paper, Stack, Switch, Text } from '@mantine/core';
import { Anchor, Badge, Group, Loader, Paper, Stack, Switch, Text } from '@mantine/core';
import { useNavigate } from 'react-router-dom';
import { alert } from '@app/components/toast';
import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal';
@@ -124,42 +124,50 @@ export default function AdminStorageSharingSection() {
return (
<div className="settings-section-container">
<div className="settings-section-content">
<Stack gap="lg">
<Stack gap="sm">
<LoginRequiredBanner show={!loginEnabled} />
<div>
<Text fw={600} size="lg">{t('admin.settings.storage.title', 'File Storage & Sharing')}</Text>
<Group gap="xs" align="center">
<Text fw={600} size="lg">{t('admin.settings.storage.title', 'File Storage & Sharing')}</Text>
<Badge size="sm" variant="light" color="orange">{t('toolPanel.alpha', 'Alpha')}</Badge>
</Group>
<Text size="sm" c="dimmed">
{t('admin.settings.storage.description', 'Control server storage and sharing options.')}
</Text>
</div>
<Paper withBorder p="md" radius="md">
<Stack gap="md">
<Group justify="space-between" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.enabled.label', 'Enable Server File Storage')}</Text>
{isFieldPending('enabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.enabled.description', 'Allow users to store files on the server.')}
</Text>
<Paper withBorder p="sm" radius="md">
<Group justify="space-between" align="flex-start" wrap="nowrap">
<div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.enabled.label', 'Enable Server File Storage')}</Text>
{isFieldPending('enabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.enabled.description', 'Allow users to store files on the server.')}
</Text>
</div>
<Switch
checked={storageEnabled}
onChange={(e) => setSettings({ ...settings, enabled: e.currentTarget.checked })}
disabled={!loginEnabled}
styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/>
</Stack>
</Group>
</Paper>
<Paper withBorder p="md" radius="md">
<Stack gap="md">
<Group justify="space-between" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.enabled.label', 'Enable Sharing')}</Text>
{isFieldPending('sharing.enabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.enabled.description', 'Allow users to share stored files.')}
</Text>
<Paper withBorder p="sm" radius="md">
<Group justify="space-between" align="flex-start" wrap="nowrap">
<div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.enabled.label', 'Enable Sharing')}</Text>
{isFieldPending('sharing.enabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.enabled.description', 'Allow users to share stored files.')}
</Text>
</div>
<Switch
checked={settings.sharing?.enabled ?? false}
onChange={(e) =>
@@ -170,35 +178,38 @@ export default function AdminStorageSharingSection() {
}
disabled={!loginEnabled || !storageEnabled}
styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/>
</Stack>
</Group>
</Paper>
<Paper withBorder p="md" radius="md">
<Stack gap="md">
<Group justify="space-between" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.links.label', 'Enable Share Links')}</Text>
{isFieldPending('sharing.linkEnabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.links.description', 'Allow sharing via signed-in links.')}
</Text>
{!frontendUrlConfigured && (
<Text size="xs" c="orange">
{t('admin.settings.storage.sharing.links.frontendUrlNote', 'Requires a Frontend URL. ')}
<Anchor
href="#"
onClick={(e) => {
e.preventDefault();
navigate('/settings/adminGeneral#frontendUrl');
}}
c="orange"
td="underline"
>
{t('admin.settings.storage.sharing.links.frontendUrlLink', 'Configure in System Settings')}
</Anchor>
<Paper withBorder p="sm" radius="md">
<Group justify="space-between" align="flex-start" wrap="nowrap">
<div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.links.label', 'Enable Share Links')}</Text>
{isFieldPending('sharing.linkEnabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.links.description', 'Allow sharing via signed-in links.')}
</Text>
)}
{!frontendUrlConfigured && (
<Text size="xs" c="orange">
{t('admin.settings.storage.sharing.links.frontendUrlNote', 'Requires a Frontend URL. ')}
<Anchor
href="#"
onClick={(e) => {
e.preventDefault();
navigate('/settings/adminGeneral#frontendUrl');
}}
c="orange"
td="underline"
>
{t('admin.settings.storage.sharing.links.frontendUrlLink', 'Configure in System Settings')}
</Anchor>
</Text>
)}
</div>
<Switch
checked={settings.sharing?.linkEnabled ?? false}
onChange={(e) =>
@@ -209,35 +220,38 @@ export default function AdminStorageSharingSection() {
}
disabled={!loginEnabled || !sharingEnabled || !frontendUrlConfigured}
styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/>
</Stack>
</Group>
</Paper>
<Paper withBorder p="md" radius="md">
<Stack gap="md">
<Group justify="space-between" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.email.label', 'Enable Email Sharing')}</Text>
{isFieldPending('sharing.emailEnabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.email.description', 'Allow sharing with email addresses.')}
</Text>
{!mailEnabled && (
<Text size="xs" c="orange">
{t('admin.settings.storage.sharing.email.mailNote', 'Requires mail configuration. ')}
<Anchor
href="#"
onClick={(e) => {
e.preventDefault();
navigate('/settings/adminConnections');
}}
c="orange"
td="underline"
>
{t('admin.settings.storage.sharing.email.mailLink', 'Configure Mail Settings')}
</Anchor>
<Paper withBorder p="sm" radius="md">
<Group justify="space-between" align="flex-start" wrap="nowrap">
<div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.email.label', 'Enable Email Sharing')}</Text>
{isFieldPending('sharing.emailEnabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.email.description', 'Allow sharing with email addresses.')}
</Text>
)}
{!mailEnabled && (
<Text size="xs" c="orange">
{t('admin.settings.storage.sharing.email.mailNote', 'Requires mail configuration. ')}
<Anchor
href="#"
onClick={(e) => {
e.preventDefault();
navigate('/settings/adminConnections');
}}
c="orange"
td="underline"
>
{t('admin.settings.storage.sharing.email.mailLink', 'Configure Mail Settings')}
</Anchor>
</Text>
)}
</div>
<Switch
checked={settings.sharing?.emailEnabled ?? false}
onChange={(e) =>
@@ -248,19 +262,22 @@ export default function AdminStorageSharingSection() {
}
disabled={!loginEnabled || !sharingEnabled || !mailEnabled}
styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/>
</Stack>
</Group>
</Paper>
<Paper withBorder p="md" radius="md">
<Stack gap="md">
<Group justify="space-between" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.signing.enabled.label', 'Enable Group Signing (Alpha)')}</Text>
{isFieldPending('signing.enabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.signing.enabled.description', 'Allow users to create multi-participant document signing sessions. Requires server file storage to be enabled.')}
</Text>
<Paper withBorder p="sm" radius="md">
<Group justify="space-between" align="flex-start" wrap="nowrap">
<div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.signing.enabled.label', 'Enable Group Signing')}</Text>
{isFieldPending('signing.enabled') && <PendingBadge show={true} />}
</Group>
<Text size="xs" c="dimmed">
{t('admin.settings.storage.signing.enabled.description', 'Allow users to create multi-participant document signing sessions. Requires server file storage to be enabled.')}
</Text>
</div>
<Switch
checked={settings.signing?.enabled ?? false}
onChange={(e) =>
@@ -271,8 +288,9 @@ export default function AdminStorageSharingSection() {
}
disabled={!loginEnabled || !storageEnabled}
styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/>
</Stack>
</Group>
</Paper>
<RestartConfirmationModal