diff --git a/web/src/components/indicators/Chip.tsx b/web/src/components/indicators/Chip.tsx
index 16cfb9bf5..8427ff692 100644
--- a/web/src/components/indicators/Chip.tsx
+++ b/web/src/components/indicators/Chip.tsx
@@ -1,4 +1,5 @@
-import { ReactNode, useRef } from "react";
+import { LogSeverity } from "@/types/log";
+import { ReactNode, useMemo, useRef } from "react";
import { CSSTransition } from "react-transition-group";
type ChipProps = {
@@ -39,3 +40,35 @@ export default function Chip({
);
}
+
+type LogChipProps = {
+ severity: LogSeverity;
+ onClickSeverity?: () => void;
+};
+export function LogChip({ severity, onClickSeverity }: LogChipProps) {
+ const severityClassName = useMemo(() => {
+ switch (severity) {
+ case "info":
+ return "text-primary-foreground/60 bg-secondary hover:bg-secondary/60";
+ case "warning":
+ return "text-warning-foreground bg-warning hover:bg-warning/80";
+ case "error":
+ return "text-destructive-foreground bg-destructive hover:bg-destructive/80";
+ }
+ }, [severity]);
+
+ return (
+
{
+ e.stopPropagation();
+
+ if (onClickSeverity) {
+ onClickSeverity();
+ }
+ }}
+ >
+ {severity}
+
+ );
+}
diff --git a/web/src/components/overlay/LogInfoDialog.tsx b/web/src/components/overlay/LogInfoDialog.tsx
new file mode 100644
index 000000000..695da273c
--- /dev/null
+++ b/web/src/components/overlay/LogInfoDialog.tsx
@@ -0,0 +1,53 @@
+import { LogLine } from "@/types/log";
+import { isDesktop } from "react-device-detect";
+import { Sheet, SheetContent } from "../ui/sheet";
+import { Drawer, DrawerContent } from "../ui/drawer";
+import { LogChip } from "../indicators/Chip";
+
+type LogInfoDialogProps = {
+ logLine?: LogLine;
+ setLogLine: (log: LogLine | undefined) => void;
+};
+export default function LogInfoDialog({
+ logLine,
+ setLogLine,
+}: LogInfoDialogProps) {
+ const Overlay = isDesktop ? Sheet : Drawer;
+ const Content = isDesktop ? SheetContent : DrawerContent;
+
+ return (
+ {
+ if (!open) {
+ setLogLine(undefined);
+ }
+ }}
+ >
+
+ {logLine && (
+
+
+
+
+ Timestamp
+
+
{logLine.dateStamp}
+
+
+
Tag
+
{logLine.section}
+
+
+
Message
+
{logLine.content}
+
+
+ )}
+
+
+ );
+}
diff --git a/web/src/pages/Logs.tsx b/web/src/pages/Logs.tsx
index a1ad29f17..54f2bd958 100644
--- a/web/src/pages/Logs.tsx
+++ b/web/src/pages/Logs.tsx
@@ -5,6 +5,8 @@ import copy from "copy-to-clipboard";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { LuCopy } from "react-icons/lu";
import axios from "axios";
+import LogInfoDialog from "@/components/overlay/LogInfoDialog";
+import { LogChip } from "@/components/indicators/Chip";
const logTypes = ["frigate", "go2rtc", "nginx"] as const;
type LogType = (typeof logTypes)[number];
@@ -300,8 +302,14 @@ function Logs() {
const [filterSeverity, setFilterSeverity] = useState();
+ // log selection
+
+ const [selectedLog, setSelectedLog] = useState();
+
return (
+
+
setFilterSeverity(line.severity)}
+ onSelect={() => setSelectedLog(line)}
/>
);
}
@@ -411,54 +420,34 @@ type LogLineDataProps = {
className: string;
line: LogLine;
onClickSeverity: () => void;
+ onSelect: () => void;
};
function LogLineData({
startRef,
className,
line,
onClickSeverity,
+ onSelect,
}: LogLineDataProps) {
- // long log message
-
- const contentRef = useRef(null);
-
- // severity coloring
-
- const severityClassName = useMemo(() => {
- switch (line.severity) {
- case "info":
- return "text-primary-foreground/60 bg-secondary hover:bg-secondary/60";
- case "warning":
- return "text-warning-foreground bg-warning hover:bg-warning/80";
- case "error":
- return "text-destructive-foreground bg-destructive hover:bg-destructive/80";
- }
- }, [line]);
-
return (