fixes and improvements
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { DialogFooter } from "./DialogFooter";
|
||||
|
||||
export function ConfirmDialog({
|
||||
open,
|
||||
title,
|
||||
message,
|
||||
confirmLabel = "Delete",
|
||||
onCancel,
|
||||
onConfirm,
|
||||
busy,
|
||||
}: {
|
||||
open: boolean;
|
||||
title: string;
|
||||
message: string;
|
||||
confirmLabel?: string;
|
||||
onCancel: () => void;
|
||||
onConfirm: () => void;
|
||||
busy?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onCancel} fullWidth maxWidth="xs">
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Stack spacing={1}>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{message}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</DialogContent>
|
||||
<DialogFooter
|
||||
onCancel={onCancel}
|
||||
onConfirm={onConfirm}
|
||||
confirmLabel={confirmLabel}
|
||||
confirmColor="error"
|
||||
confirmBusyLabel={confirmLabel}
|
||||
confirmDisabled={busy}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import {
|
||||
Alert,
|
||||
Box,
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
useMonitoringOverview,
|
||||
useSaveDashboardShortcut,
|
||||
} from "../hooks/useDashboard";
|
||||
import { useMonitoringSettings } from "../hooks/useSettings";
|
||||
import type { DashboardShortcut, DashboardShortcutInput } from "../types";
|
||||
import { NowPlaying } from "../components/NowPlaying";
|
||||
import { MonitoringOverviewTable } from "../components/MonitoringOverviewTable";
|
||||
@@ -310,7 +311,19 @@ function ShortcutCard({
|
||||
|
||||
export function Dashboard() {
|
||||
const navigate = useNavigate();
|
||||
const { data: activity } = useActivity();
|
||||
const { data: machines = [] } = useMonitoringSettings();
|
||||
const jellyfinMachines = useMemo(
|
||||
() =>
|
||||
machines.filter(
|
||||
(machine) => machine.enabled && machine.services.includes("jellyfin"),
|
||||
),
|
||||
[machines],
|
||||
);
|
||||
const [activeJellyfinMachineId, setActiveJellyfinMachineId] =
|
||||
useState<string>("");
|
||||
const selectedJellyfinId =
|
||||
activeJellyfinMachineId || jellyfinMachines[0]?.id || "";
|
||||
const { data: activity } = useActivity(selectedJellyfinId || undefined);
|
||||
const { data: monitoringOverview } = useMonitoringOverview();
|
||||
const { data: shortcuts = [] } = useDashboardShortcuts();
|
||||
const saveShortcut = useSaveDashboardShortcut();
|
||||
@@ -319,6 +332,7 @@ export function Dashboard() {
|
||||
const [shortcutDraft, setShortcutDraft] = useState<DashboardShortcutInput>(
|
||||
emptyShortcut(),
|
||||
);
|
||||
const [deleteShortcutId, setDeleteShortcutId] = useState<string | null>(null);
|
||||
|
||||
const openCreateShortcut = () => {
|
||||
setShortcutDraft(emptyShortcut());
|
||||
@@ -373,7 +387,7 @@ export function Dashboard() {
|
||||
}
|
||||
}}
|
||||
onEdit={() => openEditShortcut(shortcut)}
|
||||
onDelete={() => deleteShortcut.mutate(shortcut.id)}
|
||||
onDelete={() => setDeleteShortcutId(shortcut.id)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
@@ -389,6 +403,29 @@ export function Dashboard() {
|
||||
<SectionCard
|
||||
title="Jellyfin activity"
|
||||
description="Live sessions and idle users from Jellyfin."
|
||||
action={
|
||||
jellyfinMachines.length > 1 ? (
|
||||
<FormControl size="small" sx={{ minWidth: 180 }}>
|
||||
<Select
|
||||
value={selectedJellyfinId}
|
||||
onChange={(e) => setActiveJellyfinMachineId(e.target.value)}
|
||||
sx={{ fontSize: "0.8rem" }}
|
||||
>
|
||||
{jellyfinMachines.map((m) => (
|
||||
<MenuItem key={m.id} value={m.id}>
|
||||
{m.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
) : jellyfinMachines.length === 1 ? (
|
||||
<Chip
|
||||
label={jellyfinMachines[0].name}
|
||||
size="small"
|
||||
variant="outlined"
|
||||
/>
|
||||
) : null
|
||||
}
|
||||
>
|
||||
{activity ? (
|
||||
<NowPlaying
|
||||
@@ -414,6 +451,31 @@ export function Dashboard() {
|
||||
onClose={() => setShortcutDialogOpen(false)}
|
||||
onSave={saveShortcutDraft}
|
||||
/>
|
||||
<Dialog
|
||||
open={Boolean(deleteShortcutId)}
|
||||
onClose={() => setDeleteShortcutId(null)}
|
||||
fullWidth
|
||||
maxWidth="xs"
|
||||
>
|
||||
<DialogTitle>Delete shortcut?</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
This cannot be undone. The shortcut will be removed from the
|
||||
dashboard.
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogFooter
|
||||
onCancel={() => setDeleteShortcutId(null)}
|
||||
onConfirm={() => {
|
||||
if (deleteShortcutId) {
|
||||
deleteShortcut.mutate(deleteShortcutId);
|
||||
}
|
||||
setDeleteShortcutId(null);
|
||||
}}
|
||||
confirmLabel="Delete"
|
||||
confirmColor="error"
|
||||
/>
|
||||
</Dialog>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import { HoverEditButton } from "../components/HoverEditButton";
|
||||
import { SectionCard } from "../components/SectionCard";
|
||||
import { SelectionRailCard } from "../components/SelectionRailCard";
|
||||
import { TabbedCard } from "../components/TabbedCard";
|
||||
import { ConfirmDialog } from "../components/ConfirmDialog";
|
||||
const SERVICE_OPTIONS = [
|
||||
{ value: "monitoring", label: "Monitoring" },
|
||||
{ value: "files", label: "Files" },
|
||||
@@ -996,6 +997,7 @@ export function Settings() {
|
||||
const deleteMachine = useDeleteMonitoringMachine();
|
||||
const testMachineSSH = useTestMonitoringMachineSSH();
|
||||
const [tab, setTab] = useState<SettingsTab>("machines");
|
||||
const [deleteMachineId, setDeleteMachineId] = useState<string | null>(null);
|
||||
const [sshValidationMessage, setSSHValidationMessage] = useState("");
|
||||
const [sshValidationError, setSSHValidationError] = useState("");
|
||||
const [sshValidationStatus, setSSHValidationStatus] = useState("");
|
||||
@@ -1384,7 +1386,7 @@ export function Settings() {
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() =>
|
||||
deleteMachine.mutate(selectedMachine.id)
|
||||
setDeleteMachineId(selectedMachine.id)
|
||||
}
|
||||
>
|
||||
Delete
|
||||
@@ -1448,8 +1450,8 @@ export function Settings() {
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() => {
|
||||
deleteMachine.mutate(machineDraft.id as string);
|
||||
closeMachineDialog();
|
||||
setDeleteMachineId(machineDraft.id as string);
|
||||
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
@@ -1457,6 +1459,20 @@ export function Settings() {
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
|
||||
<ConfirmDialog
|
||||
open={Boolean(deleteMachineId)}
|
||||
title="Delete machine?"
|
||||
message="The machine will be removed. Action history will be deleted."
|
||||
onCancel={() => setDeleteMachineId(null)}
|
||||
onConfirm={() => {
|
||||
if (deleteMachineId) {
|
||||
deleteMachine.mutate(deleteMachineId);
|
||||
closeMachineDialog();
|
||||
}
|
||||
setDeleteMachineId(null);
|
||||
}}
|
||||
/>
|
||||
</Dialog>
|
||||
</Stack>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user