Browse Source

Add advanced filters (#655)

* Add advanced filters

* Review edits

---------

Co-authored-by: philon- <[email protected]>
pull/670/head
Jeremy Gallant 12 months ago
committed by GitHub
parent
commit
7adbe01723
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 32
      src/components/generic/Filter/FilterControl.tsx
  2. 22
      src/components/generic/Filter/useFilterNode.test.ts
  3. 18
      src/components/generic/Filter/useFilterNode.ts
  4. 9
      src/i18n/locales/en/ui.json

32
src/components/generic/Filter/FilterControl.tsx

@ -190,10 +190,12 @@ export function FilterControl({
);
const handleBoolChange = useCallback(
<K extends keyof FilterState>(key: K, value: string) => {
const typedValue = value === ""
? undefined
: JSON.parse(value.toLowerCase());
<K extends keyof FilterState>(key: K, value: string | boolean) => {
const typedValue = value === true || value === "true"
? true
: value === false || value === "false"
? false
: undefined;
setFilterState((prev) => ({
...prev,
@ -386,6 +388,28 @@ export function FilterControl({
formatEnumLabel(Protobuf.Mesh.HardwareModel[val])}
/>
</FilterAccordionItem>
<FilterAccordionItem label={t("advanced.label")}>
<FilterToggle
label={t("hopsUnknown.label")}
filterKey="hopsUnknown"
alternativeLabels={[
t("hide.label"),
t("showOnly.label"),
]}
filterState={filterState}
onChange={handleBoolChange}
/>
<FilterToggle
label={t("showUnheard.label")}
filterKey="showUnheard"
alternativeLabels={[
t("hide.label"),
t("showOnly.label"),
]}
filterState={filterState}
onChange={handleBoolChange}
/>
</FilterAccordionItem>
</Accordion>
<button
type="button"

22
src/components/generic/Filter/useFilterNode.test.ts

@ -114,6 +114,18 @@ describe("useFilterNode", () => {
).toBe(false);
});
it("filters by hopsUnknown", () => {
expect(nodeFilter(node, { hopsUnknown: true })).toBe(false);
expect(nodeFilter(node, { hopsUnknown: false })).toBe(true);
expect(nodeFilter(node, { hopsUnknown: undefined })).toBe(true);
});
it("filters by showUnheard", () => {
expect(nodeFilter(node, { showUnheard: true })).toBe(false);
expect(nodeFilter(node, { showUnheard: false })).toBe(true);
expect(nodeFilter(node, { showUnheard: undefined })).toBe(true);
});
it("returns false when current matches defaults", () => {
expect(isFilterDirty(defaultFilterValues)).toBe(false);
});
@ -156,5 +168,15 @@ describe("useFilterNode", () => {
};
expect(isFilterDirty(modified)).toBe(true);
});
it("detects dirty boolean field (hopsUnknown)", () => {
const modified = { ...defaultFilterValues, hopsUnknown: true };
expect(isFilterDirty(modified)).toBe(true);
});
it("detects dirty boolean field (showUnheard)", () => {
const modified = { ...defaultFilterValues, showUnheard: true };
expect(isFilterDirty(modified)).toBe(true);
});
});
});

18
src/components/generic/Filter/useFilterNode.ts

@ -15,6 +15,8 @@ export type FilterState = {
voltage: [number, number];
role: Protobuf.Config.Config_DeviceConfig_Role[];
hwModel: Protobuf.Mesh.HardwareModel[];
showUnheard: boolean | undefined;
hopsUnknown: boolean | undefined;
};
const shallowEqualArray = <T>(a: T[], b: T[]): boolean => {
@ -49,6 +51,8 @@ export function useFilterNode() {
hwModel: Object.values(Protobuf.Mesh.HardwareModel).filter(
(v): v is Protobuf.Mesh.HardwareModel => typeof v === "number",
),
hopsUnknown: undefined,
showUnheard: undefined,
}),
[],
);
@ -83,6 +87,13 @@ export function useFilterNode() {
return false;
}
if (
(filterState.hopsUnknown === true && node.hopsAway !== undefined) ||
filterState.hopsUnknown === false && node.hopsAway === undefined
) {
return false;
}
const secondsAgo = Date.now() / 1000 - (node.lastHeard ?? 0);
if (
secondsAgo < filterState.lastHeard[0] ||
@ -92,6 +103,13 @@ export function useFilterNode() {
return false;
}
if (
(filterState.showUnheard === true && (node.lastHeard ?? 0) !== 0) ||
filterState.showUnheard === false && (node.lastHeard ?? 0) === 0
) {
return false;
}
if (
typeof filterState.isFavorite !== "undefined" &&
node.isFavorite !== filterState.isFavorite

9
src/i18n/locales/en/ui.json

@ -103,6 +103,9 @@
"filter": {
"label": "Filter"
},
"advanced": {
"label": "Advanced"
},
"clearInput": {
"label": "Clear input"
},
@ -152,6 +155,12 @@
"viaMqtt": {
"label": "Connected via MQTT"
},
"hopsUnknown": {
"label": "Unknown number of hops"
},
"showUnheard": {
"label": "Never heard"
},
"language": {
"label": "Language",
"changeLanguage": "Change Language"

Loading…
Cancel
Save