diff options
Diffstat (limited to 'packages/aml-backoffice-ui/src/route.ts')
-rw-r--r-- | packages/aml-backoffice-ui/src/route.ts | 106 |
1 files changed, 74 insertions, 32 deletions
diff --git a/packages/aml-backoffice-ui/src/route.ts b/packages/aml-backoffice-ui/src/route.ts index f515a590a..ffd54d6af 100644 --- a/packages/aml-backoffice-ui/src/route.ts +++ b/packages/aml-backoffice-ui/src/route.ts @@ -1,19 +1,42 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ import { TranslatedString } from "@gnu-taler/taler-util"; import { createHashHistory } from "history"; import { ComponentChildren, h as create, createContext, VNode } from "preact"; import { useContext, useEffect, useState } from "preact/hooks"; type ContextType = { - onChange: (listener: () => void) => VoidFunction -} -const nullChangeListener = { onChange: () => () => { } } + onChange: (listener: () => void) => VoidFunction; +}; +const nullChangeListener = { onChange: () => () => {} }; const Context = createContext<ContextType>(nullChangeListener); export const usePathChangeContext = (): ContextType => useContext(Context); -export function HashPathProvider({ children }: { children: ComponentChildren }): VNode { +export function HashPathProvider({ + children, +}: { + children: ComponentChildren; +}): VNode { const history = createHashHistory(); - return create(Context.Provider, { value: { onChange: history.listen }, children }, children) + return create( + Context.Provider, + { value: { onChange: history.listen }, children }, + children, + ); } type PageDefinition<DynamicPart extends Record<string, string>> = { @@ -42,14 +65,17 @@ export function pageDefinition<T extends Record<string, string>>( `page definition pattern ${pattern} doesn't have any parameter`, ); - const vars = patternParams.reduce((prev, cur) => { - const pName = cur.match(/(\w+)/g); + const vars = patternParams.reduce( + (prev, cur) => { + const pName = cur.match(/(\w+)/g); - //skip things like :? in the path pattern - if (!pName || !pName[0]) return prev; - const name = pName[0]; - return { ...prev, [name]: cur }; - }, {} as Record<string, string>); + //skip things like :? in the path pattern + if (!pName || !pName[0]) return prev; + const name = pName[0]; + return { ...prev, [name]: cur }; + }, + {} as Record<string, string>, + ); const f = (values: T): string => replaceAll(pattern, vars, values); f.pattern = pattern; @@ -58,19 +84,19 @@ export function pageDefinition<T extends Record<string, string>>( export type PageEntry<T = unknown> = T extends Record<string, string> ? { - url: PageDefinition<T>; - view: (props: T) => VNode; - name: TranslatedString, - Icon?: () => VNode, - } + url: PageDefinition<T>; + view: (props: T) => VNode; + name: TranslatedString; + Icon?: () => VNode; + } : T extends unknown - ? { - url: string; - view: (props: {}) => VNode; - name: TranslatedString, - Icon?: () => VNode, - } - : never; + ? { + url: string; + view: (props: {}) => VNode; + name: TranslatedString; + Icon?: () => VNode; + } + : never; export function Router({ pageList, @@ -91,27 +117,39 @@ type Location = { path: string; values: Record<string, string>; }; -export function useCurrentLocation(pageList: Array<PageEntry<any>>): Location | undefined { - const [currentLocation, setCurrentLocation] = useState<Location | null | undefined>(null); +export function useCurrentLocation( + pageList: Array<PageEntry<any>>, +): Location | undefined { + const [currentLocation, setCurrentLocation] = useState< + Location | null | undefined + >(null); const path = usePathChangeContext(); useEffect(() => { return path.onChange(() => { - const result = doSync(window.location.hash, new URLSearchParams(window.location.search), pageList); + const result = doSync( + window.location.hash, + new URLSearchParams(window.location.search), + pageList, + ); setCurrentLocation(result); }); }, []); if (currentLocation === null) { - return doSync(window.location.hash, new URLSearchParams(window.location.search), pageList); + return doSync( + window.location.hash, + new URLSearchParams(window.location.search), + pageList, + ); } return currentLocation; } export function useChangeLocation() { - const [location, setLocation] = useState(window.location.hash) - const path = usePathChangeContext() + const [location, setLocation] = useState(window.location.hash); + const path = usePathChangeContext(); useEffect(() => { return path.onChange(() => { - setLocation(window.location.hash) + setLocation(window.location.hash); }); }, []); return location; @@ -125,7 +163,11 @@ export function useChangeLocation() { * @param path * @param params */ -export function doSync(path: string, params: URLSearchParams, pageList: Array<PageEntry<any>>): Location | undefined { +export function doSync( + path: string, + params: URLSearchParams, + pageList: Array<PageEntry<any>>, +): Location | undefined { for (let idx = 0; idx < pageList.length; idx++) { const page = pageList[idx]; if (typeof page.url === "string") { |