mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 21:44:13 +03:00
refactor: add formatList
This commit is contained in:
parent
5e6ffd62a3
commit
05a607b538
@ -1,25 +1,7 @@
|
|||||||
import { TrackingDetailsSequence } from "@/types/timeline";
|
import { TrackingDetailsSequence } from "@/types/timeline";
|
||||||
import { t } from "i18next";
|
import { t } from "i18next";
|
||||||
import { getTranslatedLabel } from "./i18n";
|
import { getTranslatedLabel } from "./i18n";
|
||||||
import { capitalizeFirstLetter } from "./stringUtil";
|
import { capitalizeFirstLetter, formatList } from "./stringUtil";
|
||||||
|
|
||||||
function formatZonesList(zones: string[]): string {
|
|
||||||
if (zones.length === 0) return "";
|
|
||||||
if (zones.length === 1) return zones[0];
|
|
||||||
if (zones.length === 2) {
|
|
||||||
return t("list.two", {
|
|
||||||
0: zones[0],
|
|
||||||
1: zones[1],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const separatorWithSpace = t("list.separatorWithSpace", { ns: "common" });
|
|
||||||
const allButLast = zones.slice(0, -1).join(separatorWithSpace);
|
|
||||||
return t("list.many", {
|
|
||||||
items: allButLast,
|
|
||||||
last: zones[zones.length - 1],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getLifecycleItemDescription(
|
export function getLifecycleItemDescription(
|
||||||
lifecycleItem: TrackingDetailsSequence,
|
lifecycleItem: TrackingDetailsSequence,
|
||||||
@ -42,7 +24,7 @@ export function getLifecycleItemDescription(
|
|||||||
return t("trackingDetails.lifecycleItemDesc.entered_zone", {
|
return t("trackingDetails.lifecycleItemDesc.entered_zone", {
|
||||||
ns: "views/explore",
|
ns: "views/explore",
|
||||||
label,
|
label,
|
||||||
zones: formatZonesList(
|
zones: formatList(
|
||||||
lifecycleItem.data.zones_friendly_names ?? lifecycleItem.data.zones,
|
lifecycleItem.data.zones_friendly_names ?? lifecycleItem.data.zones,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { t } from "i18next";
|
||||||
|
|
||||||
export const capitalizeFirstLetter = (text: string): string => {
|
export const capitalizeFirstLetter = (text: string): string => {
|
||||||
return text.charAt(0).toUpperCase() + text.slice(1);
|
return text.charAt(0).toUpperCase() + text.slice(1);
|
||||||
};
|
};
|
||||||
@ -45,3 +47,29 @@ export function generateFixedHash(name: string, prefix: string = "id"): string {
|
|||||||
export function isValidId(name: string): boolean {
|
export function isValidId(name: string): boolean {
|
||||||
return /^[a-zA-Z0-9_-]+$/.test(name) && !/^\d+$/.test(name);
|
return /^[a-zA-Z0-9_-]+$/.test(name) && !/^\d+$/.test(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a list of strings into a human-readable format with proper localization.
|
||||||
|
* Handles different cases for empty, single-item, two-item, and multi-item lists.
|
||||||
|
*
|
||||||
|
* @param item - The array of strings to format
|
||||||
|
* @returns A formatted string representation of the list
|
||||||
|
*/
|
||||||
|
export function formatList(item: string[]): string {
|
||||||
|
if (item.length === 0) return "";
|
||||||
|
if (item.length === 1) return item[0];
|
||||||
|
if (item.length === 2) {
|
||||||
|
return t("list.two", {
|
||||||
|
0: item[0],
|
||||||
|
1: item[1],
|
||||||
|
ns: "common",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const separatorWithSpace = t("list.separatorWithSpace", { ns: "common" });
|
||||||
|
const allButLast = item.slice(0, -1).join(separatorWithSpace);
|
||||||
|
return t("list.many", {
|
||||||
|
items: allButLast,
|
||||||
|
last: item[item.length - 1],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@ -42,6 +42,7 @@ import { IoMdArrowRoundBack } from "react-icons/io";
|
|||||||
import { isDesktop } from "react-device-detect";
|
import { isDesktop } from "react-device-detect";
|
||||||
import { useCameraFriendlyName } from "@/hooks/use-camera-friendly-name";
|
import { useCameraFriendlyName } from "@/hooks/use-camera-friendly-name";
|
||||||
import { resolveZoneName } from "@/hooks/use-zone-friendly-name";
|
import { resolveZoneName } from "@/hooks/use-zone-friendly-name";
|
||||||
|
import { formatList } from "@/utils/stringUtil";
|
||||||
|
|
||||||
type CameraSettingsViewProps = {
|
type CameraSettingsViewProps = {
|
||||||
selectedCamera: string;
|
selectedCamera: string;
|
||||||
@ -106,27 +107,27 @@ export default function CameraSettingsView({
|
|||||||
|
|
||||||
const alertsLabels = useMemo(() => {
|
const alertsLabels = useMemo(() => {
|
||||||
return cameraConfig?.review.alerts.labels
|
return cameraConfig?.review.alerts.labels
|
||||||
? cameraConfig.review.alerts.labels
|
? formatList(
|
||||||
.map((label) =>
|
cameraConfig.review.alerts.labels.map((label) =>
|
||||||
getTranslatedLabel(
|
getTranslatedLabel(
|
||||||
label,
|
label,
|
||||||
cameraConfig?.audio?.listen?.includes(label) ? "audio" : "object",
|
cameraConfig?.audio?.listen?.includes(label) ? "audio" : "object",
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.join(", ")
|
|
||||||
: "";
|
: "";
|
||||||
}, [cameraConfig]);
|
}, [cameraConfig]);
|
||||||
|
|
||||||
const detectionsLabels = useMemo(() => {
|
const detectionsLabels = useMemo(() => {
|
||||||
return cameraConfig?.review.detections.labels
|
return cameraConfig?.review.detections.labels
|
||||||
? cameraConfig.review.detections.labels
|
? formatList(
|
||||||
.map((label) =>
|
cameraConfig.review.detections.labels.map((label) =>
|
||||||
getTranslatedLabel(
|
getTranslatedLabel(
|
||||||
label,
|
label,
|
||||||
cameraConfig?.audio?.listen?.includes(label) ? "audio" : "object",
|
cameraConfig?.audio?.listen?.includes(label) ? "audio" : "object",
|
||||||
),
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.join(", ")
|
|
||||||
: "";
|
: "";
|
||||||
}, [cameraConfig]);
|
}, [cameraConfig]);
|
||||||
|
|
||||||
@ -555,9 +556,11 @@ export default function CameraSettingsView({
|
|||||||
"cameraReview.reviewClassification.zoneObjectAlertsTips",
|
"cameraReview.reviewClassification.zoneObjectAlertsTips",
|
||||||
{
|
{
|
||||||
alertsLabels,
|
alertsLabels,
|
||||||
zone: watchedAlertsZones.map((zone) =>
|
zone: formatList(
|
||||||
|
watchedAlertsZones.map((zone) =>
|
||||||
getZoneName(zone),
|
getZoneName(zone),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
cameraName: selectCameraName,
|
cameraName: selectCameraName,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -669,9 +672,11 @@ export default function CameraSettingsView({
|
|||||||
i18nKey="cameraReview.reviewClassification.zoneObjectDetectionsTips.text"
|
i18nKey="cameraReview.reviewClassification.zoneObjectDetectionsTips.text"
|
||||||
values={{
|
values={{
|
||||||
detectionsLabels,
|
detectionsLabels,
|
||||||
zone: watchedDetectionsZones.map((zone) =>
|
zone: formatList(
|
||||||
|
watchedDetectionsZones.map((zone) =>
|
||||||
getZoneName(zone),
|
getZoneName(zone),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
cameraName: selectCameraName,
|
cameraName: selectCameraName,
|
||||||
}}
|
}}
|
||||||
ns="views/settings"
|
ns="views/settings"
|
||||||
@ -681,9 +686,11 @@ export default function CameraSettingsView({
|
|||||||
i18nKey="cameraReview.reviewClassification.zoneObjectDetectionsTips.notSelectDetections"
|
i18nKey="cameraReview.reviewClassification.zoneObjectDetectionsTips.notSelectDetections"
|
||||||
values={{
|
values={{
|
||||||
detectionsLabels,
|
detectionsLabels,
|
||||||
zone: watchedDetectionsZones.map((zone) =>
|
zone: formatList(
|
||||||
|
watchedDetectionsZones.map((zone) =>
|
||||||
getZoneName(zone),
|
getZoneName(zone),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
cameraName: selectCameraName,
|
cameraName: selectCameraName,
|
||||||
}}
|
}}
|
||||||
ns="views/settings"
|
ns="views/settings"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user