* Fix api filter hook

cameras, labels, sub labels, plates, and zones could be parsed as numeric values rather than strings, which would break the explore filter. This change adds an optional param to the useApiFilterArgs hook to always parse keys as string[]

* fix notifications register button from being incorrectly disabled
This commit is contained in:
Josh Hawkins 2025-08-06 22:09:43 -05:00 committed by GitHub
parent 5fc030c3f6
commit b6b3178e3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 35 additions and 20 deletions

View File

@ -47,9 +47,9 @@ export default function useApiFilter<
return [filter, setFilter, searchParams];
}
export function useApiFilterArgs<
F extends FilterType,
>(): useApiFilterReturn<F> {
export function useApiFilterArgs<F extends FilterType>(
arrayKeys: string[],
): useApiFilterReturn<F> {
const [rawParams, setRawParams] = useSearchParams();
const setFilter = useCallback(
@ -64,30 +64,37 @@ export function useApiFilterArgs<
const filter: { [key: string]: unknown } = {};
rawParams.forEach((value, key) => {
const isValidNumber = /^-?\d+(\.\d+)?(?!.)/.test(value);
const isValidEventID = /^\d+\.\d+-[a-zA-Z0-9]+$/.test(value);
// always treat these keys as string[], not as a number or event id
const arrayKeySet = new Set(arrayKeys);
if (
value != "true" &&
value != "false" &&
!isValidNumber &&
!isValidEventID
) {
rawParams.forEach((value, key) => {
if (arrayKeySet.has(key)) {
filter[key] = value.includes(",") ? value.split(",") : [value];
} else {
if (value != undefined) {
try {
filter[key] = JSON.parse(value);
} catch {
filter[key] = `${value}`;
const isValidNumber = /^-?\d+(\.\d+)?(?!.)/.test(value);
const isValidEventID = /^\d+\.\d+-[a-zA-Z0-9]+$/.test(value);
if (
value != "true" &&
value != "false" &&
!isValidNumber &&
!isValidEventID
) {
filter[key] = value.includes(",") ? value.split(",") : [value];
} else {
if (value != undefined) {
try {
filter[key] = JSON.parse(value);
} catch {
filter[key] = `${value}`;
}
}
}
}
});
return filter as F;
}, [rawParams]);
}, [rawParams, arrayKeys]);
const searchParams = useMemo(() => {
if (filter == undefined || Object.keys(filter).length == 0) {

View File

@ -58,7 +58,13 @@ export default function Explore() {
const [search, setSearch] = useState("");
const [searchFilter, setSearchFilter, searchSearchParams] =
useApiFilterArgs<SearchFilter>();
useApiFilterArgs<SearchFilter>([
"cameras",
"labels",
"sub_labels",
"recognized_license_plate",
"zones",
]);
const searchTerm = useMemo(
() => searchSearchParams?.["query"] || "",

View File

@ -523,7 +523,9 @@ export default function NotificationView({
aria-label={t("notification.registerDevice")}
disabled={
(!config?.notifications.enabled &&
notificationCameras.length === 0) ||
notificationCameras.length === 0 &&
!form.watch("allEnabled") &&
form.watch("cameras").length === 0) ||
publicKey == undefined
}
onClick={() => {