From 70d61832fe56db5a646f91da29c59d2c353c7813 Mon Sep 17 00:00:00 2001 From: Nick Mowen Date: Fri, 15 Dec 2023 16:42:51 -0700 Subject: [PATCH] Cleanup --- web-new/src/pages/Dashboard.tsx | 2 +- web-new/src/pages/Live.tsx | 10 ++- web-new/src/types/frigateConfig.ts | 2 + web-new/src/utils/dateUtil.ts | 123 ++++++++++++++++++++--------- 4 files changed, 98 insertions(+), 39 deletions(-) diff --git a/web-new/src/pages/Dashboard.tsx b/web-new/src/pages/Dashboard.tsx index f806884c5..70f9fa89a 100644 --- a/web-new/src/pages/Dashboard.tsx +++ b/web-new/src/pages/Dashboard.tsx @@ -39,7 +39,7 @@ export function Dashboard() { {config && (
-
+
{sortedCameras.map((camera) => { return ; })} diff --git a/web-new/src/pages/Live.tsx b/web-new/src/pages/Live.tsx index 86aeddb95..41913cdee 100644 --- a/web-new/src/pages/Live.tsx +++ b/web-new/src/pages/Live.tsx @@ -26,6 +26,14 @@ function Live() { const cameraConfig = useMemo(() => { return config?.cameras[camera]; }, [camera, config]); + const sortedCameras = useMemo(() => { + if (!config) { + return []; + } + + return Object.values(config.cameras) + .sort((aConf, bConf) => aConf.ui.order - bConf.ui.order); + }, [config]); const restreamEnabled = useMemo(() => { return ( config && @@ -66,7 +74,7 @@ function Live() { Select A Camera - {Object.keys(config?.cameras || {}).map((item) => ( + {Object.keys(sortedCameras).map((item) => ( new Date(long * 1000); export const epochToLong = (date: number): number => date / 1000; export const dateToLong = (date: Date): number => epochToLong(date.getTime()); @@ -40,23 +39,45 @@ export const getNowYesterdayInLong = (): number => { // only used as a fallback if the browser does not support dateStyle/timeStyle in Intl.DateTimeFormat const formatMap: { [k: string]: { - date: { year: 'numeric' | '2-digit'; month: 'long' | 'short' | '2-digit'; day: 'numeric' | '2-digit' }; - time: { hour: 'numeric'; minute: 'numeric'; second?: 'numeric'; timeZoneName?: 'short' | 'long' }; + date: { + year: "numeric" | "2-digit"; + month: "long" | "short" | "2-digit"; + day: "numeric" | "2-digit"; + }; + time: { + hour: "numeric"; + minute: "numeric"; + second?: "numeric"; + timeZoneName?: "short" | "long"; + }; }; } = { full: { - date: { year: 'numeric', month: 'long', day: 'numeric' }, - time: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'long' }, + date: { year: "numeric", month: "long", day: "numeric" }, + time: { + hour: "numeric", + minute: "numeric", + second: "numeric", + timeZoneName: "long", + }, }, long: { - date: { year: 'numeric', month: 'long', day: 'numeric' }, - time: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'long' }, + date: { year: "numeric", month: "long", day: "numeric" }, + time: { + hour: "numeric", + minute: "numeric", + second: "numeric", + timeZoneName: "long", + }, }, medium: { - date: { year: 'numeric', month: 'short', day: 'numeric' }, - time: { hour: 'numeric', minute: 'numeric', second: 'numeric' }, + date: { year: "numeric", month: "short", day: "numeric" }, + time: { hour: "numeric", minute: "numeric", second: "numeric" }, + }, + short: { + date: { year: "2-digit", month: "2-digit", day: "2-digit" }, + time: { hour: "numeric", minute: "numeric" }, }, - short: { date: { year: '2-digit', month: '2-digit', day: '2-digit' }, time: { hour: 'numeric', minute: 'numeric' } }, }; /** @@ -79,11 +100,11 @@ const getResolvedTimeZone = () => { return Intl.DateTimeFormat().resolvedOptions().timeZone; } catch (error) { const offsetMinutes = new Date().getTimezoneOffset(); - return `UTC${offsetMinutes < 0 ? '+' : '-'}${Math.abs(offsetMinutes / 60) + return `UTC${offsetMinutes < 0 ? "+" : "-"}${Math.abs(offsetMinutes / 60) .toString() - .padStart(2, '0')}:${Math.abs(offsetMinutes % 60) + .padStart(2, "0")}:${Math.abs(offsetMinutes % 60) .toString() - .padStart(2, '0')}`; + .padStart(2, "0")}`; } }; @@ -103,11 +124,21 @@ const getResolvedTimeZone = () => { * * @throws {Error} If the given unixTimestamp is not a valid number, the function will return 'Invalid time'. */ -export const formatUnixTimestampToDateTime = (unixTimestamp: number, config: UiConfig): string => { - const { timezone, time_format, date_style, time_style, strftime_fmt } = config; - const locale = window.navigator?.language || 'en-US'; +export const formatUnixTimestampToDateTime = ( + unixTimestamp: number, + config: { + timezone?: string; + time_format?: "browser" | "12hour" | "24hour"; + date_style?: "full" | "long" | "medium" | "short"; + time_style?: "full" | "long" | "medium" | "short"; + strftime_fmt?: string; + } +): string => { + const { timezone, time_format, date_style, time_style, strftime_fmt } = + config; + const locale = window.navigator?.language || "en-US"; if (isNaN(unixTimestamp)) { - return 'Invalid time'; + return "Invalid time"; } try { @@ -125,7 +156,7 @@ export const formatUnixTimestampToDateTime = (unixTimestamp: number, config: UiC const options: Intl.DateTimeFormatOptions = { dateStyle: date_style, timeStyle: time_style, - hour12: time_format !== 'browser' ? time_format == '12hour' : undefined, + hour12: time_format !== "browser" ? time_format == "12hour" : undefined, }; // Only set timeZone option when resolvedTimeZone does not match UTC±HH:MM format, or when timezone is set in config @@ -143,15 +174,26 @@ export const formatUnixTimestampToDateTime = (unixTimestamp: number, config: UiC // fallback if the browser does not support dateStyle/timeStyle in Intl.DateTimeFormat // This works even tough the timezone is undefined, it will use the runtime's default time zone if (!containsTime) { - const dateOptions = { ...formatMap[date_style ?? ""]?.date, timeZone: options.timeZone, hour12: options.hour12 }; - const timeOptions = { ...formatMap[time_style ?? ""]?.time, timeZone: options.timeZone, hour12: options.hour12 }; + const dateOptions = { + ...formatMap[date_style ?? ""]?.date, + timeZone: options.timeZone, + hour12: options.hour12, + }; + const timeOptions = { + ...formatMap[time_style ?? ""]?.time, + timeZone: options.timeZone, + hour12: options.hour12, + }; - return `${date.toLocaleDateString(locale, dateOptions)} ${date.toLocaleTimeString(locale, timeOptions)}`; + return `${date.toLocaleDateString( + locale, + dateOptions + )} ${date.toLocaleTimeString(locale, timeOptions)}`; } return formattedDateTime; } catch (error) { - return 'Invalid time'; + return "Invalid time"; } }; @@ -169,28 +211,31 @@ interface DurationToken { * @param end_time: number|null - Unix timestamp for end time * @returns string - duration or 'In Progress' if end time is not provided */ -export const getDurationFromTimestamps = (start_time: number, end_time: number | null): string => { +export const getDurationFromTimestamps = ( + start_time: number, + end_time: number | null +): string => { if (isNaN(start_time)) { - return 'Invalid start time'; + return "Invalid start time"; } - let duration = 'In Progress'; + let duration = "In Progress"; if (end_time !== null) { if (isNaN(end_time)) { - return 'Invalid end time'; + return "Invalid end time"; } const start = fromUnixTime(start_time); const end = fromUnixTime(end_time); const formatDistanceLocale: DurationToken = { - xSeconds: '{{count}}s', - xMinutes: '{{count}}m', - xHours: '{{count}}h', + xSeconds: "{{count}}s", + xMinutes: "{{count}}m", + xHours: "{{count}}h", }; const shortEnLocale = { formatDistance: (token: keyof DurationToken, count: number) => - formatDistanceLocale[token].replace('{{count}}', count.toString()), + formatDistanceLocale[token].replace("{{count}}", count.toString()), }; duration = formatDuration(intervalToDuration({ start, end }), { - format: ['hours', 'minutes', 'seconds'], + format: ["hours", "minutes", "seconds"], locale: shortEnLocale, }); } @@ -209,14 +254,18 @@ const getUTCOffset = (date: Date, timezone: string): number => { if (utcOffsetMatch) { const hours = parseInt(utcOffsetMatch[2], 10); const minutes = parseInt(utcOffsetMatch[3], 10); - return (utcOffsetMatch[1] === '+' ? 1 : -1) * (hours * 60 + minutes); + return (utcOffsetMatch[1] === "+" ? 1 : -1) * (hours * 60 + minutes); } // Otherwise, calculate offset using provided timezone - const utcDate = new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000); + const utcDate = new Date( + date.getTime() - date.getTimezoneOffset() * 60 * 1000 + ); // locale of en-CA is required for proper locale format - let iso = utcDate.toLocaleString('en-CA', { timeZone: timezone, hour12: false }).replace(', ', 'T'); - iso += `.${utcDate.getMilliseconds().toString().padStart(3, '0')}`; + let iso = utcDate + .toLocaleString("en-CA", { timeZone: timezone, hour12: false }) + .replace(", ", "T"); + iso += `.${utcDate.getMilliseconds().toString().padStart(3, "0")}`; let target = new Date(`${iso}Z`); // safari doesn't like the default format