0.12.0 Begin neu Architecture
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import { Card } from 'primereact/card';
|
||||
import { Button } from 'primereact/button';
|
||||
@@ -20,10 +20,12 @@ import blurayIndicatorIcon from '../assets/media-bluray.svg';
|
||||
import discIndicatorIcon from '../assets/media-disc.svg';
|
||||
import otherIndicatorIcon from '../assets/media-other.svg';
|
||||
import audiobookIndicatorIcon from '../assets/media-audiobook.svg';
|
||||
import { resolveJobPluginExecution } from '../utils/pluginExecution';
|
||||
import { getStatusLabel, getStatusSeverity, normalizeStatus } from '../utils/statusPresentation';
|
||||
|
||||
const processingStates = ['ANALYZING', 'RIPPING', 'MEDIAINFO_CHECK', 'ENCODING', 'CD_ANALYZING', 'CD_RIPPING', 'CD_ENCODING'];
|
||||
const driveActiveStates = ['ANALYZING', 'RIPPING', 'MEDIAINFO_CHECK', 'CD_ANALYZING', 'CD_RIPPING'];
|
||||
const activeCdDriveStates = ['CD_ANALYZING', 'CD_METADATA_SELECTION', 'CD_READY_TO_RIP', 'CD_RIPPING', 'CD_ENCODING'];
|
||||
const dashboardStatuses = new Set([
|
||||
'ANALYZING',
|
||||
'METADATA_SELECTION',
|
||||
@@ -822,8 +824,10 @@ export default function DashboardPage({
|
||||
jobsRefreshToken,
|
||||
pendingExpandedJobId,
|
||||
onPendingExpandedJobHandled,
|
||||
downloadSummary = null
|
||||
downloadSummary = null,
|
||||
children = null
|
||||
}) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [busyJobIds, setBusyJobIds] = useState(() => new Set());
|
||||
@@ -955,6 +959,7 @@ export default function DashboardPage({
|
||||
: audiobookUploadPhase === 'error'
|
||||
? 'Fehler'
|
||||
: 'Inaktiv';
|
||||
const isSubpageRoute = location.pathname !== '/';
|
||||
|
||||
const loadDashboardJobs = async () => {
|
||||
setJobsLoading(true);
|
||||
@@ -1335,19 +1340,12 @@ export default function DashboardPage({
|
||||
}
|
||||
};
|
||||
|
||||
const refreshKnownDrives = () => {
|
||||
api.getDetectedDrives()
|
||||
.then((res) => setKnownDrives(Array.isArray(res?.drives) ? res.drives : []))
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const handleRescan = async () => {
|
||||
setBusy(true);
|
||||
try {
|
||||
const response = await api.rescanDisc();
|
||||
refreshKnownDrives();
|
||||
const allDetected = response?.result?.allDetected || [];
|
||||
const emitted = response?.result?.emitted || 'none';
|
||||
const allDetected = Array.isArray(response?.result?.allDetected) ? response.result.allDetected : [];
|
||||
const count = allDetected.length;
|
||||
toastRef.current?.show({
|
||||
severity: count > 0 ? 'success' : 'info',
|
||||
@@ -1357,7 +1355,6 @@ export default function DashboardPage({
|
||||
: 'Kein Medium erkannt.',
|
||||
life: 2800
|
||||
});
|
||||
void emitted; // used implicitly via count
|
||||
await refreshPipeline();
|
||||
await loadDashboardJobs();
|
||||
} catch (error) {
|
||||
@@ -1367,6 +1364,12 @@ export default function DashboardPage({
|
||||
}
|
||||
};
|
||||
|
||||
const refreshKnownDrives = () => {
|
||||
api.getDetectedDrives()
|
||||
.then((res) => setKnownDrives(Array.isArray(res?.drives) ? res.drives : []))
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const handleRescanDrive = async (devicePath) => {
|
||||
setDriveRescanBusy((prev) => new Set([...prev, devicePath]));
|
||||
try {
|
||||
@@ -2029,7 +2032,6 @@ export default function DashboardPage({
|
||||
const lastNonCdDiscEvent = lastDiscEvent?.mediaProfile !== 'cd' ? lastDiscEvent : null;
|
||||
const contextDevice = pipeline?.context?.device;
|
||||
const device = lastNonCdDiscEvent || (contextDevice?.mediaProfile !== 'cd' ? contextDevice : null);
|
||||
const cdDriveEntries = Object.entries(pipeline?.cdDrives || {});
|
||||
|
||||
// Unified list of all known drives: merge lsblk drives + CD state + non-CD pipeline state
|
||||
const allDrives = useMemo(() => {
|
||||
@@ -2360,6 +2362,7 @@ export default function DashboardPage({
|
||||
const driveJobId = normalizeJobId(cdDrive?.jobId);
|
||||
const driveCtx = cdDrive?.context && typeof cdDrive.context === 'object' ? cdDrive.context : {};
|
||||
const cdState = cdDrive ? String(cdDrive.state || '').toUpperCase() : null;
|
||||
const isCdDriveLocked = cdState ? activeCdDriveStates.includes(cdState) : false;
|
||||
|
||||
return (
|
||||
<div key={drivePath} className="drive-list-item">
|
||||
@@ -2380,7 +2383,7 @@ export default function DashboardPage({
|
||||
size="small"
|
||||
severity="secondary"
|
||||
loading={isRescanBusy}
|
||||
disabled={isRescanBusy || isDriveActive}
|
||||
disabled={isRescanBusy || isDriveActive || isCdDriveLocked}
|
||||
onClick={() => handleRescanDrive(drivePath)}
|
||||
title="Laufwerk neu lesen"
|
||||
aria-label="Laufwerk neu lesen"
|
||||
@@ -2481,7 +2484,12 @@ export default function DashboardPage({
|
||||
</div>
|
||||
|
||||
<div className="dashboard-col dashboard-col-center">
|
||||
<Card title="Job Übersicht" subTitle="Kompakte Liste; Klick auf Zeile öffnet die volle Job-Detailansicht mit passenden CTAs">
|
||||
{isSubpageRoute ? (
|
||||
<div className="dashboard-subpage-content">
|
||||
{children}
|
||||
</div>
|
||||
) : (
|
||||
<Card title="Job Übersicht" subTitle="Kompakte Liste; Klick auf Zeile öffnet die volle Job-Detailansicht mit passenden CTAs">
|
||||
{jobsLoading ? (
|
||||
<p>Jobs werden geladen ...</p>
|
||||
) : dashboardJobs.length === 0 ? (
|
||||
@@ -2530,6 +2538,7 @@ export default function DashboardPage({
|
||||
? pipelineForJob.context.selectedMetadata
|
||||
: {};
|
||||
const audiobookChapterCount = Array.isArray(audiobookMeta?.chapters) ? audiobookMeta.chapters.length : 0;
|
||||
const pluginExecution = resolveJobPluginExecution(job, pipelineForJob?.context);
|
||||
|
||||
if (isExpanded) {
|
||||
return (
|
||||
@@ -2552,6 +2561,7 @@ export default function DashboardPage({
|
||||
</strong>
|
||||
<div className="dashboard-job-badges">
|
||||
<Tag value={statusBadgeValue} severity={statusBadgeSeverity} />
|
||||
{pluginExecution ? <Tag value={pluginExecution.label} severity="warning" title={pluginExecution.title} /> : null}
|
||||
{isCurrentSession ? <Tag value="Aktive Session" severity="info" /> : null}
|
||||
{isResumable ? <Tag value="Fortsetzbar" severity="success" /> : null}
|
||||
{normalizedStatus === 'READY_TO_ENCODE'
|
||||
@@ -2681,6 +2691,7 @@ export default function DashboardPage({
|
||||
</div>
|
||||
<div className="dashboard-job-badges">
|
||||
<Tag value={statusBadgeValue} severity={statusBadgeSeverity} />
|
||||
{pluginExecution ? <Tag value={pluginExecution.label} severity="warning" title={pluginExecution.title} /> : null}
|
||||
{isCurrentSession ? <Tag value="Aktive Session" severity="info" /> : null}
|
||||
{isResumable ? <Tag value="Fortsetzbar" severity="success" /> : null}
|
||||
{normalizedStatus === 'READY_TO_ENCODE'
|
||||
@@ -2700,6 +2711,7 @@ export default function DashboardPage({
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="dashboard-col dashboard-col-right">
|
||||
@@ -3051,7 +3063,7 @@ export default function DashboardPage({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{monitoringState.enabled ? (
|
||||
{!isSubpageRoute && monitoringState.enabled ? (
|
||||
<Card title="Hardware Monitoring">
|
||||
<div className="hardware-monitor-head">
|
||||
{!monitoringState.enabled ? (
|
||||
|
||||
Reference in New Issue
Block a user