diff options
author | Sebastian <sebasjm@gmail.com> | 2023-11-18 09:55:23 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2023-11-18 09:55:23 -0300 |
commit | 7ed3e78f790837479fc2bb2eb6ddc40c78ce59b5 (patch) | |
tree | d914627537315e15240034fed441239448dfff07 /packages/aml-backoffice-ui/src | |
parent | c797d551d9716924120d6ce6f270793c7bb5a4f9 (diff) |
sync page with history
Diffstat (limited to 'packages/aml-backoffice-ui/src')
-rw-r--r-- | packages/aml-backoffice-ui/src/Dashboard.tsx | 83 | ||||
-rw-r--r-- | packages/aml-backoffice-ui/src/hooks/useOfficer.ts | 47 | ||||
-rw-r--r-- | packages/aml-backoffice-ui/src/hooks/useSettings.ts | 10 | ||||
-rw-r--r-- | packages/aml-backoffice-ui/src/route.ts | 77 |
4 files changed, 93 insertions, 124 deletions
diff --git a/packages/aml-backoffice-ui/src/Dashboard.tsx b/packages/aml-backoffice-ui/src/Dashboard.tsx index d111ae145..b813f83d5 100644 --- a/packages/aml-backoffice-ui/src/Dashboard.tsx +++ b/packages/aml-backoffice-ui/src/Dashboard.tsx @@ -77,75 +77,6 @@ const versionText = VERSION * writing text with the correct format */ -const pageList = Object.values(Pages); -function LeftMenu() { - const currentLocation = useCurrentLocation(pageList); - - return ( - <nav class="flex flex-1 flex-col"> - <ul role="list" class="flex flex-1 flex-col gap-y-7"> - <li> - <ul role="list" class="-mx-2 space-y-1"> - <li> - <a - href={Pages.cases.url} - class={classNames( - Pages.cases.url === currentLocation?.path - ? "bg-indigo-700 text-white" - : "text-indigo-200 hover:text-white hover:bg-indigo-700", - "group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold", - )} - > - {/* <InformationCircleIcon - class={classNames( - Pages.cases.url === currentLocation?.path - ? "text-white" - : "text-indigo-200 group-hover:text-white", - "h-6 w-6 shrink-0", - )} - aria-hidden="true" - /> */} - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> - <path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" /> - </svg> - - Cases - </a> - </li> - <li> - <a - href={Pages.officer.url} - class={classNames( - Pages.officer.url === currentLocation?.path - ? "bg-indigo-700 text-white" - : "text-indigo-200 hover:text-white hover:bg-indigo-700", - "group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold", - )} - > - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"> - <path stroke-linecap="round" stroke-linejoin="round" d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" /> - </svg> - - {/* <UserIcon - class={classNames( - Pages.officer.url === currentLocation?.path - ? "text-white" - : "text-indigo-200 group-hover:text-white", - "h-6 w-6 shrink-0", - )} - aria-hidden="true" - /> */} - Account - </a> - </li> - </ul> - </li> - </ul> - </nav> - ); -} - - export function ExchangeAmlFrame({ children, }: { @@ -238,21 +169,21 @@ function Navigation(): VNode { ] const location = useChangeLocation(); return ( - <div class="flex gap-y-5 w-48 bg-indigo-600 divide-y rounded-r-lg divide-cyan-800 overflow-y-auto overflow-x-clip"> + <div class="hidden sm:block w-48 min-w-min bg-indigo-600 divide-y rounded-r-lg divide-cyan-800 overflow-y-auto overflow-x-clip"> <nav class="flex flex-1 flex-col mx-4 mt-4 mb-2"> <ul role="list" class="flex flex-1 flex-col gap-y-7"> <li> <ul role="list" class="-mx-2 space-y-1"> {pageList.map(p => { - + return <li> - {/* <!-- Current: "bg-indigo-700 text-white", - Default: "text-indigo-200 hover:text-white hover:bg-indigo-700" --> */} - <a href={p.url} data-selected={location == p.url} + <a href={p.url} data-selected={location == p.url} class="data-[selected=true]:bg-indigo-700 data-[selected=true]:text-white text-indigo-200 hover:text-white hover:bg-indigo-700 group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold"> - { p.Icon && <p.Icon />} - {p.name} + {p.Icon && <p.Icon />} + <span class="hidden md:inline"> + {p.name} + </span> </a> </li> diff --git a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts index 0747170e8..64cf79cc9 100644 --- a/packages/aml-backoffice-ui/src/hooks/useOfficer.ts +++ b/packages/aml-backoffice-ui/src/hooks/useOfficer.ts @@ -3,10 +3,15 @@ import { Codec, LockedAccount, OfficerAccount, + OfficerId, + SigningKey, buildCodecForObject, codecForAbsoluteTime, codecForString, + codecOptional, createNewOfficerAccount, + decodeCrock, + encodeCrock, unlockOfficerAccount, } from "@gnu-taler/taler-util"; import { @@ -14,6 +19,7 @@ import { useLocalStorage, useMemoryStorage, } from "@gnu-taler/web-util/browser"; +import { useMemo } from "preact/hooks"; export interface Officer { account: LockedAccount; @@ -22,6 +28,17 @@ export interface Officer { const codecForLockedAccount = codecForString() as Codec<LockedAccount>; +type OfficerAccountString = { + id: string, + strKey: string; +} + +export const codecForOfficerAccount = (): Codec<OfficerAccountString> => + buildCodecForObject<OfficerAccountString>() + .property("id", codecForString()) // FIXME + .property("strKey", codecForString()) // FIXME + .build("OfficerAccount"); + export const codecForOfficer = (): Codec<Officer> => buildCodecForObject<Officer>() .property("account", codecForLockedAccount) // FIXME @@ -47,26 +64,41 @@ interface OfficerReady { } const OFFICER_KEY = buildStorageKey("officer", codecForOfficer()); +const DEV_ACCOUNT_KEY = buildStorageKey("account-dev", codecForOfficerAccount()); const ACCOUNT_KEY = "account"; export function useOfficer(): OfficerState { - const accountStorage = useMemoryStorage<OfficerAccount>(ACCOUNT_KEY); - const officerStorage = useLocalStorage(OFFICER_KEY); + // dev account, is save when reloaded. + const accountStorage = useLocalStorage(DEV_ACCOUNT_KEY); + const account = useMemo(() => { + if (!accountStorage.value) return undefined + return { + id: accountStorage.value.id as OfficerId, + signingKey: decodeCrock(accountStorage.value.strKey) as SigningKey + } + }, [accountStorage.value]) + + + // const accountStorage = useMemoryStorage<OfficerAccount>(ACCOUNT_KEY); + // const account = accountStorage.value; + const officerStorage = useLocalStorage(OFFICER_KEY); const officer = officerStorage.value; - const account = accountStorage.value; + if (officer === undefined) { return { state: "not-found", create: async (pwd: string) => { - const { id, safe, signingKey } = await createNewOfficerAccount(pwd); + const { id, safe, signingKey } = await createNewOfficerAccount(pwd); officerStorage.update({ account: safe, when: AbsoluteTime.now(), }); - accountStorage.update({ id, signingKey }); + // accountStorage.update({ id, signingKey }); + const strKey = encodeCrock(signingKey) + accountStorage.update({id, strKey }) }, }; } @@ -79,14 +111,15 @@ export function useOfficer(): OfficerState { }, tryUnlock: async (pwd: string) => { const ac = await unlockOfficerAccount(officer.account, pwd); - accountStorage.update(ac); + // accountStorage.update(ac); + accountStorage.update({id: ac.id, strKey: encodeCrock(ac.signingKey)}) }, }; } return { state: "ready", - account: account, + account, lock: () => { accountStorage.reset(); }, diff --git a/packages/aml-backoffice-ui/src/hooks/useSettings.ts b/packages/aml-backoffice-ui/src/hooks/useSettings.ts index 52f6f1614..f1610576e 100644 --- a/packages/aml-backoffice-ui/src/hooks/useSettings.ts +++ b/packages/aml-backoffice-ui/src/hooks/useSettings.ts @@ -27,25 +27,29 @@ import { buildStorageKey, useLocalStorage, useTranslationContext } from "@gnu-ta interface Settings { allowInsecurePassword: boolean; + keepSessionAfterReload: boolean; } export function getAllBooleanSettings(): Array<keyof Settings> { - return ["allowInsecurePassword"] + return ["allowInsecurePassword", "keepSessionAfterReload"] } export function getLabelForSetting(k: keyof Settings, i18n: ReturnType<typeof useTranslationContext>["i18n"]): TranslatedString { switch (k) { case "allowInsecurePassword": return i18n.str`Allow Insecure password` + case "keepSessionAfterReload": return i18n.str`Keep session after reload` } } export const codecForSettings = (): Codec<Settings> => buildCodecForObject<Settings>() - .property("allowInsecurePassword", (codecForBoolean())) - .build("Settings"); + .property("allowInsecurePassword", (codecForBoolean())) + .property("keepSessionAfterReload", (codecForBoolean())) + .build("Settings"); const defaultSettings: Settings = { allowInsecurePassword: false, + keepSessionAfterReload: false, }; const EXCHANGE_SETTINGS_KEY = buildStorageKey( diff --git a/packages/aml-backoffice-ui/src/route.ts b/packages/aml-backoffice-ui/src/route.ts index 9176ab5e4..091b92d5c 100644 --- a/packages/aml-backoffice-ui/src/route.ts +++ b/packages/aml-backoffice-ui/src/route.ts @@ -79,48 +79,17 @@ type Location = { path: string; values: Record<string, string>; }; -export function useCurrentLocation(pageList: Array<PageEntry<any>>) { - const [currentLocation, setCurrentLocation] = useState<Location>(); - /** - * Search path in the pageList - * get the values from the path found - * add params from searchParams - * - * @param path - * @param params - */ - function doSync(path: string, params: URLSearchParams) { - let result: typeof currentLocation; - for (let idx = 0; idx < pageList.length; idx++) { - const page = pageList[idx]; - if (typeof page.url === "string") { - if (page.url === path) { - const values: Record<string, string> = {}; - params.forEach((v, k) => { - values[k] = v; - }); - result = { page, values, path }; - break; - } - } else { - const values = doestUrlMatchToRoute(path, page.url.pattern); - if (values !== undefined) { - params.forEach((v, k) => { - values[k] = v; - }); - result = { page, values, path }; - break; - } - } - } - setCurrentLocation(result); - } +export function useCurrentLocation(pageList: Array<PageEntry<any>>): Location | undefined { + const [currentLocation, setCurrentLocation] = useState<Location | null | undefined>(null); useEffect(() => { - doSync(window.location.hash, new URLSearchParams(window.location.search)); return history.listen(() => { - doSync(window.location.hash, new URLSearchParams(window.location.search)); + 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 currentLocation; } @@ -134,6 +103,38 @@ export function useChangeLocation() { return location; } +/** + * Search path in the pageList + * get the values from the path found + * add params from searchParams + * + * @param path + * @param params + */ +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") { + if (page.url === path) { + const values: Record<string, string> = {}; + params.forEach((v, k) => { + values[k] = v; + }); + return { page, values, path }; + } + } else { + const values = doestUrlMatchToRoute(path, page.url.pattern); + if (values !== undefined) { + params.forEach((v, k) => { + values[k] = v; + }); + return { page, values, path }; + } + } + } + return undefined; +} + function doestUrlMatchToRoute( url: string, route: string, |