From 6d06b52605005f4d25381fc73383c3c9e48f20f8 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sat, 11 Jun 2022 19:10:26 -0300 Subject: add testing to web components --- .../pages/home/AddingProviderScreen.stories.tsx | 61 ---- .../src/pages/home/AddingProviderScreen.tsx | 367 --------------------- .../src/pages/home/AddingProviderScreen/index.ts | 102 ++++++ .../src/pages/home/AddingProviderScreen/state.ts | 147 +++++++++ .../pages/home/AddingProviderScreen/stories.tsx | 89 +++++ .../src/pages/home/AddingProviderScreen/test.ts | 42 +++ .../src/pages/home/AddingProviderScreen/views.tsx | 304 +++++++++++++++++ .../src/pages/home/AuthenticationEditorScreen.tsx | 4 +- .../src/pages/home/SecretSelectionScreen.tsx | 10 +- .../src/pages/home/index.storiesNo.tsx | 2 +- packages/anastasis-webui/src/pages/home/index.tsx | 6 +- 11 files changed, 697 insertions(+), 437 deletions(-) delete mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx delete mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx create mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen/index.ts create mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts create mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx create mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts create mode 100644 packages/anastasis-webui/src/pages/home/AddingProviderScreen/views.tsx (limited to 'packages/anastasis-webui/src/pages') diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx deleted file mode 100644 index ce860ba29..000000000 --- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - This file is part of GNU Anastasis - (C) 2021-2022 Anastasis SARL - - GNU Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Anastasis 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - GNU Anastasis; see the file COPYING. If not, see - */ - -/** - * - * @author Sebastian Javier Marchano (sebasjm) - */ - -import { ReducerState } from "@gnu-taler/anastasis-core"; -import { createExample, reducerStatesExample } from "../../utils/index.js"; -import { AddingProviderScreen as TestedComponent } from "./AddingProviderScreen.js"; - -export default { - title: "Pages/ManageProvider", - component: TestedComponent, - args: { - order: 1, - }, - argTypes: { - onUpdate: { action: "onUpdate" }, - onBack: { action: "onBack" }, - }, -}; - -export const NewProvider = createExample(TestedComponent, { - ...reducerStatesExample.authEditing, -} as ReducerState); - -export const NewProviderWithoutProviderList = createExample(TestedComponent, { - ...reducerStatesExample.authEditing, - authentication_providers: {}, -} as ReducerState); - -export const NewSmsProvider = createExample( - TestedComponent, - { - ...reducerStatesExample.authEditing, - } as ReducerState, - { providerType: "sms" }, -); - -export const NewIBANProvider = createExample( - TestedComponent, - { - ...reducerStatesExample.authEditing, - } as ReducerState, - { providerType: "iban" }, -); diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx deleted file mode 100644 index 6aeee9e7a..000000000 --- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx +++ /dev/null @@ -1,367 +0,0 @@ -/* - This file is part of GNU Anastasis - (C) 2021-2022 Anastasis SARL - - GNU Anastasis is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Anastasis 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - GNU Anastasis; see the file COPYING. If not, see - */ -import { - AuthenticationProviderStatus, - AuthenticationProviderStatusError, - AuthenticationProviderStatusOk, -} from "@gnu-taler/anastasis-core"; -import { h, VNode } from "preact"; -import { useEffect, useRef, useState } from "preact/hooks"; -import { TextInput } from "../../components/fields/TextInput.js"; -import { useAnastasisContext } from "../../context/anastasis.js"; -import { authMethods, KnownAuthMethods } from "./authMethod/index.js"; -import { AnastasisClientFrame } from "./index.js"; - -interface Props { - providerType?: KnownAuthMethods; - onCancel: () => void; -} - -async function testProvider( - url: string, - expectedMethodType?: string, -): Promise { - try { - const response = await fetch(new URL("config", url).href); - const json = await response.json().catch((d) => ({})); - if (!("methods" in json) || !Array.isArray(json.methods)) { - throw Error( - "This provider doesn't have authentication method. Check the provider URL", - ); - } - if (!expectedMethodType) { - return; - } - let found = false; - for (let i = 0; i < json.methods.length && !found; i++) { - found = json.methods[i].type === expectedMethodType; - } - if (!found) { - throw Error( - `This provider does not support authentication method ${expectedMethodType}`, - ); - } - return; - } catch (e) { - console.log("error", e); - const error = - e instanceof Error - ? Error( - `There was an error testing this provider, try another one. ${e.message}`, - ) - : Error(`There was an error testing this provider, try another one.`); - throw error; - } -} - -export function AddingProviderScreen({ providerType, onCancel }: Props): VNode { - const reducer = useAnastasisContext(); - - const [providerURL, setProviderURL] = useState(""); - - const [error, setError] = useState(); - const [testing, setTesting] = useState(false); - - const providerLabel = providerType - ? authMethods[providerType].label - : undefined; - - const allAuthProviders = - !reducer || - !reducer.currentReducerState || - reducer.currentReducerState.reducer_type === "error" || - !reducer.currentReducerState.authentication_providers - ? {} - : reducer.currentReducerState.authentication_providers; - - const authProvidersByStatus = Object.keys(allAuthProviders).reduce( - (prev, url) => { - const p = allAuthProviders[url]; - if ( - providerLabel && - p.status === "ok" && - p.methods.findIndex((m) => m.type === providerType) !== -1 - ) { - return prev; - } - const others = prev[p.status] ? prev[p.status] : []; - others.push({ ...p, url }); - return { - ...prev, - [p.status]: others, - }; - }, - {} as Record< - AuthenticationProviderStatus["status"], - (AuthenticationProviderStatus & { url: string })[] - >, - ); - const authProviders = authProvidersByStatus["ok"].map((p) => p.url); - - console.log("rodos", allAuthProviders); - //FIXME: move this timeout logic into a hook - const timeout = useRef(undefined); - useEffect(() => { - if (timeout) window.clearTimeout(timeout.current); - timeout.current = window.setTimeout(async () => { - const url = providerURL.endsWith("/") ? providerURL : providerURL + "/"; - if (!providerURL || authProviders.includes(url)) return; - try { - setTesting(true); - await testProvider(url, providerType); - setError(""); - } catch (e) { - if (e instanceof Error) setError(e.message); - } - setTesting(false); - }, 200); - }, [providerURL, reducer]); - - async function addProvider(provider_url: string): Promise { - await reducer?.transition("add_provider", { provider_url }); - onCancel(); - } - function deleteProvider(provider_url: string): void { - reducer?.transition("delete_provider", { provider_url }); - } - - if (!reducer) { - return
no reducer in context
; - } - - if ( - !reducer.currentReducerState || - !("authentication_providers" in reducer.currentReducerState) - ) { - return
invalid state
; - } - - let errors = !providerURL ? "Add provider URL" : undefined; - let url: string | undefined; - try { - url = new URL("", providerURL).href; - } catch { - errors = "Check the URL"; - } - if (!!error && !errors) { - errors = error; - } - if (!errors && authProviders.includes(url!)) { - errors = "That provider is already known"; - } - - return ( - -
- {!providerLabel ? ( -

Add a provider url

- ) : ( -

Add a provider url for a {providerLabel} service

- )} -
- -
-

Example: https://kudos.demo.anastasis.lu

- {testing &&

Testing

} - -
- - - - -
- - {authProviders.length > 0 ? ( - !providerLabel ? ( -

Current providers

- ) : ( -

- Current providers for {providerLabel} service -

- ) - ) : !providerLabel ? ( -

No known providers, add one.

- ) : ( -

No known providers for {providerLabel} service

- )} - - {authProviders.map((k) => { - const p = allAuthProviders[k] as AuthenticationProviderStatusOk; - return ( - - ); - })} - {authProvidersByStatus["error"]?.map((k) => { - const p = k as AuthenticationProviderStatusError; - return ( - - ); - })} -
-
- ); -} -function TableRow({ - url, - info, - onDelete, -}: { - onDelete: (s: string) => void; - url: string; - info: AuthenticationProviderStatusOk; -}): VNode { - const [status, setStatus] = useState("checking"); - useEffect(function () { - testProvider(url.endsWith("/") ? url.substring(0, url.length - 1) : url) - .then(function () { - setStatus("responding"); - }) - .catch(function () { - setStatus("failed to contact"); - }); - }); - return ( -
-
-
{url}
-
-
- Business Name -
-
{info.business_name}
-
- Supported methods -
-
{info.methods.map((m) => m.type).join(",")}
-
- Maximum storage -
-
{info.storage_limit_in_megabytes} Mb
-
- Status -
-
{status}
-
-
-
- -
-
- ); -} - -function TableRowError({ - url, - info, - onDelete, -}: { - onDelete: (s: string) => void; - url: string; - info: AuthenticationProviderStatusError; -}): VNode { - const [status, setStatus] = useState("checking"); - useEffect(function () { - testProvider(url.endsWith("/") ? url.substring(0, url.length - 1) : url) - .then(function () { - setStatus("responding"); - }) - .catch(function () { - setStatus("failed to contact"); - }); - }); - return ( -
-
-
{url}
-
-
- Error -
-
{info.hint}
-
- Code -
-
{info.code}
-
- Status -
-
{status}
-
-
-
- -
-
- ); -} diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/index.ts b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/index.ts new file mode 100644 index 000000000..5d5913ffc --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/index.ts @@ -0,0 +1,102 @@ +/* + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL + + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Anastasis 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see + */ +import { AuthenticationProviderStatus } from "@gnu-taler/anastasis-core"; +import InvalidState from "../../../components/InvalidState.js"; +import NoReducer from "../../../components/NoReducer.js"; +import { compose, StateViewMap } from "../../../utils/index.js"; +import useComponentState from "./state.js"; +import { WithoutProviderType, WithProviderType } from "./views.js"; + +export type AuthProvByStatusMap = Record< + AuthenticationProviderStatus["status"], + (AuthenticationProviderStatus & { url: string })[] +> + +export type State = NoReducer | InvalidState | WithType | WithoutType; + +export interface NoReducer { + status: "no-reducer"; +} +export interface InvalidState { + status: "invalid-state"; +} + +interface CommonProps { + addProvider?: () => Promise; + deleteProvider: (url: string) => Promise; + authProvidersByStatus: AuthProvByStatusMap; + error: string | undefined; + onCancel: () => Promise; + testing: boolean; + setProviderURL: (url: string) => Promise; + providerURL: string; + errors: string | undefined; +} + +export interface WithType extends CommonProps { + status: "with-type"; + providerLabel: string; +} +export interface WithoutType extends CommonProps { + status: "without-type"; +} + +const map: StateViewMap = { + "no-reducer": NoReducer, + "invalid-state": InvalidState, + "with-type": WithProviderType, + "without-type": WithoutProviderType, +}; + +export default compose("AddingProviderScreen", useComponentState, map) + + +export async function testProvider( + url: string, + expectedMethodType?: string, +): Promise { + try { + const response = await fetch(new URL("config", url).href); + const json = await response.json().catch((d) => ({})); + if (!("methods" in json) || !Array.isArray(json.methods)) { + throw Error( + "This provider doesn't have authentication method. Check the provider URL", + ); + } + if (!expectedMethodType) { + return; + } + let found = false; + for (let i = 0; i < json.methods.length && !found; i++) { + found = json.methods[i].type === expectedMethodType; + } + if (!found) { + throw Error( + `This provider does not support authentication method ${expectedMethodType}`, + ); + } + return; + } catch (e) { + console.log("error", e); + const error = + e instanceof Error + ? Error( + `There was an error testing this provider, try another one. ${e.message}`, + ) + : Error(`There was an error testing this provider, try another one.`); + throw error; + } +} diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts new file mode 100644 index 000000000..a04c7957b --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/state.ts @@ -0,0 +1,147 @@ +/* + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL + + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Anastasis 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see + */ +import { useEffect, useRef, useState } from "preact/hooks"; +import { useAnastasisContext } from "../../../context/anastasis.js"; +import { authMethods, KnownAuthMethods } from "../authMethod/index.jsx"; +import { AuthProvByStatusMap, State, testProvider } from "./index.js"; + +interface Props { + providerType?: KnownAuthMethods; + onCancel: () => Promise; +} + +export default function useComponentState({ providerType, onCancel }: Props): State { + const reducer = useAnastasisContext(); + + const [providerURL, setProviderURL] = useState(""); + + const [error, setError] = useState(); + const [testing, setTesting] = useState(false); + + const providerLabel = providerType + ? authMethods[providerType].label + : undefined; + + const allAuthProviders = + !reducer || + !reducer.currentReducerState || + reducer.currentReducerState.reducer_type === "error" || + !reducer.currentReducerState.authentication_providers + ? {} + : reducer.currentReducerState.authentication_providers; + + const authProvidersByStatus = Object.keys(allAuthProviders).reduce( + (prev, url) => { + const p = allAuthProviders[url]; + if ( + providerLabel && + p.status === "ok" && + p.methods.findIndex((m) => m.type === providerType) !== -1 + ) { + return prev; + } + prev[p.status].push({ ...p, url }); + return prev; + }, + { "not-contacted": [], disabled: [], error: [], ok: [] } as AuthProvByStatusMap, + ); + const authProviders = authProvidersByStatus["ok"].map((p) => p.url); + + //FIXME: move this timeout logic into a hook + const timeout = useRef | undefined>(undefined); + useEffect(() => { + if (timeout.current) clearTimeout(timeout.current); + timeout.current = setTimeout(async () => { + const url = providerURL.endsWith("/") ? providerURL : providerURL + "/"; + if (!providerURL || authProviders.includes(url)) return; + try { + setTesting(true); + await testProvider(url, providerType); + setError(""); + } catch (e) { + if (e instanceof Error) setError(e.message); + } + setTesting(false); + }, 200); + }, [providerURL, reducer]); + + if (!reducer) { + return { + status: "no-reducer", + }; + } + + if ( + !reducer.currentReducerState || + !("authentication_providers" in reducer.currentReducerState) + ) { + return { + status: "invalid-state", + }; + } + + const addProvider = async (provider_url: string): Promise => { + await reducer.transition("add_provider", { provider_url }); + onCancel(); + } + const deleteProvider = async (provider_url: string): Promise => { + reducer.transition("delete_provider", { provider_url }); + } + + let errors = !providerURL ? "Add provider URL" : undefined; + let url: string | undefined; + try { + url = new URL("", providerURL).href; + } catch { + errors = "Check the URL"; + } + const _url = url + + if (!!error && !errors) { + errors = error; + } + if (!errors && authProviders.includes(url!)) { + errors = "That provider is already known"; + } + + const commonState = { + addProvider: !_url ? undefined : async () => addProvider(_url), + deleteProvider: async (url: string) => deleteProvider(url), + allAuthProviders, + authProvidersByStatus, + onCancel, + providerURL, + testing, + setProviderURL: async (s: string) => setProviderURL(s), + errors, + error, + } + + if (!providerLabel) { + return { + status: "without-type", + ...commonState + } + } else { + return { + status: "with-type", + providerLabel, + ...commonState + } + } + +} + diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx new file mode 100644 index 000000000..6d8a634d5 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/stories.tsx @@ -0,0 +1,89 @@ +/* + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL + + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Anastasis 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ + +import { AuthenticationProviderStatusOk } from "@gnu-taler/anastasis-core"; +import { createExampleWithoutAnastasis } from "../../../utils/index.jsx"; +import { WithoutProviderType, WithProviderType } from "./views.jsx"; + +export default { + title: "Pages/ManageProvider", + args: { + order: 1, + }, + argTypes: { + onUpdate: { action: "onUpdate" }, + onBack: { action: "onBack" }, + }, +}; + +export const NewProvider = createExampleWithoutAnastasis(WithoutProviderType, { + authProvidersByStatus: { + ok: [ + { + business_name: "X provider", + status: "ok", + storage_limit_in_megabytes: 5, + methods: [ + { + type: "question", + usage_fee: "KUDOS:1", + }, + ], + url: "", + } as AuthenticationProviderStatusOk & { url: string }, + ], + "not-contacted": [], + disabled: [], + error: [], + }, +}); + +export const NewProviderWithoutProviderList = createExampleWithoutAnastasis( + WithoutProviderType, + { + authProvidersByStatus: { + ok: [], + "not-contacted": [], + disabled: [], + error: [], + }, + }, +); + +export const NewSmsProvider = createExampleWithoutAnastasis(WithProviderType, { + authProvidersByStatus: { + ok: [], + "not-contacted": [], + disabled: [], + error: [], + }, + providerLabel: "sms", +}); + +export const NewIBANProvider = createExampleWithoutAnastasis(WithProviderType, { + authProvidersByStatus: { + ok: [], + "not-contacted": [], + disabled: [], + error: [], + }, + providerLabel: "IBAN", +}); diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts new file mode 100644 index 000000000..d051d7c0b --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/test.ts @@ -0,0 +1,42 @@ +/* + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL + + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Anastasis 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ + +import { expect } from "chai"; +import { mountHook } from "../../../test-utils.js"; +import useComponentState from "./state.js"; + +describe("AddingProviderScreen states", () => { + it("should have status 'no-balance' when balance is empty", async () => { + const { getLastResultOrThrow, waitNextUpdate, assertNoPendingUpdate } = + mountHook(() => + useComponentState({ onCancel: async () => { null } }), + ); + + { + const { status } = getLastResultOrThrow(); + expect(status).equal("no-reducer"); + } + + await assertNoPendingUpdate(); + + }); + +}); diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen/views.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/views.tsx new file mode 100644 index 000000000..bb1283a82 --- /dev/null +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen/views.tsx @@ -0,0 +1,304 @@ +/* + This file is part of GNU Anastasis + (C) 2021-2022 Anastasis SARL + + GNU Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Anastasis 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + GNU Anastasis; see the file COPYING. If not, see + */ +import { + AuthenticationProviderStatusError, + AuthenticationProviderStatusOk, +} from "@gnu-taler/anastasis-core"; +import { h, VNode } from "preact"; +import { useEffect, useState } from "preact/hooks"; +import { TextInput } from "../../../components/fields/TextInput.js"; +import { AnastasisClientFrame } from "../index.js"; +import { testProvider, WithoutType, WithType } from "./index.js"; + +export function WithProviderType(props: WithType): VNode { + return ( + +
+

Add a provider url for a {props.providerLabel} service

+
+ +
+

Example: https://kudos.demo.anastasis.lu

+ {props.testing &&

Testing

} + +
+ + + + +
+ + {props.authProvidersByStatus["ok"].length > 0 ? ( +

+ Current providers for {props.providerLabel} service +

+ ) : ( +

+ No known providers for {props.providerLabel} service +

+ )} + + {props.authProvidersByStatus["ok"].map((k, i) => { + const p = k as AuthenticationProviderStatusOk; + return ( + + ); + })} +

Providers with errors

+ {props.authProvidersByStatus["error"].map((k, i) => { + const p = k as AuthenticationProviderStatusError; + return ( + + ); + })} +
+
+ ); +} + +export function WithoutProviderType(props: WithoutType): VNode { + return ( + +
+

Add a provider url

+
+ +
+

Example: https://kudos.demo.anastasis.lu

+ {props.testing &&

Testing

} + +
+ + + + +
+ + {props.authProvidersByStatus["ok"].length > 0 ? ( +

Current providers

+ ) : ( +

No known providers, add one.

+ )} + + {props.authProvidersByStatus["ok"].map((k, i) => { + const p = k as AuthenticationProviderStatusOk; + return ( + + ); + })} +

Providers with errors

+ {props.authProvidersByStatus["error"].map((k, i) => { + const p = k as AuthenticationProviderStatusError; + return ( + + ); + })} +
+
+ ); +} + +function TableRow({ + url, + info, + onDelete, +}: { + onDelete: (s: string) => Promise; + url: string; + info: AuthenticationProviderStatusOk; +}): VNode { + const [status, setStatus] = useState("checking"); + useEffect(function () { + testProvider(url.endsWith("/") ? url.substring(0, url.length - 1) : url) + .then(function () { + setStatus("responding"); + }) + .catch(function () { + setStatus("failed to contact"); + }); + }); + return ( +
+
+
{url}
+
+
+ Business Name +
+
{info.business_name}
+
+ Supported methods +
+
{info.methods.map((m) => m.type).join(",")}
+
+ Maximum storage +
+
{info.storage_limit_in_megabytes} Mb
+
+ Status +
+
{status}
+
+
+
+ +
+
+ ); +} + +function TableRowError({ + url, + info, + onDelete, +}: { + onDelete: (s: string) => void; + url: string; + info: AuthenticationProviderStatusError; +}): VNode { + const [status, setStatus] = useState("checking"); + useEffect(function () { + testProvider(url.endsWith("/") ? url.substring(0, url.length - 1) : url) + .then(function () { + setStatus("responding"); + }) + .catch(function () { + setStatus("failed to contact"); + }); + }); + return ( +
+
+
{url}
+
+
+ Error +
+
{info.hint}
+
+ Code +
+
{info.code}
+
+ Status +
+
{status}
+
+
+
+ +
+
+ ); +} diff --git a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx index f93ecfd8a..3018f88dd 100644 --- a/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/AuthenticationEditorScreen.tsx @@ -17,7 +17,7 @@ import { AuthMethod, ReducerStateBackup } from "@gnu-taler/anastasis-core"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; import { useAnastasisContext } from "../../context/anastasis.js"; -import { AddingProviderScreen } from "./AddingProviderScreen.js"; +import AddingProviderScreen from "./AddingProviderScreen/index.js"; import { authMethods, AuthMethodSetupProps, @@ -84,7 +84,7 @@ export function AuthenticationEditorScreen(): VNode { if (manageProvider !== undefined) { return ( setManageProvider(undefined)} + onCancel={async () => setManageProvider(undefined)} providerType={ isKnownAuthMethods(manageProvider) ? manageProvider : undefined } diff --git a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx index 7d92bcd2c..11271aaa5 100644 --- a/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/SecretSelectionScreen.tsx @@ -22,7 +22,7 @@ import { useEffect, useState } from "preact/hooks"; import { AsyncButton } from "../../components/AsyncButton.js"; import { PhoneNumberInput } from "../../components/fields/NumberInput.js"; import { useAnastasisContext } from "../../context/anastasis.js"; -import { AddingProviderScreen } from "./AddingProviderScreen.js"; +import AddingProviderScreen from "./AddingProviderScreen/index.js"; import { AnastasisClientFrame } from "./index.js"; export function SecretSelectionScreen(): VNode { @@ -54,7 +54,9 @@ export function SecretSelectionScreen(): VNode { const recoveryDocument = reducer.currentReducerState.recovery_document; if (manageProvider) { - return setManageProvider(false)} />; + return ( + setManageProvider(false)} /> + ); } if (reducer.discoveryState.state === "none") { @@ -220,7 +222,9 @@ export function OldSecretSelectionScreen(): VNode { } if (manageProvider) { - return setManageProvider(false)} />; + return ( + setManageProvider(false)} /> + ); } const providerInfo = provs[ diff --git a/packages/anastasis-webui/src/pages/home/index.storiesNo.tsx b/packages/anastasis-webui/src/pages/home/index.storiesNo.tsx index 1c47b57ee..0d01a5c89 100644 --- a/packages/anastasis-webui/src/pages/home/index.storiesNo.tsx +++ b/packages/anastasis-webui/src/pages/home/index.storiesNo.tsx @@ -19,7 +19,7 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import * as a23 from "./AddingProviderScreen.stories.js"; +import * as a23 from "./AddingProviderScreen/stories.js"; import * as a28 from "./AttributeEntryScreen.stories.js"; import * as a18 from "./AuthenticationEditorScreen.stories.js"; import * as a8 from "./authMethod/AuthMethodEmailSetup.stories.js"; diff --git a/packages/anastasis-webui/src/pages/home/index.tsx b/packages/anastasis-webui/src/pages/home/index.tsx index 57f935bd6..25d9c63d9 100644 --- a/packages/anastasis-webui/src/pages/home/index.tsx +++ b/packages/anastasis-webui/src/pages/home/index.tsx @@ -168,9 +168,9 @@ export function AnastasisClientFrame(props: AnastasisClientFrameProps): VNode { window.removeEventListener("popstate", browserOnBackButton); }; }, []); - if (!reducer) { - return

Fatal: Reducer must be in context.

; - } + // if (!reducer) { + // return

Fatal: Reducer must be in context.

; + // } return ( -- cgit v1.2.3