Redesign beta Magent UI
This commit is contained in:
@@ -19,6 +19,12 @@ type ServiceOptions = {
|
||||
qualityProfiles: { id: number; name: string; label: string }[]
|
||||
}
|
||||
|
||||
type ServiceStatus = {
|
||||
name: string
|
||||
status: string
|
||||
message?: string
|
||||
}
|
||||
|
||||
const SECTION_LABELS: Record<string, string> = {
|
||||
magent: 'Magent',
|
||||
general: 'General',
|
||||
@@ -414,6 +420,8 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
||||
const [maintenanceStatus, setMaintenanceStatus] = useState<string | null>(null)
|
||||
const [maintenanceBusy, setMaintenanceBusy] = useState(false)
|
||||
const [liveStreamConnected, setLiveStreamConnected] = useState(false)
|
||||
const [serviceStatuses, setServiceStatuses] = useState<ServiceStatus[]>([])
|
||||
const [serviceStatusCheckedAt, setServiceStatusCheckedAt] = useState<string | null>(null)
|
||||
const requestsSyncRef = useRef<any | null>(null)
|
||||
const artworkPrefetchRef = useRef<any | null>(null)
|
||||
const computeProgressPercent = (
|
||||
@@ -543,6 +551,21 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const loadServiceStatuses = useCallback(async () => {
|
||||
try {
|
||||
const baseUrl = getApiBase()
|
||||
const response = await authFetch(`${baseUrl}/status/services`)
|
||||
if (!response.ok) {
|
||||
return
|
||||
}
|
||||
const data = await response.json()
|
||||
setServiceStatuses(Array.isArray(data?.services) ? data.services : [])
|
||||
setServiceStatusCheckedAt(new Date().toISOString())
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const load = async () => {
|
||||
if (!getToken()) {
|
||||
@@ -550,7 +573,7 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await loadSettings()
|
||||
await Promise.all([loadSettings(), loadServiceStatuses()])
|
||||
if (section === 'cache' || section === 'artwork') {
|
||||
await loadArtworkPrefetchStatus()
|
||||
await loadArtworkSummary()
|
||||
@@ -570,7 +593,7 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
||||
if (section === 'radarr') {
|
||||
void loadOptions('radarr')
|
||||
}
|
||||
}, [loadArtworkPrefetchStatus, loadArtworkSummary, loadOptions, loadSettings, router, section])
|
||||
}, [loadArtworkPrefetchStatus, loadArtworkSummary, loadOptions, loadServiceStatuses, loadSettings, router, section])
|
||||
|
||||
const groupedSettings = useMemo(() => {
|
||||
const groups: Record<string, AdminSetting[]> = {}
|
||||
@@ -583,6 +606,22 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
||||
}, [settings])
|
||||
|
||||
const settingsSection = SETTINGS_SECTION_MAP[section] ?? null
|
||||
const statusNamesBySection: Record<string, string[]> = {
|
||||
seerr: ['Seerr', 'Jellyseerr', 'Jellyseer'],
|
||||
jellyseerr: ['Seerr', 'Jellyseerr', 'Jellyseer'],
|
||||
jellyfin: ['Jellyfin'],
|
||||
sonarr: ['Sonarr'],
|
||||
radarr: ['Radarr'],
|
||||
prowlarr: ['Prowlarr'],
|
||||
qbittorrent: ['qBittorrent', 'Qbittorrent'],
|
||||
}
|
||||
const statusNames = statusNamesBySection[section] ?? statusNamesBySection[settingsSection ?? ''] ?? []
|
||||
const currentServiceStatus = serviceStatuses.find((service) =>
|
||||
statusNames.some((name) => name.toLowerCase() === service.name.toLowerCase())
|
||||
)
|
||||
const currentServiceConfigured = currentServiceStatus
|
||||
? currentServiceStatus.status !== 'not_configured'
|
||||
: null
|
||||
const isMagentGroupedSection = section === 'magent' || section === 'general' || section === 'notifications'
|
||||
const isSiteGroupedSection = section === 'site'
|
||||
const visibleSections = settingsSection ? [settingsSection] : []
|
||||
@@ -1681,6 +1720,39 @@ export default function SettingsPage({ section }: SettingsPageProps) {
|
||||
}
|
||||
>
|
||||
{status && <div className="error-banner">{status}</div>}
|
||||
{currentServiceStatus ? (
|
||||
<section className="admin-section admin-zone service-status-panel">
|
||||
<div className="service-status-summary">
|
||||
<span className={`system-dot system-dot-${currentServiceStatus.status}`} aria-hidden="true" />
|
||||
<div>
|
||||
<span className="section-kicker">Connection status</span>
|
||||
<h2>{currentServiceStatus.name}</h2>
|
||||
<p className="section-subtitle">
|
||||
{currentServiceStatus.message ?? 'No service message was returned.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="service-status-grid">
|
||||
<div>
|
||||
<span>Status</span>
|
||||
<strong>{currentServiceStatus.status.replaceAll('_', ' ')}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Configuration</span>
|
||||
<strong>{currentServiceConfigured ? 'Configured' : 'Not configured'}</strong>
|
||||
</div>
|
||||
<div>
|
||||
<span>Last checked</span>
|
||||
<strong>
|
||||
{serviceStatusCheckedAt ? new Date(serviceStatusCheckedAt).toLocaleString() : 'Not checked yet'}
|
||||
</strong>
|
||||
</div>
|
||||
<button type="button" className="ghost-button" onClick={() => void loadServiceStatuses()}>
|
||||
Refresh status
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
) : null}
|
||||
{settingsSections.length > 0 ? (
|
||||
<div className="admin-form admin-zone-stack">
|
||||
{settingsSections
|
||||
|
||||
Reference in New Issue
Block a user