mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-07 11:45:24 +03:00
reduce duplicate items and improve time format
This commit is contained in:
parent
a7f4f9919d
commit
8d143dc655
@ -47,7 +47,7 @@ export default function HistoryCard({
|
||||
<LuClock className="h-5 w-5 mr-2 inline" />
|
||||
{formatUnixTimestampToDateTime(timeline.time, {
|
||||
strftime_fmt:
|
||||
config.ui.time_format == "24hour" ? "%H:%M:%S" : "%I:%M:%S",
|
||||
config.ui.time_format == "24hour" ? "%H:%M:%S" : "%I:%M:%S %p",
|
||||
time_style: "medium",
|
||||
date_style: "medium",
|
||||
})}
|
||||
|
||||
@ -105,7 +105,10 @@ export default function PreviewThumbnailPlayer({
|
||||
);
|
||||
|
||||
let content;
|
||||
if (!relevantPreview || !visible) {
|
||||
|
||||
if (relevantPreview && !visible) {
|
||||
content = <div />;
|
||||
} else if (!relevantPreview) {
|
||||
if (isCurrentHour(startTs)) {
|
||||
content = (
|
||||
<img
|
||||
|
||||
@ -8,6 +8,7 @@ import HistoryCard from "@/components/card/HistoryCard";
|
||||
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
|
||||
import axios from "axios";
|
||||
import TimelinePlayerCard from "@/components/card/TimelinePlayerCard";
|
||||
import { getHourlyTimelineData } from "@/utils/historyUtil";
|
||||
|
||||
const API_LIMIT = 120;
|
||||
|
||||
@ -59,83 +60,7 @@ function History() {
|
||||
return [];
|
||||
}
|
||||
|
||||
const cards: CardsData = {};
|
||||
timelinePages.forEach((hourlyTimeline) => {
|
||||
Object.keys(hourlyTimeline["hours"])
|
||||
.reverse()
|
||||
.forEach((hour) => {
|
||||
const day = new Date(parseInt(hour) * 1000);
|
||||
day.setHours(0, 0, 0, 0);
|
||||
const dayKey = (day.getTime() / 1000).toString();
|
||||
const source_to_types: { [key: string]: string[] } = {};
|
||||
Object.values(hourlyTimeline["hours"][hour]).forEach((i) => {
|
||||
const time = new Date(i.timestamp * 1000);
|
||||
time.setSeconds(0);
|
||||
time.setMilliseconds(0);
|
||||
const key = `${i.source_id}-${time.getMinutes()}`;
|
||||
if (key in source_to_types) {
|
||||
source_to_types[key].push(i.class_type);
|
||||
} else {
|
||||
source_to_types[key] = [i.class_type];
|
||||
}
|
||||
});
|
||||
|
||||
if (!Object.keys(cards).includes(dayKey)) {
|
||||
cards[dayKey] = {};
|
||||
}
|
||||
cards[dayKey][hour] = {};
|
||||
Object.values(hourlyTimeline["hours"][hour]).forEach((i) => {
|
||||
const time = new Date(i.timestamp * 1000);
|
||||
const key = `${i.camera}-${time.getMinutes()}`;
|
||||
|
||||
// detail level for saving items
|
||||
// detail level determines which timeline items for each moment is returned
|
||||
// values can be normal, extra, or full
|
||||
// normal: return all items except active / attribute / gone / stationary / visible unless that is the only item.
|
||||
// extra: return all items except attribute / gone / visible unless that is the only item
|
||||
// full: return all items
|
||||
|
||||
let add = true;
|
||||
if (detailLevel == "normal") {
|
||||
if (
|
||||
source_to_types[`${i.source_id}-${time.getMinutes()}`].length >
|
||||
1 &&
|
||||
[
|
||||
"active",
|
||||
"attribute",
|
||||
"gone",
|
||||
"stationary",
|
||||
"visible",
|
||||
].includes(i.class_type)
|
||||
) {
|
||||
add = false;
|
||||
}
|
||||
} else if (detailLevel == "extra") {
|
||||
if (
|
||||
source_to_types[`${i.source_id}-${time.getMinutes()}`].length >
|
||||
1 &&
|
||||
i.class_type in ["attribute", "gone", "visible"]
|
||||
) {
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
if (key in cards[dayKey][hour]) {
|
||||
cards[dayKey][hour][key].entries.push(i);
|
||||
} else {
|
||||
cards[dayKey][hour][key] = {
|
||||
camera: i.camera,
|
||||
time: time.getTime() / 1000,
|
||||
entries: [i],
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return cards;
|
||||
return getHourlyTimelineData(timelinePages, detailLevel);
|
||||
}, [detailLevel, timelinePages]);
|
||||
|
||||
const isDone =
|
||||
@ -206,7 +131,10 @@ function History() {
|
||||
<div key={hour} ref={lastRow ? lastTimelineRef : null}>
|
||||
<Heading as="h4">
|
||||
{formatUnixTimestampToDateTime(parseInt(hour), {
|
||||
strftime_fmt: "%I:00",
|
||||
strftime_fmt:
|
||||
config.ui.time_format == "24hour"
|
||||
? "%H:00"
|
||||
: "%I:00 %p",
|
||||
time_style: "medium",
|
||||
date_style: "medium",
|
||||
})}
|
||||
@ -229,6 +157,7 @@ function History() {
|
||||
preview.end > startTs
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<HistoryCard
|
||||
key={key}
|
||||
|
||||
@ -10,6 +10,7 @@ type Card = {
|
||||
camera: string,
|
||||
time: number,
|
||||
entries: Timeline[],
|
||||
uniqueKeys: string[],
|
||||
}
|
||||
|
||||
type Preview = {
|
||||
|
||||
88
web/src/utils/historyUtil.ts
Normal file
88
web/src/utils/historyUtil.ts
Normal file
@ -0,0 +1,88 @@
|
||||
export function getHourlyTimelineData(
|
||||
timelinePages: HourlyTimeline[],
|
||||
detailLevel: string
|
||||
) {
|
||||
const cards: CardsData = {};
|
||||
timelinePages.forEach((hourlyTimeline) => {
|
||||
Object.keys(hourlyTimeline["hours"])
|
||||
.reverse()
|
||||
.forEach((hour) => {
|
||||
const day = new Date(parseInt(hour) * 1000);
|
||||
day.setHours(0, 0, 0, 0);
|
||||
const dayKey = (day.getTime() / 1000).toString();
|
||||
const source_to_types: { [key: string]: string[] } = {};
|
||||
Object.values(hourlyTimeline["hours"][hour]).forEach((i) => {
|
||||
const time = new Date(i.timestamp * 1000);
|
||||
time.setSeconds(0);
|
||||
time.setMilliseconds(0);
|
||||
const key = `${i.source_id}-${time.getMinutes()}`;
|
||||
if (key in source_to_types) {
|
||||
source_to_types[key].push(i.class_type);
|
||||
} else {
|
||||
source_to_types[key] = [i.class_type];
|
||||
}
|
||||
});
|
||||
|
||||
if (!Object.keys(cards).includes(dayKey)) {
|
||||
cards[dayKey] = {};
|
||||
}
|
||||
cards[dayKey][hour] = {};
|
||||
Object.values(hourlyTimeline["hours"][hour]).forEach((i) => {
|
||||
const time = new Date(i.timestamp * 1000);
|
||||
const minuteKey = `${i.camera}-${time.getMinutes()}`;
|
||||
const uniqueKey = `${i.source_id}-${i.class_type}`;
|
||||
|
||||
// detail level for saving items
|
||||
// detail level determines which timeline items for each moment is returned
|
||||
// values can be normal, extra, or full
|
||||
// normal: return all items except active / attribute / gone / stationary / visible unless that is the only item.
|
||||
// extra: return all items except attribute / gone / visible unless that is the only item
|
||||
// full: return all items
|
||||
|
||||
let add = true;
|
||||
if (detailLevel == "normal") {
|
||||
if (
|
||||
source_to_types[`${i.source_id}-${time.getMinutes()}`].length >
|
||||
1 &&
|
||||
["active", "attribute", "gone", "stationary", "visible"].includes(
|
||||
i.class_type
|
||||
)
|
||||
) {
|
||||
add = false;
|
||||
}
|
||||
} else if (detailLevel == "extra") {
|
||||
if (
|
||||
source_to_types[`${i.source_id}-${time.getMinutes()}`].length >
|
||||
1 &&
|
||||
i.class_type in ["attribute", "gone", "visible"]
|
||||
) {
|
||||
add = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
if (minuteKey in cards[dayKey][hour]) {
|
||||
if (
|
||||
!cards[dayKey][hour][minuteKey].uniqueKeys.includes(
|
||||
uniqueKey
|
||||
) ||
|
||||
detailLevel == "full"
|
||||
) {
|
||||
cards[dayKey][hour][minuteKey].entries.push(i);
|
||||
cards[dayKey][hour][minuteKey].uniqueKeys.push(uniqueKey);
|
||||
}
|
||||
} else {
|
||||
cards[dayKey][hour][minuteKey] = {
|
||||
camera: i.camera,
|
||||
time: time.getTime() / 1000,
|
||||
entries: [i],
|
||||
uniqueKeys: [uniqueKey],
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return cards;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user