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
@@ -1,5 +1,5 @@
import React, { useMemo, useState, useEffect, useCallback, useRef } from 'react'; 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 { useNavigate, useLocation } from 'react-router-dom';
import LocalIcon from '@app/components/shared/LocalIcon'; import LocalIcon from '@app/components/shared/LocalIcon';
import { useConfigNavSections } from '@app/components/shared/config/configNavSections'; 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 }}> <Text size="sm" fw={500} style={{ color }}>
{item.label} {item.label}
</Text> </Text>
{item.badge && (
<Badge size="xs" variant="light" color={item.badgeColor ?? 'orange'} style={{ flexShrink: 0 }}>
{item.badge}
</Badge>
)}
{showPlanWarning && ( {showPlanWarning && (
<LocalIcon <LocalIcon
icon="warning-rounded" icon="warning-rounded"
@@ -11,6 +11,8 @@ export interface ConfigNavItem {
component: React.ReactNode; component: React.ReactNode;
disabled?: boolean; disabled?: boolean;
disabledTooltip?: string; disabledTooltip?: string;
badge?: string;
badgeColor?: string;
} }
export interface ConfigNavSection { export interface ConfigNavSection {
@@ -105,7 +105,9 @@ export const useConfigNavSections = (
icon: 'storage-rounded', icon: 'storage-rounded',
component: <AdminStorageSharingSection />, component: <AdminStorageSharingSection />,
disabled: requiresLogin, disabled: requiresLogin,
disabledTooltip: requiresLogin ? enableLoginTooltip : undefined disabledTooltip: requiresLogin ? enableLoginTooltip : undefined,
badge: t('toolPanel.alpha', 'Alpha'),
badgeColor: 'orange',
}, },
{ {
key: 'adminEndpoints', key: 'adminEndpoints',
@@ -1,6 +1,6 @@
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next'; 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 { useNavigate } from 'react-router-dom';
import { alert } from '@app/components/toast'; import { alert } from '@app/components/toast';
import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal'; import RestartConfirmationModal from '@app/components/shared/config/RestartConfirmationModal';
@@ -124,42 +124,50 @@ export default function AdminStorageSharingSection() {
return ( return (
<div className="settings-section-container"> <div className="settings-section-container">
<div className="settings-section-content"> <div className="settings-section-content">
<Stack gap="lg"> <Stack gap="sm">
<LoginRequiredBanner show={!loginEnabled} /> <LoginRequiredBanner show={!loginEnabled} />
<div> <div>
<Group gap="xs" align="center">
<Text fw={600} size="lg">{t('admin.settings.storage.title', 'File Storage & Sharing')}</Text> <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"> <Text size="sm" c="dimmed">
{t('admin.settings.storage.description', 'Control server storage and sharing options.')} {t('admin.settings.storage.description', 'Control server storage and sharing options.')}
</Text> </Text>
</div> </div>
<Paper withBorder p="md" radius="md"> <Paper withBorder p="sm" radius="md">
<Stack gap="md"> <Group justify="space-between" align="flex-start" wrap="nowrap">
<Group justify="space-between" align="center"> <div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.enabled.label', 'Enable Server File Storage')}</Text> <Text fw={600} size="sm">{t('admin.settings.storage.enabled.label', 'Enable Server File Storage')}</Text>
{isFieldPending('enabled') && <PendingBadge show={true} />} {isFieldPending('enabled') && <PendingBadge show={true} />}
</Group> </Group>
<Text size="xs" c="dimmed"> <Text size="xs" c="dimmed">
{t('admin.settings.storage.enabled.description', 'Allow users to store files on the server.')} {t('admin.settings.storage.enabled.description', 'Allow users to store files on the server.')}
</Text> </Text>
</div>
<Switch <Switch
checked={storageEnabled} checked={storageEnabled}
onChange={(e) => setSettings({ ...settings, enabled: e.currentTarget.checked })} onChange={(e) => setSettings({ ...settings, enabled: e.currentTarget.checked })}
disabled={!loginEnabled} disabled={!loginEnabled}
styles={getDisabledStyles()} styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/> />
</Stack> </Group>
</Paper> </Paper>
<Paper withBorder p="md" radius="md"> <Paper withBorder p="sm" radius="md">
<Stack gap="md"> <Group justify="space-between" align="flex-start" wrap="nowrap">
<Group justify="space-between" align="center"> <div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.enabled.label', 'Enable Sharing')}</Text> <Text fw={600} size="sm">{t('admin.settings.storage.sharing.enabled.label', 'Enable Sharing')}</Text>
{isFieldPending('sharing.enabled') && <PendingBadge show={true} />} {isFieldPending('sharing.enabled') && <PendingBadge show={true} />}
</Group> </Group>
<Text size="xs" c="dimmed"> <Text size="xs" c="dimmed">
{t('admin.settings.storage.sharing.enabled.description', 'Allow users to share stored files.')} {t('admin.settings.storage.sharing.enabled.description', 'Allow users to share stored files.')}
</Text> </Text>
</div>
<Switch <Switch
checked={settings.sharing?.enabled ?? false} checked={settings.sharing?.enabled ?? false}
onChange={(e) => onChange={(e) =>
@@ -170,13 +178,15 @@ export default function AdminStorageSharingSection() {
} }
disabled={!loginEnabled || !storageEnabled} disabled={!loginEnabled || !storageEnabled}
styles={getDisabledStyles()} styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/> />
</Stack> </Group>
</Paper> </Paper>
<Paper withBorder p="md" radius="md"> <Paper withBorder p="sm" radius="md">
<Stack gap="md"> <Group justify="space-between" align="flex-start" wrap="nowrap">
<Group justify="space-between" align="center"> <div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.links.label', 'Enable Share Links')}</Text> <Text fw={600} size="sm">{t('admin.settings.storage.sharing.links.label', 'Enable Share Links')}</Text>
{isFieldPending('sharing.linkEnabled') && <PendingBadge show={true} />} {isFieldPending('sharing.linkEnabled') && <PendingBadge show={true} />}
</Group> </Group>
@@ -199,6 +209,7 @@ export default function AdminStorageSharingSection() {
</Anchor> </Anchor>
</Text> </Text>
)} )}
</div>
<Switch <Switch
checked={settings.sharing?.linkEnabled ?? false} checked={settings.sharing?.linkEnabled ?? false}
onChange={(e) => onChange={(e) =>
@@ -209,13 +220,15 @@ export default function AdminStorageSharingSection() {
} }
disabled={!loginEnabled || !sharingEnabled || !frontendUrlConfigured} disabled={!loginEnabled || !sharingEnabled || !frontendUrlConfigured}
styles={getDisabledStyles()} styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/> />
</Stack> </Group>
</Paper> </Paper>
<Paper withBorder p="md" radius="md"> <Paper withBorder p="sm" radius="md">
<Stack gap="md"> <Group justify="space-between" align="flex-start" wrap="nowrap">
<Group justify="space-between" align="center"> <div>
<Group gap="xs" align="center">
<Text fw={600} size="sm">{t('admin.settings.storage.sharing.email.label', 'Enable Email Sharing')}</Text> <Text fw={600} size="sm">{t('admin.settings.storage.sharing.email.label', 'Enable Email Sharing')}</Text>
{isFieldPending('sharing.emailEnabled') && <PendingBadge show={true} />} {isFieldPending('sharing.emailEnabled') && <PendingBadge show={true} />}
</Group> </Group>
@@ -238,6 +251,7 @@ export default function AdminStorageSharingSection() {
</Anchor> </Anchor>
</Text> </Text>
)} )}
</div>
<Switch <Switch
checked={settings.sharing?.emailEnabled ?? false} checked={settings.sharing?.emailEnabled ?? false}
onChange={(e) => onChange={(e) =>
@@ -248,19 +262,22 @@ export default function AdminStorageSharingSection() {
} }
disabled={!loginEnabled || !sharingEnabled || !mailEnabled} disabled={!loginEnabled || !sharingEnabled || !mailEnabled}
styles={getDisabledStyles()} styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/> />
</Stack> </Group>
</Paper> </Paper>
<Paper withBorder p="md" radius="md"> <Paper withBorder p="sm" radius="md">
<Stack gap="md"> <Group justify="space-between" align="flex-start" wrap="nowrap">
<Group justify="space-between" align="center"> <div>
<Text fw={600} size="sm">{t('admin.settings.storage.signing.enabled.label', 'Enable Group Signing (Alpha)')}</Text> <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} />} {isFieldPending('signing.enabled') && <PendingBadge show={true} />}
</Group> </Group>
<Text size="xs" c="dimmed"> <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.')} {t('admin.settings.storage.signing.enabled.description', 'Allow users to create multi-participant document signing sessions. Requires server file storage to be enabled.')}
</Text> </Text>
</div>
<Switch <Switch
checked={settings.signing?.enabled ?? false} checked={settings.signing?.enabled ?? false}
onChange={(e) => onChange={(e) =>
@@ -271,8 +288,9 @@ export default function AdminStorageSharingSection() {
} }
disabled={!loginEnabled || !storageEnabled} disabled={!loginEnabled || !storageEnabled}
styles={getDisabledStyles()} styles={getDisabledStyles()}
style={{ flexShrink: 0 }}
/> />
</Stack> </Group>
</Paper> </Paper>
<RestartConfirmationModal <RestartConfirmationModal