diff --git a/web/static/src/ts/core/utils.ts b/web/static/src/ts/core/utils.ts index c85d87ac..a0d33453 100644 --- a/web/static/src/ts/core/utils.ts +++ b/web/static/src/ts/core/utils.ts @@ -83,3 +83,23 @@ export function debounce( } }; } + +interface Tree { + children: T[]; +} + +export function findInTree>( + tree: T, + predicate: (t: T) => boolean +): T | null { + if (predicate(tree)) { + return tree; + } + for (let child of tree.children) { + let match = findInTree(child, predicate); + if (match) { + return match; + } + } + return null; +} diff --git a/web/static/tests/core/utils.test.ts b/web/static/tests/core/utils.test.ts index f604a4e9..73aac965 100644 --- a/web/static/tests/core/utils.test.ts +++ b/web/static/tests/core/utils.test.ts @@ -3,7 +3,8 @@ import { htmlTrim, idGenerator, memoize, - debounce + debounce, + findInTree } from "../../src/ts/core/utils"; describe("escape", () => { @@ -77,3 +78,16 @@ describe("debounce", () => { expect(n).toBe(1); }); }); + +describe("findInTree", () => { + test("can find stuff in tree", () => { + let tree = { + id: 1, + children: [{ id: 2, children: [] }, { id: 3, key: "hello", children: [] }] + }; + const match1 = findInTree(tree, t => t.id === 3); + expect((match1).key).toBe("hello"); + const match2 = findInTree(tree, t => t.id === 4); + expect(match2).toBe(null); + }); +});