diff options
author | Sebastian <sebasjm@gmail.com> | 2021-11-08 15:33:41 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-11-08 15:33:41 -0300 |
commit | c898eae296b21e7ca3be7b2fd524d639f492b337 (patch) | |
tree | 60099f369bf6014a0f1b3ac05bc179eb4fd26fe3 | |
parent | bc806e7b51bc3f786ccde6efcc9111b8da8bb438 (diff) |
manage provider screen
-rw-r--r-- | packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx | 4 | ||||
-rw-r--r-- | packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx | 164 |
2 files changed, 123 insertions, 45 deletions
diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx index d290a6602..60261bd0d 100644 --- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.stories.tsx @@ -25,10 +25,10 @@ import { AddingProviderScreen as TestedComponent } from './AddingProviderScreen' export default { - title: 'Pages/backup/AuthorizationMethod/AddingProvider', + title: 'Pages/ManageProvider', component: TestedComponent, args: { - order: 4, + order: 1, }, argTypes: { onUpdate: { action: 'onUpdate' }, diff --git a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx index 9c83da49e..d2d22374e 100644 --- a/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx +++ b/packages/anastasis-webui/src/pages/home/AddingProviderScreen.tsx @@ -1,11 +1,8 @@ -/* eslint-disable @typescript-eslint/camelcase */ -import { - encodeCrock, - stringToBytes -} from "@gnu-taler/taler-util"; +import { AuthenticationProviderStatusOk } from "anastasis-core"; import { h, VNode } from "preact"; -import { useLayoutEffect, useRef, useState } from "preact/hooks"; +import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks"; import { TextInput } from "../../components/fields/TextInput"; +import { useAnastasisContext } from "../../context/anastasis"; import { authMethods, KnownAuthMethods } from "./authMethod"; import { AnastasisClientFrame } from "./index"; @@ -13,38 +10,70 @@ interface Props { providerType?: KnownAuthMethods; cancel: () => void; } + + +async function testProvider(url: string, expectedMethodType?: string): Promise<void> { + try { + const response = await fetch(`${url}/config`) + 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, cancel }: Props): VNode { + const reducer = useAnastasisContext(); + const [providerURL, setProviderURL] = useState(""); const [error, setError] = useState<string | undefined>() + const [testing, setTesting] = useState(false) const providerLabel = providerType ? authMethods[providerType].label : undefined - function testProvider(): void { - setError(undefined) + //FIXME: move this timeout logic into a hook + const timeout = useRef<number | undefined>(undefined); + useEffect(() => { + if (timeout) window.clearTimeout(timeout.current) + timeout.current = window.setTimeout(async () => { + const url = providerURL.endsWith('/') ? providerURL.substring(0, providerURL.length - 1) : providerURL + if (!url) return; + try { + setTesting(true) + await testProvider(url, providerType) + // this is use as tested but everything when ok + // undefined will mean that the field is not dirty + setError("") + } catch (e) { + console.log("tuvieja", e) + if (e instanceof Error) setError(e.message) + } + setTesting(false) + }, 1000); + }, [providerURL]) - fetch(`${providerURL}/config`) - .then(r => r.json().catch(d => ({}))) - .then(r => { - if (!("methods" in r) || !Array.isArray(r.methods)) { - setError("This provider doesn't have authentication method. Check the provider URL") - return; - } - if (!providerLabel) { - setError("") - return - } - let found = false - for (let i = 0; i < r.methods.length && !found; i++) { - found = r.methods[i].type !== providerType - } - if (!found) { - setError(`This provider does not support authentication method ${providerLabel}`) - } - }) - .catch(e => { - setError(`There was an error testing this provider, try another one. ${e.message}`) - }) + if (!reducer) { + return <div>no reducer in context</div>; } + function addProvider(): void { // addAuthMethod({ // authentication_method: { @@ -54,10 +83,6 @@ export function AddingProviderScreen({ providerType, cancel }: Props): VNode { // }, // }); } - const inputRef = useRef<HTMLInputElement>(null); - useLayoutEffect(() => { - inputRef.current?.focus(); - }, []); let errors = !providerURL ? 'Add provider URL' : undefined try { @@ -69,14 +94,25 @@ export function AddingProviderScreen({ providerType, cancel }: Props): VNode { errors = error } + if (!reducer.currentReducerState || !("authentication_providers" in reducer.currentReducerState)) { + return <div>invalid state</div> + } + + const authProviders = reducer.currentReducerState.authentication_providers || {} + return ( <AnastasisClientFrame hideNav - title={!providerLabel ? `Backup: Adding a provider` : `Backup: Adding a ${providerLabel} provider`} + title="Backup: Manage providers" hideNext={errors}> <div> - <p> - Add a provider url {errors} - </p> + {!providerLabel ? + <p> + Add a provider url + </p> : + <p> + Add a provider url for a {providerLabel} service + </p> + } <div class="container"> <TextInput label="Provider URL" @@ -84,18 +120,60 @@ export function AddingProviderScreen({ providerType, cancel }: Props): VNode { grabFocus bind={[providerURL, setProviderURL]} /> </div> + <p class="block"> + Example: https://kudos.demo.anastasis.lu + </p> + + {testing && <p class="block has-text-info">Testing</p>} {!!error && <p class="block has-text-danger">{error}</p>} {error === "" && <p class="block has-text-success">This provider worked!</p>} - <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}> - <button class="button" onClick={testProvider}>TEST</button> - </div> - <div style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}> + + <div class="block" style={{ marginTop: '2em', display: 'flex', justifyContent: 'space-between' }}> <button class="button" onClick={cancel}>Cancel</button> <span data-tooltip={errors}> - <button class="button is-info" disabled={errors !== undefined} onClick={addProvider}>Add</button> + <button class="button is-info" disabled={error !== "" || testing} onClick={addProvider}>Add</button> </span> </div> + + <p class="subtitle"> + Current providers + </p> + {/* <table class="table"> */} + {Object.keys(authProviders).map(k => { + const p = authProviders[k] + if (("currency" in p)) { + return <TableRow url={k} info={p} /> + } + } + )} + {/* </table> */} </div> </AnastasisClientFrame> ); } +function TableRow({ url, info }: { url: string, info: AuthenticationProviderStatusOk }) { + 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 <div class="box" style={{ display: 'flex', justifyContent: 'space-between' }}> + <div> + <div class="subtitle">{url}</div> + <dl> + <dt><b>Business Name</b></dt> + <dd>{info.business_name}</dd> + <dt><b>Supported methods</b></dt> + <dd>{info.methods.map(m => m.type).join(',')}</dd> + <dt><b>Maximum storage</b></dt> + <dd>{info.storage_limit_in_megabytes} Mb</dd> + <dt><b>Status</b></dt> + <dd>{status}</dd> + </dl> + </div> + <div class="block" style={{ marginTop: 'auto', marginBottom: 'auto', display: 'flex', justifyContent: 'space-between', flexDirection: 'column' }}> + <button class="button is-danger" >Remove</button> + </div> + </div> +}
\ No newline at end of file |