Publish curated LumaOps source from c85ee9ef8f1454f5c305398902afbb9e6738de40
Managed validation / full (push) Failing after 8s
Managed validation / full (push) Failing after 8s
This commit is contained in:
1 parent
91f8b3e3c1
commit
def7920856
2271 files changed
+501225
-501178
No files matched your search
@@ -1,80 +1,80 @@
|
||||
import { ArrowLeft, Layers3, MemoryStick, Wifi } from "lucide-react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { api } from "../api/client";
|
||||
import type { DeviceGroup, DeviceState } from "../api/types";
|
||||
import { DeviceCard } from "../components/DeviceCard";
|
||||
import { RgbControlPanel } from "../components/RgbControlPanel";
|
||||
import { useToast } from "../components/Toast";
|
||||
import { Badge, ErrorPanel, LoadingGrid, PageHeader } from "../components/ui";
|
||||
|
||||
export function DeviceGroupPage() {
|
||||
const { groupId = "" } = useParams();
|
||||
const queryClient = useQueryClient();
|
||||
const { notify } = useToast();
|
||||
const query = useQuery({
|
||||
queryKey: ["device-group", groupId],
|
||||
queryFn: () => api<DeviceGroup>(`/api/v1/device-groups/${groupId}`),
|
||||
});
|
||||
const command = useMutation({
|
||||
mutationFn: (state: DeviceState) => api<{ status: string; results: Array<{ status: string }> }>(`/api/v1/device-groups/${groupId}/state`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ state }),
|
||||
}),
|
||||
onSuccess: (result) => {
|
||||
const failed = result.results.filter((item) => item.status === "failed").length;
|
||||
notify(failed ? `${failed} RAM-modules konden niet worden bijgewerkt.` : "RAM-groep bijgewerkt.", failed ? "danger" : "success");
|
||||
void queryClient.invalidateQueries({ queryKey: ["device-group", groupId] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["device-groups"] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["devices"] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["system"] });
|
||||
},
|
||||
onError: (error) => notify(error instanceof Error ? error.message : "RAM-groepsopdracht mislukt.", "danger"),
|
||||
});
|
||||
|
||||
if (query.isLoading) return <LoadingGrid count={3} />;
|
||||
if (query.error || !query.data) return <ErrorPanel error={query.error} retry={() => void query.refetch()} />;
|
||||
const group = query.data;
|
||||
const disabled = group.online_count === 0 || group.devices.every((device) => device.read_only || device.blocked);
|
||||
|
||||
return <>
|
||||
<Link className="back-link" to="/devices"><ArrowLeft size={16} /> Terug naar apparaten</Link>
|
||||
<PageHeader
|
||||
eyebrow="Gegroepeerd apparaat"
|
||||
title={group.name}
|
||||
description={`${group.vendor ?? "RAM"} · ${group.module_count} fysieke modules · ${group.led_count} leds`}
|
||||
/>
|
||||
<div className="detail-status">
|
||||
<Badge tone={group.online ? "success" : "warning"}><Wifi size={13} /> {group.online_count}/{group.module_count} online</Badge>
|
||||
<Badge tone="accent"><Layers3 size={13} /> Als groep bedienbaar</Badge>
|
||||
{group.mixed ? <Badge tone="warning">Gemengde toestand</Badge> : null}
|
||||
</div>
|
||||
<div className="detail-grid device-group-overview">
|
||||
<RgbControlPanel
|
||||
targetKey={group.id}
|
||||
capabilities={group.capabilities}
|
||||
state={group.state}
|
||||
modes={group.modes}
|
||||
pending={command.isPending}
|
||||
disabled={disabled}
|
||||
onApply={(state) => command.mutate(state)}
|
||||
/>
|
||||
<div className="group-summary">
|
||||
<MemoryStick size={34} />
|
||||
<strong>{group.module_count} modules</strong>
|
||||
<span>Groepsopdrachten worden afzonderlijk bevestigd en blijvend opgeslagen per fysieke module.</span>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section-block">
|
||||
<div className="section-heading"><div><h2>Individuele RAM-modules</h2><p>Open een module om kleur, effect en overige mogelijkheden uitsluitend daarop toe te passen.</p></div></div>
|
||||
<div className="grid grid--devices">
|
||||
{group.devices.map((device, index) => <DeviceCard device={device} moduleLabel={`RAM-module ${index + 1} · ${moduleAddress(device.location)}`} key={device.id} />)}
|
||||
</div>
|
||||
</section>
|
||||
</>;
|
||||
}
|
||||
|
||||
function moduleAddress(location: string | null) {
|
||||
const address = location?.match(/address (0x[0-9a-f]+)/i)?.[1];
|
||||
return address?.toUpperCase() ?? "onbekend adres";
|
||||
}
|
||||
import { ArrowLeft, Layers3, MemoryStick, Wifi } from "lucide-react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Link, useParams } from "react-router-dom";
|
||||
import { api } from "../api/client";
|
||||
import type { DeviceGroup, DeviceState } from "../api/types";
|
||||
import { DeviceCard } from "../components/DeviceCard";
|
||||
import { RgbControlPanel } from "../components/RgbControlPanel";
|
||||
import { useToast } from "../components/Toast";
|
||||
import { Badge, ErrorPanel, LoadingGrid, PageHeader } from "../components/ui";
|
||||
|
||||
export function DeviceGroupPage() {
|
||||
const { groupId = "" } = useParams();
|
||||
const queryClient = useQueryClient();
|
||||
const { notify } = useToast();
|
||||
const query = useQuery({
|
||||
queryKey: ["device-group", groupId],
|
||||
queryFn: () => api<DeviceGroup>(`/api/v1/device-groups/${groupId}`),
|
||||
});
|
||||
const command = useMutation({
|
||||
mutationFn: (state: DeviceState) => api<{ status: string; results: Array<{ status: string }> }>(`/api/v1/device-groups/${groupId}/state`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ state }),
|
||||
}),
|
||||
onSuccess: (result) => {
|
||||
const failed = result.results.filter((item) => item.status === "failed").length;
|
||||
notify(failed ? `${failed} RAM-modules konden niet worden bijgewerkt.` : "RAM-groep bijgewerkt.", failed ? "danger" : "success");
|
||||
void queryClient.invalidateQueries({ queryKey: ["device-group", groupId] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["device-groups"] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["devices"] });
|
||||
void queryClient.invalidateQueries({ queryKey: ["system"] });
|
||||
},
|
||||
onError: (error) => notify(error instanceof Error ? error.message : "RAM-groepsopdracht mislukt.", "danger"),
|
||||
});
|
||||
|
||||
if (query.isLoading) return <LoadingGrid count={3} />;
|
||||
if (query.error || !query.data) return <ErrorPanel error={query.error} retry={() => void query.refetch()} />;
|
||||
const group = query.data;
|
||||
const disabled = group.online_count === 0 || group.devices.every((device) => device.read_only || device.blocked);
|
||||
|
||||
return <>
|
||||
<Link className="back-link" to="/devices"><ArrowLeft size={16} /> Terug naar apparaten</Link>
|
||||
<PageHeader
|
||||
eyebrow="Gegroepeerd apparaat"
|
||||
title={group.name}
|
||||
description={`${group.vendor ?? "RAM"} · ${group.module_count} fysieke modules · ${group.led_count} leds`}
|
||||
/>
|
||||
<div className="detail-status">
|
||||
<Badge tone={group.online ? "success" : "warning"}><Wifi size={13} /> {group.online_count}/{group.module_count} online</Badge>
|
||||
<Badge tone="accent"><Layers3 size={13} /> Als groep bedienbaar</Badge>
|
||||
{group.mixed ? <Badge tone="warning">Gemengde toestand</Badge> : null}
|
||||
</div>
|
||||
<div className="detail-grid device-group-overview">
|
||||
<RgbControlPanel
|
||||
targetKey={group.id}
|
||||
capabilities={group.capabilities}
|
||||
state={group.state}
|
||||
modes={group.modes}
|
||||
pending={command.isPending}
|
||||
disabled={disabled}
|
||||
onApply={(state) => command.mutate(state)}
|
||||
/>
|
||||
<div className="group-summary">
|
||||
<MemoryStick size={34} />
|
||||
<strong>{group.module_count} modules</strong>
|
||||
<span>Groepsopdrachten worden afzonderlijk bevestigd en blijvend opgeslagen per fysieke module.</span>
|
||||
</div>
|
||||
</div>
|
||||
<section className="section-block">
|
||||
<div className="section-heading"><div><h2>Individuele RAM-modules</h2><p>Open een module om kleur, effect en overige mogelijkheden uitsluitend daarop toe te passen.</p></div></div>
|
||||
<div className="grid grid--devices">
|
||||
{group.devices.map((device, index) => <DeviceCard device={device} moduleLabel={`RAM-module ${index + 1} · ${moduleAddress(device.location)}`} key={device.id} />)}
|
||||
</div>
|
||||
</section>
|
||||
</>;
|
||||
}
|
||||
|
||||
function moduleAddress(location: string | null) {
|
||||
const address = location?.match(/address (0x[0-9a-f]+)/i)?.[1];
|
||||
return address?.toUpperCase() ?? "onbekend adres";
|
||||
}
|
||||
Reference in new issue
Block a user