From 1bb887037666783c8a9da9d0af88765f24229bd1 Mon Sep 17 00:00:00 2001 From: ng <�> Date: Sun, 25 Sep 2022 16:04:31 +0200 Subject: fix: 🚨 Only use curlys when multiple statements in block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/bank/package.json | 3 +- packages/bank/src/components/AsyncButton.tsx | 8 +- packages/bank/src/components/FileButton.tsx | 4 +- packages/bank/src/components/fields/DateInput.tsx | 8 +- packages/bank/src/components/fields/EmailInput.tsx | 8 +- packages/bank/src/components/fields/FileInput.tsx | 8 +- packages/bank/src/components/fields/ImageInput.tsx | 8 +- .../bank/src/components/fields/NumberInput.tsx | 8 +- packages/bank/src/components/fields/TextInput.tsx | 8 +- packages/bank/src/components/picker/DatePicker.tsx | 20 +- .../bank/src/components/picker/DurationPicker.tsx | 4 +- packages/bank/src/context/translation.ts | 4 +- packages/bank/src/hooks/index.ts | 24 +- packages/bank/src/i18n/index.tsx | 36 +- packages/bank/src/pages/home/index.tsx | 438 +++++++++++---------- 15 files changed, 310 insertions(+), 279 deletions(-) (limited to 'packages') diff --git a/packages/bank/package.json b/packages/bank/package.json index e844aa1..f50ea78 100644 --- a/packages/bank/package.json +++ b/packages/bank/package.json @@ -28,7 +28,8 @@ "@typescript-eslint/ban-ts-comment": [1], "quotes": [2, "single", {"allowTemplateLiterals": true,"avoidEscape": false}], "indent": [2,2], - "prefer-arrow-callback": [2, {"allowNamedFunctions": false, "allowUnboundThis": true}] + "prefer-arrow-callback": [2, {"allowNamedFunctions": false, "allowUnboundThis": true}], + "curly": [2,"multi"] } }, "dependencies": { diff --git a/packages/bank/src/components/AsyncButton.tsx b/packages/bank/src/components/AsyncButton.tsx index 6edd01a..0c43056 100644 --- a/packages/bank/src/components/AsyncButton.tsx +++ b/packages/bank/src/components/AsyncButton.tsx @@ -44,17 +44,17 @@ export function AsyncButton({ const buttonRef = useRef(null); useLayoutEffect(() => { - if (grabFocus) { + if (grabFocus) buttonRef.current?.focus(); - } + }, [grabFocus]); // if (isSlow) { // return ; // } - if (isLoading) { + if (isLoading) return ; - } + return ( diff --git a/packages/bank/src/components/FileButton.tsx b/packages/bank/src/components/FileButton.tsx index 10ff984..dba86cc 100644 --- a/packages/bank/src/components/FileButton.tsx +++ b/packages/bank/src/components/FileButton.tsx @@ -27,9 +27,9 @@ export function FileButton(props: Props): VNode { type="file" onChange={(e) => { const f: FileList | null = e.currentTarget.files; - if (!f || f.length != 1) { + if (!f || f.length != 1) return props.onChange(undefined); - } + console.log(f); if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { setSizeError(true); diff --git a/packages/bank/src/components/fields/DateInput.tsx b/packages/bank/src/components/fields/DateInput.tsx index 75c7a87..06ec4b6 100644 --- a/packages/bank/src/components/fields/DateInput.tsx +++ b/packages/bank/src/components/fields/DateInput.tsx @@ -16,9 +16,9 @@ export interface DateInputProps { export function DateInput(props: DateInputProps): VNode { const inputRef = useRef(null); useLayoutEffect(() => { - if (props.grabFocus) { + if (props.grabFocus) inputRef.current?.focus(); - } + }, [props.grabFocus]); const [opened, setOpened] = useState(false); @@ -46,9 +46,9 @@ export function DateInput(props: DateInputProps): VNode { class={showError ? 'input is-danger' : 'input'} value={value} onKeyPress={(e) => { - if (e.key === 'Enter' && props.onConfirm) { + if (e.key === 'Enter' && props.onConfirm) props.onConfirm() - } + }} onInput={(e) => { const text = e.currentTarget.value; diff --git a/packages/bank/src/components/fields/EmailInput.tsx b/packages/bank/src/components/fields/EmailInput.tsx index c643083..8b64264 100644 --- a/packages/bank/src/components/fields/EmailInput.tsx +++ b/packages/bank/src/components/fields/EmailInput.tsx @@ -14,9 +14,9 @@ export interface TextInputProps { export function EmailInput(props: TextInputProps): VNode { const inputRef = useRef(null); useLayoutEffect(() => { - if (props.grabFocus) { + if (props.grabFocus) inputRef.current?.focus(); - } + }, [props.grabFocus]); const value = props.bind[0]; const [dirty, setDirty] = useState(false); @@ -39,9 +39,9 @@ export function EmailInput(props: TextInputProps): VNode { type="email" class={showError ? 'input is-danger' : 'input'} onKeyPress={(e) => { - if (e.key === 'Enter' && props.onConfirm) { + if (e.key === 'Enter' && props.onConfirm) props.onConfirm() - } + }} onInput={(e) => { setDirty(true); diff --git a/packages/bank/src/components/fields/FileInput.tsx b/packages/bank/src/components/fields/FileInput.tsx index 65db491..17413b9 100644 --- a/packages/bank/src/components/fields/FileInput.tsx +++ b/packages/bank/src/components/fields/FileInput.tsx @@ -42,9 +42,9 @@ export interface FileInputProps { export function FileInput(props: FileInputProps): VNode { const inputRef = useRef(null); useLayoutEffect(() => { - if (props.grabFocus) { + if (props.grabFocus) inputRef.current?.focus(); - } + }, [props.grabFocus]); const fileInputRef = useRef(null); @@ -74,9 +74,9 @@ export function FileInput(props: FileInputProps): VNode { // name={String(name)} onChange={(e) => { const f: FileList | null = e.currentTarget.files; - if (!f || f.length != 1) { + if (!f || f.length != 1) return props.onChange(undefined); - } + console.log(f) if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { setSizeError(true); diff --git a/packages/bank/src/components/fields/ImageInput.tsx b/packages/bank/src/components/fields/ImageInput.tsx index ea50a98..98457af 100644 --- a/packages/bank/src/components/fields/ImageInput.tsx +++ b/packages/bank/src/components/fields/ImageInput.tsx @@ -28,9 +28,9 @@ const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024; export function ImageInput(props: TextInputProps): VNode { const inputRef = useRef(null); useLayoutEffect(() => { - if (props.grabFocus) { + if (props.grabFocus) inputRef.current?.focus(); - } + }, [props.grabFocus]); const value = props.bind[0]; @@ -64,9 +64,9 @@ export function ImageInput(props: TextInputProps): VNode { name={String(name)} onChange={(e) => { const f: FileList | null = e.currentTarget.files; - if (!f || f.length != 1) { + if (!f || f.length != 1) return onChange(emptyImage); - } + if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { setSizeError(true); return onChange(emptyImage); diff --git a/packages/bank/src/components/fields/NumberInput.tsx b/packages/bank/src/components/fields/NumberInput.tsx index 196d5ca..881c61c 100644 --- a/packages/bank/src/components/fields/NumberInput.tsx +++ b/packages/bank/src/components/fields/NumberInput.tsx @@ -14,9 +14,9 @@ export interface TextInputProps { export function PhoneNumberInput(props: TextInputProps): VNode { const inputRef = useRef(null); useLayoutEffect(() => { - if (props.grabFocus) { + if (props.grabFocus) inputRef.current?.focus(); - } + }, [props.grabFocus]); const value = props.bind[0]; const [dirty, setDirty] = useState(false); @@ -38,9 +38,9 @@ export function PhoneNumberInput(props: TextInputProps): VNode { placeholder={props.placeholder} class={showError ? 'input is-danger' : 'input'} onKeyPress={(e) => { - if (e.key === 'Enter' && props.onConfirm) { + if (e.key === 'Enter' && props.onConfirm) props.onConfirm() - } + }} onInput={(e) => { setDirty(true); diff --git a/packages/bank/src/components/fields/TextInput.tsx b/packages/bank/src/components/fields/TextInput.tsx index d36fc0e..5cc9f32 100644 --- a/packages/bank/src/components/fields/TextInput.tsx +++ b/packages/bank/src/components/fields/TextInput.tsx @@ -16,9 +16,9 @@ export interface TextInputProps { const TextInputType = function ({ inputType, grabFocus, ...rest }: any): VNode { const inputRef = useRef(null); useLayoutEffect(() => { - if (grabFocus) { + if (grabFocus) inputRef.current?.focus(); - } + }, [grabFocus]); return inputType === 'multiline' ? ( @@ -51,9 +51,9 @@ export function TextInput(props: TextInputProps): VNode { placeholder={props.placeholder} class={showError ? 'input is-danger' : 'input'} onKeyPress={(e: any) => { - if (e.key === 'Enter' && props.onConfirm) { + if (e.key === 'Enter' && props.onConfirm) props.onConfirm(); - } + }} onInput={(e: any) => { setDirty(true); diff --git a/packages/bank/src/components/picker/DatePicker.tsx b/packages/bank/src/components/picker/DatePicker.tsx index 91467a1..94dbc94 100644 --- a/packages/bank/src/components/picker/DatePicker.tsx +++ b/packages/bank/src/components/picker/DatePicker.tsx @@ -131,41 +131,41 @@ export class DatePicker extends Component { * Display previous month by updating state */ displayPrevMonth() { - if (this.state.displayedMonth <= 0) { + if (this.state.displayedMonth <= 0) this.setState({ displayedMonth: 11, displayedYear: this.state.displayedYear - 1, }); - } else { + else this.setState({ displayedMonth: this.state.displayedMonth - 1, }); - } + } /** * Display next month by updating state */ displayNextMonth() { - if (this.state.displayedMonth >= 11) { + if (this.state.displayedMonth >= 11) this.setState({ displayedMonth: 0, displayedYear: this.state.displayedYear + 1, }); - } else { + else this.setState({ displayedMonth: this.state.displayedMonth + 1, }); - } + } /** * Display the selected month (gets fired when clicking on the date string) */ displaySelectedMonth() { - if (this.state.selectYearMode) { + if (this.state.selectYearMode) this.toggleYearSelector(); - } else { + else { if (!this.state.currentDate) return false; this.setState({ displayedMonth: this.state.currentDate.getMonth(), @@ -351,6 +351,6 @@ export class DatePicker extends Component { } } -for (let i = 2010; i <= now.getFullYear() + 10; i++) { +for (let i = 2010; i <= now.getFullYear() + 10; i++) yearArr.push(i); -} + diff --git a/packages/bank/src/components/picker/DurationPicker.tsx b/packages/bank/src/components/picker/DurationPicker.tsx index 17e7ae7..542ff2f 100644 --- a/packages/bank/src/components/picker/DurationPicker.tsx +++ b/packages/bank/src/components/picker/DurationPicker.tsx @@ -204,8 +204,8 @@ function DurationColumn({ } function toTwoDigitString(n: number) { - if (n < 10) { + if (n < 10) return `0${n}`; - } + return `${n}`; } diff --git a/packages/bank/src/context/translation.ts b/packages/bank/src/context/translation.ts index 953777f..1879fe4 100644 --- a/packages/bank/src/context/translation.ts +++ b/packages/bank/src/context/translation.ts @@ -58,9 +58,9 @@ export const TranslationProvider = ({ const [lang, changeLanguage] = useLang(initial); useEffect(() => { - if (forceLang) { + if (forceLang) changeLanguage(forceLang); - } + }); console.log('lang store', strings); const handler = new jedLib.Jed(strings[lang] || strings['en']); diff --git a/packages/bank/src/hooks/index.ts b/packages/bank/src/hooks/index.ts index 0d9192d..a75b00d 100644 --- a/packages/bank/src/hooks/index.ts +++ b/packages/bank/src/hooks/index.ts @@ -64,9 +64,9 @@ export function useBackendInstanceToken( const [defaultToken, defaultSetToken] = useBackendDefaultToken(); // instance named 'default' use the default token - if (id === 'default') { + if (id === 'default') return [defaultToken, defaultSetToken]; - } + return [token, setToken]; } @@ -96,13 +96,13 @@ export function useLocalStorage( ) => { setStoredValue((p) => { const toStore = value instanceof Function ? value(p) : value; - if (typeof window !== 'undefined') { - if (!toStore) { + if (typeof window !== 'undefined') + if (!toStore) window.localStorage.removeItem(key); - } else { + else window.localStorage.setItem(key, toStore); - } - } + + return toStore; }); }; @@ -123,13 +123,13 @@ export function useNotNullLocalStorage( const setValue = (value: string | ((val: string) => string)) => { const valueToStore = value instanceof Function ? value(storedValue) : value; setStoredValue(valueToStore); - if (typeof window !== 'undefined') { - if (!valueToStore) { + if (typeof window !== 'undefined') + if (!valueToStore) window.localStorage.removeItem(key); - } else { + else window.localStorage.setItem(key, valueToStore); - } - } + + }; return [storedValue, setValue]; diff --git a/packages/bank/src/i18n/index.tsx b/packages/bank/src/i18n/index.tsx index 0694892..9882525 100644 --- a/packages/bank/src/i18n/index.tsx +++ b/packages/bank/src/i18n/index.tsx @@ -49,9 +49,9 @@ function toI18nString(stringSeq: ReadonlyArray): string { let s = ''; for (let i = 0; i < stringSeq.length; i++) { s += stringSeq[i]; - if (i < stringSeq.length - 1) { + if (i < stringSeq.length - 1) s += `%${i + 1}$s`; - } + } return s; } @@ -64,9 +64,9 @@ interface TranslateSwitchProps { function stringifyChildren(children: ComponentChildren): string { let n = 1; const ss = (children instanceof Array ? children : [children]).map((c) => { - if (typeof c === 'string') { + if (typeof c === 'string') return c; - } + return `%${n++}$s`; }); const s = ss.join('').replace(/ +/g, ' ').trim(); @@ -97,24 +97,24 @@ function getTranslatedChildren( const placeholderChildren = Array(); for (let i = 0; i < childArray.length; i++) { const x = childArray[i]; - if (x === undefined) { + if (x === undefined) continue; - } else if (typeof x === 'string') { + else if (typeof x === 'string') continue; - } else { + else placeholderChildren.push(x); - } + } const result = Array(); - for (let i = 0; i < tr.length; i++) { - if (i % 2 == 0) { + for (let i = 0; i < tr.length; i++) + if (i % 2 == 0) // Text result.push(tr[i]); - } else { + else { const childIdx = Number.parseInt(tr[i], 10) - 1; result.push(placeholderChildren[childIdx]); } - } + return result; } @@ -154,18 +154,18 @@ export function TranslateSwitch({ children, target }: TranslateSwitchProps) { let singular: VNode | undefined; let plural: VNode | undefined; // const children = this.props.children; - if (children) { + if (children) (children instanceof Array ? children : [children]).forEach( (child: any) => { - if (child.type === TranslatePlural) { + if (child.type === TranslatePlural) plural = child; - } - if (child.type === TranslateSingular) { + + if (child.type === TranslateSingular) singular = child; - } + }, ); - } + if (!singular || !plural) { console.error('translation not found'); return h('span', {}, ['translation not found']); diff --git a/packages/bank/src/pages/home/index.tsx b/packages/bank/src/pages/home/index.tsx index 3ab1481..3a4bfd6 100644 --- a/packages/bank/src/pages/home/index.tsx +++ b/packages/bank/src/pages/home/index.tsx @@ -9,7 +9,7 @@ import { QR } from '../../components/QR'; import { useNotNullLocalStorage, useLocalStorage } from '../../hooks'; import '../../scss/main.scss'; import talerLogo from '../../assets/logo-white.svg'; -import { LangSelectorLikePy as LangSelector} from '../../components/menu/LangSelector'; +import { LangSelectorLikePy as LangSelector } from '../../components/menu/LangSelector'; // Uncomment to allow test runs: // const __LIBEUFIN_UI_ALLOW_REGISTRATIONS__ = 1; @@ -146,7 +146,7 @@ function genCaptchaNumbers(): string { * Bring the state to show the public accounts page. */ function goPublicAccounts(pageStateSetter: StateUpdater) { - return () => pageStateSetter((prevState) => ({...prevState, showPublicHistories: true})) + return () => pageStateSetter((prevState) => ({ ...prevState, showPublicHistories: true })) } /** @@ -161,7 +161,7 @@ function validateAmount(maybeAmount: string): any { return; } if (typeof maybeAmount !== 'undefined' || maybeAmount !== '') { - console.log(`Maybe valid amount: ${ maybeAmount}`); + console.log(`Maybe valid amount: ${maybeAmount}`); // tolerating comma instead of point. const re = RegExp(amountRegex) if (!re.test(maybeAmount)) { @@ -192,7 +192,7 @@ function parseAmount(val: string): Amount { if (!format.test(val)) throw Error(`Backend gave invalid amount: ${val}.`) const amountSplit = val.split(':'); - return {value: amountSplit[1], currency: amountSplit[0]} + return { value: amountSplit[1], currency: amountSplit[0] } } /** @@ -200,9 +200,9 @@ function parseAmount(val: string): Amount { * exception if not found. */ function getUsername(backendState: BackendStateTypeOpt): string { - if (typeof backendState === 'undefined') { + if (typeof backendState === 'undefined') throw Error('Username can\'t be found in a undefined backend state.') - } + return backendState.username; } @@ -216,9 +216,9 @@ async function postToBackend( backendState: BackendStateTypeOpt, body: string ): Promise { - if (typeof backendState === 'undefined') { + if (typeof backendState === 'undefined') throw Error('Credentials can\'t be found in a undefined backend state.') - } + const { username, password } = backendState; const headers = prepareHeaders(username, password); // Backend URL must have been stored _with_ a final slash. @@ -234,7 +234,7 @@ async function postToBackend( function useTransactionPageNumber(): [number, StateUpdater] { const ret = useNotNullLocalStorage('transaction-page', '0'); const retObj = JSON.parse(ret[0]); - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) ret[1](newVal) } @@ -248,7 +248,7 @@ function prepareHeaders(username: string, password: string) { const headers = new Headers(); headers.append( 'Authorization', - `Basic ${Buffer.from(`${username }:${ password}`).toString('base64')}` + `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` ); headers.append( 'Content-Type', @@ -265,7 +265,7 @@ const getRootPath = () => { const maybeRootPath = typeof window !== undefined ? window.location.origin + window.location.pathname : '/'; - if (!maybeRootPath.endsWith('/')) return `${maybeRootPath }/`; + if (!maybeRootPath.endsWith('/')) return `${maybeRootPath}/`; return maybeRootPath; }; @@ -284,7 +284,7 @@ function useShowPublicAccount( const ret = useLocalStorage('show-public-account', JSON.stringify(state)); const retObj: string | undefined = ret[0] ? JSON.parse(ret[0]) : ret[0]; - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) ret[1](newVal) } @@ -302,7 +302,7 @@ function useRawPaytoInputType( const ret = useLocalStorage('raw-payto-input-state', state); const retObj: RawPaytoInputTypeOpt = ret[0]; - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? val(retObj) : val ret[1](newVal) } @@ -323,7 +323,7 @@ function useWireTransferRequestType( const ret = useLocalStorage('wire-transfer-request-state', JSON.stringify(state)); const retObj: WireTransferRequestTypeOpt = ret[0] ? JSON.parse(ret[0]) : ret[0]; - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) ret[1](newVal) } @@ -342,7 +342,7 @@ function useCredentialsRequestType( const ret = useLocalStorage('credentials-request-state', JSON.stringify(state)); const retObj: CredentialsRequestTypeOpt = ret[0] ? JSON.parse(ret[0]) : ret[0]; - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) ret[1](newVal) } @@ -361,7 +361,7 @@ function useBackendState( const ret = useLocalStorage('backend-state', JSON.stringify(state)); const retObj: BackendStateTypeOpt = ret[0] ? JSON.parse(ret[0]) : ret[0]; - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) ret[1](newVal) } @@ -379,7 +379,7 @@ function useAccountState( const ret = useLocalStorage('account-state', JSON.stringify(state)); const retObj: AccountStateTypeOpt = ret[0] ? JSON.parse(ret[0]) : ret[0]; - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) ret[1](newVal) } @@ -403,7 +403,7 @@ function usePageState( const ret = useNotNullLocalStorage('page-state', JSON.stringify(state)); const retObj: PageStateType = JSON.parse(ret[0]); console.log('Current page state', retObj); - const retSetter: StateUpdater = function(val) { + const retSetter: StateUpdater = function (val) { const newVal = val instanceof Function ? JSON.stringify(val(retObj)) : JSON.stringify(val) console.log('Setting new page state', newVal) ret[1](newVal) @@ -437,12 +437,12 @@ async function abortWithdrawalCall( ) { if (typeof backendState === 'undefined') { console.log('No credentials found.'); - pageStateSetter((prevState) => ({...prevState, hasError: true, error: 'No credentials found.'})) + pageStateSetter((prevState) => ({ ...prevState, hasError: true, error: 'No credentials found.' })) return; } if (typeof withdrawalId === 'undefined') { console.log('No withdrawal ID found.'); - pageStateSetter((prevState) => ({...prevState, hasError: true, error: 'No withdrawal ID found.'})) + pageStateSetter((prevState) => ({ ...prevState, hasError: true, error: 'No withdrawal ID found.' })) return; } @@ -465,13 +465,14 @@ async function abortWithdrawalCall( `access-api/accounts/${backendState.username}/withdrawals/${withdrawalId}/abort`, backendState.url ) - var res = await fetch(url.href, {method: 'POST', headers}) + var res = await fetch(url.href, { method: 'POST', headers }) } catch (error) { console.log('Could not abort the withdrawal', error); pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Could not abort the withdrawal: ${error}`})) + error: `Could not abort the withdrawal: ${error}` + })) return; } if (!res.ok) { @@ -479,17 +480,19 @@ async function abortWithdrawalCall( pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Withdrawal abortion gave response error (${res.status})`})) + error: `Withdrawal abortion gave response error (${res.status})` + })) return; - } + } console.log('Withdrawal operation aborted!'); pageStateSetter((prevState) => { const { talerWithdrawUri, withdrawalId, ...rest } = prevState; return { ...rest, withdrawalOutcome: 'Withdrawal aborted!' - }}) - + } + }) + } /** @@ -510,15 +513,15 @@ async function confirmWithdrawalCall( if (typeof backendState === 'undefined') { console.log('No credentials found.'); - pageStateSetter((prevState) => ({...prevState, hasError: true, error: 'No credentials found.'})) + pageStateSetter((prevState) => ({ ...prevState, hasError: true, error: 'No credentials found.' })) return; } if (typeof withdrawalId === 'undefined') { console.log('No withdrawal ID found.'); - pageStateSetter((prevState) => ({...prevState, hasError: true, error: 'No withdrawal ID found.'})) + pageStateSetter((prevState) => ({ ...prevState, hasError: true, error: 'No withdrawal ID found.' })) return; } - + let res: Response; try { const { username, password } = backendState; const headers = prepareHeaders(username, password); @@ -538,7 +541,7 @@ async function confirmWithdrawalCall( `access-api/accounts/${backendState.username}/withdrawals/${withdrawalId}/confirm`, backendState.url ) - var res = await fetch(url.href, { + res = await fetch(url.href, { method: 'POST', headers }) @@ -547,25 +550,28 @@ async function confirmWithdrawalCall( pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Could not confirm the withdrawal: ${error}`})) + error: `Could not confirm the withdrawal: ${error}` + })) return; } - if (!res.ok) { + if (res ? !res.ok : true) { // assume not ok if res is null console.log(`Withdrawal confirmation gave response error (${res.status})`, res.statusText); pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Withdrawal confirmation gave response error (${res.status})`})) + error: `Withdrawal confirmation gave response error (${res.status})` + })) return; - } + } console.log('Withdrawal operation confirmed!'); pageStateSetter((prevState) => { const { talerWithdrawUri, ...rest } = prevState; return { ...rest, withdrawalOutcome: 'Withdrawal confirmed!' - }}) - + } + }) + } /** @@ -596,7 +602,8 @@ async function createTransactionCall( pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Could not create the wire transfer: ${error}`})) + error: `Could not create the wire transfer: ${error}` + })) return; } // POST happened, status not sure yet. @@ -606,7 +613,8 @@ async function createTransactionCall( pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Transfer creation gave response error: ${responseText} (${res.status})`})) + error: `Transfer creation gave response error: ${responseText} (${res.status})` + })) return; } // status is 200 OK here, tell the user. @@ -636,7 +644,7 @@ async function createWithdrawalCall( ) { if (typeof backendState === 'undefined') { console.log('Page has a problem: no credentials found in the state.'); - pageStateSetter((prevState) => ({...prevState, hasError: true, error: 'No credentials given.'})) + pageStateSetter((prevState) => ({ ...prevState, hasError: true, error: 'No credentials given.' })) return; } try { @@ -651,7 +659,7 @@ async function createWithdrawalCall( var res = await fetch(url.href, { method: 'POST', headers, - body: JSON.stringify({amount}), + body: JSON.stringify({ amount }), } ); } catch (error) { @@ -659,7 +667,8 @@ async function createWithdrawalCall( pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Could not create withdrawal operation: ${error}`})) + error: `Could not create withdrawal operation: ${error}` + })) return; } if (!res.ok) { @@ -668,7 +677,8 @@ async function createWithdrawalCall( pageStateSetter((prevState) => ({ ...prevState, hasError: true, - error: `Withdrawal creation gave response error: ${responseText} (${res.status})`})) + error: `Withdrawal creation gave response error: ${responseText} (${res.status})` + })) return; } @@ -678,7 +688,8 @@ async function createWithdrawalCall( ...prevState, withdrawalInProgress: true, talerWithdrawUri: resp.taler_withdraw_uri, - withdrawalId: resp.withdrawal_id})) + withdrawalId: resp.withdrawal_id + })) } async function loginCall( @@ -697,9 +708,9 @@ async function loginCall( * whether the credentials are valid. */ pageStateSetter((prevState) => ({ ...prevState, isLoggedIn: true })); let baseUrl = getRootPath(); - if (!baseUrl.endsWith('/')) { + if (!baseUrl.endsWith('/')) baseUrl += '/'; - } + backendStateSetter((prevState) => ({ ...prevState, url: baseUrl, @@ -733,9 +744,9 @@ async function registrationCall( * is not empty, then the concatenation made by URL() * drops the last path element. */ - if (!baseUrl.endsWith('/')) { + if (!baseUrl.endsWith('/')) baseUrl += '/' - } + const headers = new Headers(); headers.append( 'Content-Type', @@ -784,9 +795,9 @@ async function registrationCall( function Currency(): VNode { const { data, error } = useSWR(`${getRootPath()}integration-api/config`, fetcher); - if (typeof error !== 'undefined') { + if (typeof error !== 'undefined') return error: currency could not be retrieved; - } + if (typeof data === 'undefined') return "..."; console.log('found bank config', data); return data.currency; @@ -801,8 +812,9 @@ function ErrorBanner(Props: any): VNode | null {    { pageStateSetter((prevState: PageStateType) => { delete prevState.error; // delete error message - return {...prevState, hasError: false} // delete error state - })}}> + return { ...prevState, hasError: false } // delete error state + }) + }}> {i18n`Clear`}

); @@ -842,9 +854,9 @@ function BankFrame(Props: any): VNode { ['Survey', '__DEMO_SITE_SURVEY_URL__'], ]; const demo_sites = []; - for (const i in DEMO_SITES) { + for (const i in DEMO_SITES) demo_sites.push({DEMO_SITES[i][0]}) - } + return (
@@ -856,19 +868,19 @@ function BankFrame(Props: any): VNode { { maybeDemoContent(

This part of the demo shows how a bank that supports - Taler directly would work. In addition to using your own - bank account, you can also see the transaction history of - some Public Accounts. -

- ) - } + Taler directly would work. In addition to using your own + bank account, you can also see the transaction history of + some Public Accounts. +

+ ) + } + height="100" + width="224" + style="margin: 2em 2em" />
@@ -908,21 +920,19 @@ function PaytoWireTransfer(Props: any): VNode { const focusInput = useRef(null); useEffect(() => { console.log('Now focus', focusInput); - if (focusInput.current) { - // @ts-ignore - focusInput.current.focus(); - } + if (focusInput.current) + (focusInput.current as any).focus(); }, []); console.log('wire form page state', pageState); const goBackForm = { - pageStateSetter((prevState: PageStateType) => ({...prevState, tryManualTransfer: false})) + pageStateSetter((prevState: PageStateType) => ({ ...prevState, tryManualTransfer: false })) submitDataSetter(undefined) } }>{i18n`Go back`}; const goBackRawPayto = { - pageStateSetter((prevState: PageStateType) => ({...prevState, isRawPayto: false})) + pageStateSetter((prevState: PageStateType) => ({ ...prevState, isRawPayto: false })) rawPaytoInputSetter(undefined) } @@ -938,13 +948,14 @@ function PaytoWireTransfer(Props: any): VNode { ref={focusInput} type="text" placeholder="receiver iban" - required + required pattern={ibanRegex} onInput={(e): void => { submitDataSetter((submitData: any) => ({ ...submitData, iban: e.currentTarget.value, - }))}} />

+ })) + }} />

({ ...submitData, subject: e.currentTarget.value, - }))}} />

+ })) + }} />

({ ...submitData, amount: e.currentTarget.value.replace(',', '.'), - }))}} /> 

+ })) + }} /> 

- ({...prevState, hasError: true, error: 'Field(s) missing.'})) + ({ ...prevState, hasError: true, error: 'Field(s) missing.' })) return; } transactionData = { @@ -996,14 +1009,14 @@ function PaytoWireTransfer(Props: any): VNode { pageStateSetter, submitDataSetter // need here only to be cleaned. ); - }} /> + }} />

{ - console.log('switch to raw payto form'); - pageStateSetter((prevState: any) => ({...prevState, isRawPayto: true})); - }}>{i18n`Want to try the raw payto://-format?`} + console.log('switch to raw payto form'); + pageStateSetter((prevState: any) => ({ ...prevState, isRawPayto: true })); + }}>{i18n`Want to try the raw payto://-format?`}

{goBackForm} @@ -1015,7 +1028,7 @@ function PaytoWireTransfer(Props: any): VNode {

{i18n`Wire transfer`}

{i18n`Transfer money via the Payto system:`}

Address pattern: - payto://iban/[receiver-iban]?message=[subject]&amount=[{currency}:X.Y] + payto://iban/[receiver-iban]?message=[subject]&amount=[{currency}:X.Y]

@@ -1031,15 +1044,15 @@ function PaytoWireTransfer(Props: any): VNode { { + onClick={() => { // empty string evaluates to false. if (!rawPaytoInput) { console.log('Didn\'t get any raw Payto string!'); return; } - transactionData = {paytoUri: rawPaytoInput}; + transactionData = { paytoUri: rawPaytoInput }; if (typeof transactionData.paytoUri === 'undefined' || - transactionData.paytoUri.length === 0) return; + transactionData.paytoUri.length === 0) return; createTransactionCall( transactionData, Props.backendState, @@ -1082,26 +1095,26 @@ function TalerWithdrawalConfirmationQuestion(Props: any): VNode { { + onClick={() => { if (captchaAnswer == (captchaNumbers.a + captchaNumbers.b).toString()) { confirmWithdrawalCall( backendState, pageState.withdrawalId, pageStateSetter) - return; - } + return; + } pageStateSetter((prevState: PageStateType) => - ({...prevState, hasError: true, error: 'Answer is wrong.'})) + ({ ...prevState, hasError: true, error: 'Answer is wrong.' })) }} /> - abortWithdrawalCall( + onClick={() => + abortWithdrawalCall( backendState, pageState.withdrawalId, pageStateSetter - )} /> + )} />

A this point, a real bank would ask for an additional @@ -1111,19 +1124,19 @@ function TalerWithdrawalConfirmationQuestion(Props: any): VNode { ); } -function QrCodeSection({talerWithdrawUri, abortButton}:{talerWithdrawUri:string, abortButton: h.JSX.Element}) { +function QrCodeSection({ talerWithdrawUri, abortButton }: { talerWithdrawUri: string, abortButton: h.JSX.Element }) { const i18n = useTranslator(); useEffect(() => { //Taler Wallet WebExtension is listening to headers response and tab updates. //In the SPA there is no header response with the Taler URI so //this hack manually triggers the tab update after the QR is in the DOM. - window.location.href = `${window.location.href.split('#')[0] }#` - },[]) + window.location.href = `${window.location.href.split('#')[0]}#` + }, []) return

{i18n`Withdraw to a Taler Wallet`}

{i18n`You can use this QR code to withdraw to your mobile wallet:`}

- {QR({text: talerWithdrawUri})} + {QR({ text: talerWithdrawUri })}

Click {i18n`this link`} to open your Taler wallet!


{abortButton} @@ -1148,7 +1161,8 @@ function TalerWithdrawalQRCode(Props: any): VNode { pageStateSetter((prevState: PageStateType) => { const { withdrawalOutcome, withdrawalId, talerWithdrawUri, ...rest } = prevState; return { ...rest, withdrawalInProgress: false }; - })}}>{i18n`Abort`} + }) + }}>{i18n`Abort`} console.log(`Showing withdraw URI: ${talerWithdrawUri}`); // waiting for the wallet: @@ -1166,15 +1180,15 @@ function TalerWithdrawalQRCode(Props: any): VNode { } // data didn't arrive yet and wallet didn't communicate: - if (typeof data === 'undefined') { + if (typeof data === 'undefined') return

{i18n`Waiting the bank to create the operaion...`}

- } + /** * Wallet didn't communicate withdrawal details yet: */ console.log('withdrawal status', data); - if (data.aborted) { + if (data.aborted) pageStateSetter((prevState: PageStateType) => { const { withdrawalOutcome, @@ -1188,7 +1202,7 @@ function TalerWithdrawalQRCode(Props: any): VNode { error: i18n`This withdrawal was aborted!` }; }) - } + if (!data.selection_done) { setTimeout(() => mutate(), 1000); // check again after 1 second. @@ -1205,7 +1219,7 @@ function TalerWithdrawalQRCode(Props: any): VNode { * Let the user choose an amount and submit the withdtawal. */ function TalerWithdrawal(Props: any): VNode { - const {backendState, pageStateSetter} = Props; + const { backendState, pageStateSetter } = Props; const currency = useContext(CurrencyContext); const i18n = useTranslator(); let submitAmount = '5.00'; // must match the first { - submitAmount = e.currentTarget.value; }}> + submitAmount = e.currentTarget.value; + }}> -  {submitButton} + type="text" + readonly + class="currency-indicator" + size={currency.length} + tabIndex={-1} value={currency} /> +  {submitButton} ); @@ -1263,7 +1279,7 @@ function TalerWithdrawal(Props: any): VNode { * Collect and submit login data. */ function LoginForm(Props: any): VNode { - const {backendStateSetter, pageStateSetter} = Props; + const { backendStateSetter, pageStateSetter } = Props; const [submitData, submitDataSetter] = useCredentialsRequestType(); const i18n = useTranslator(); // FIXME: try removing the outer Fragment. @@ -1279,23 +1295,25 @@ function LoginForm(Props: any): VNode { submitDataSetter((submitData: any) => ({ ...submitData, username: e.currentTarget.value, - }))}} /> + })) + }} /> { - submitDataSetter((submitData: any) => ({ + submitDataSetter((submitData: any) => ({ ...submitData, password: e.currentTarget.value, - }))}} /> + })) + }} /> - // FIXME: should use a different color + submitDataSetter({ username: '', password: '' }) + }}> + {i18n`Register`} + + {/* FIXME: should use a different color */} - + pageStateSetter((prevState: PageStateType) => ({ ...prevState, tryRegister: false })) + }}> + {i18n`cancel`} + @@ -1435,7 +1459,7 @@ function Transactions(Props: any): VNode { ); if (typeof error !== 'undefined') { console.log('transactions not found error', error); - switch(error.status) { + switch (error.status) { case 404: { return

Transactions page {pageNumber} was not found.

} @@ -1463,7 +1487,7 @@ function Transactions(Props: any): VNode { - {data.transactions.map((item: any) => { + {data.transactions.map((item: any, idx: number) => { const sign = item.direction == 'DBIT' ? '-' : ''; const counterpart = item.direction == 'DBIT' ? item.creditorIban : item.debtorIban; // Pattern: @@ -1473,7 +1497,7 @@ function Transactions(Props: any): VNode { const dateRegex = /^([0-9]{4})-([0-9]{2})-([0-9]{1,2})/ const dateParse = dateRegex.exec(item.date) const date = dateParse !== null ? `${dateParse[3]}/${dateParse[2]} ${dateParse[1]}` : 'date not found' - return ( + return ( {date} {sign}{item.amount} {item.currency} {counterpart} @@ -1512,9 +1536,9 @@ function Account(Props: any): VNode { */ const [txPageNumber, setTxPageNumber] = useTransactionPageNumber() const txsPages = [] - for (let i = 0; i <= txPageNumber; i++) { + for (let i = 0; i <= txPageNumber; i++) txsPages.push() - } + if (typeof error !== 'undefined') { console.log('account error', error); /** @@ -1522,7 +1546,7 @@ function Account(Props: any): VNode { * of pageStateSetter, after having decided the error * message in the case-branch. */ - switch(error.status) { + switch (error.status) { case 404: { pageStateSetter((prevState: PageStateType) => ({ ...prevState, @@ -1532,18 +1556,18 @@ function Account(Props: any): VNode { })); /** - * 404 should never stick to the cache, because they - * taint successful future registrations. How? After - * registering, the user gets navigated to this page, - * therefore a previous 404 on this SWR key (the requested - * resource) would still appear as valid and cause this - * page not to be shown! A typical case is an attempted - * login of a unregistered user X, and then a registration - * attempt of the same user X: in this case, the failed - * login would cache a 404 error to X's profile, resulting - * in the legitimate request after the registration to still - * be flagged as 404. Clearing the cache should prevent - * this. */ + * 404 should never stick to the cache, because they + * taint successful future registrations. How? After + * registering, the user gets navigated to this page, + * therefore a previous 404 on this SWR key (the requested + * resource) would still appear as valid and cause this + * page not to be shown! A typical case is an attempted + * login of a unregistered user X, and then a registration + * attempt of the same user X: in this case, the failed + * login would cache a 404 error to X's profile, resulting + * in the legitimate request after the registration to still + * be flagged as 404. Clearing the cache should prevent + * this. */ (cache as any).clear(); return

Profile not found...

; } @@ -1552,7 +1576,7 @@ function Account(Props: any): VNode { ...prevState, hasError: true, isLoggedIn: false, - error: i18n`Wrong credentials given.` + error: i18n`Wrong credentials given.` })); return

Wrong credentials...

; } @@ -1561,7 +1585,7 @@ function Account(Props: any): VNode { ...prevState, hasError: true, isLoggedIn: false, - error: i18n`Account information could not be retrieved.` + error: i18n`Account information could not be retrieved.` })); return

Unknown problem...

; } @@ -1574,7 +1598,7 @@ function Account(Props: any): VNode { * such state is usually successful, as errors should * have been reported earlier. */ - if (transferOutcome) { + if (transferOutcome) return

{transferOutcome}

- } + /** * Withdrawal reached a final state: show it. */ - if (withdrawalOutcome) { + if (withdrawalOutcome) return

{withdrawalOutcome}

- } + /** * This block shows the withdrawal QR code. @@ -1625,21 +1653,21 @@ function Account(Props: any): VNode { return ( + accountLabel={accountLabel} + backendState={backendState} + withdrawalId={withdrawalId} + talerWithdrawUri={talerWithdrawUri} /> ); } const balance = parseAmount(data.balance.amount) - if (tryManualTransfer) { + if (tryManualTransfer) return ( ); - } + return (

@@ -1648,7 +1676,7 @@ function Account(Props: any): VNode {

@@ -1663,7 +1691,7 @@ function Account(Props: any): VNode {

pageStateSetter((prevState: PageStateType) => - ({...prevState, tryManualTransfer: true})) + ({ ...prevState, tryManualTransfer: true })) }>{i18n`Transfer money manually`}

@@ -1678,7 +1706,7 @@ function SWRWithCredentials(props: any): VNode { const headers = new Headers(); headers.append( 'Authorization', - `Basic ${Buffer.from(`${username }:${ password}`).toString('base64')}` + `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}` ); console.log('Likely backend base URL', backendUrl); return ( @@ -1686,13 +1714,13 @@ function SWRWithCredentials(props: any): VNode { value={{ fetcher: (url) => fetch(backendUrl + url || '', { headers }).then( - (r) => { - if (!r.ok) { - throw {status: r.status, json: r.json()}; - } + (r) => { + if (!r.ok) + throw { status: r.status, json: r.json() }; + return r.json() - } - ), + } + ), }}>{props.children} ); } @@ -1705,13 +1733,13 @@ function SWRWithoutCredentials(Props: any): VNode { value={{ fetcher: (url) => fetch(baseUrl + url || '').then( - (r) => { - if (!r.ok) { - throw {status: r.status, json: r.json()}; - } + (r) => { + if (!r.ok) + throw { status: r.status, json: r.json() }; + return r.json() - } - ), + } + ), }}>{Props.children} ); } @@ -1726,7 +1754,7 @@ function PublicHistories(Props: any): VNode { if (typeof error !== 'undefined') { console.log('account error', error); - switch(error.status) { + switch (error.status) { case 404: console.log('public accounts: 404', error); Props.pageStateSetter((prevState: PageStateType) => ({ @@ -1742,7 +1770,7 @@ function PublicHistories(Props: any): VNode { ...prevState, hasError: true, showPublicHistories: false, - error: i18n`List of public accounts could not be retrieved.` + error: i18n`List of public accounts could not be retrieved.` })); break; } @@ -1766,7 +1794,7 @@ function PublicHistories(Props: any): VNode { accountsBar.push(
  • setShowAccount(account.accountLabel)}>{account.accountLabel}
  • ); @@ -1798,37 +1826,38 @@ export function BankHome(): VNode { const setTxPageNumber = useTransactionPageNumber()[1]; const i18n = useTranslator(); - if (pageState.showPublicHistories) { + if (pageState.showPublicHistories) return ( -
    +
    { pageStateSetter((prevState: PageStateType) => - ({...prevState, showPublicHistories: false}))}}>Go back + ({ ...prevState, showPublicHistories: false })) + }}>Go back
    ); - } + if (pageState.tryRegister) { // @ts-expect-error Global variable unknown to ts console.log('allow registrations?', __LIBEUFIN_UI_ALLOW_REGISTRATIONS__) // @ts-expect-error Global variable unknown to ts - if (__LIBEUFIN_UI_ALLOW_REGISTRATIONS__) { + if (__LIBEUFIN_UI_ALLOW_REGISTRATIONS__) return ( - - + + ); - } + return ( -

    {i18n`Currently, the bank is not accepting new registrations!`}

    +

    {i18n`Currently, the bank is not accepting new registrations!`}

    ); @@ -1861,19 +1890,20 @@ export function BankHome(): VNode { * bank did.) FIXME: currency needed at startup too. */ const regMsg = function () { // @ts-expect-error Global variable unknown to ts - if (__LIBEUFIN_UI_ALLOW_REGISTRATIONS__) { + if (__LIBEUFIN_UI_ALLOW_REGISTRATIONS__) return (

    If you are a new customer please  - - {pageStateSetter((prevState) => - ({...prevState, tryRegister: true}))}}>register! -   

    { - maybeDemoContent(

    Registration is fast and + { + pageStateSetter((prevState) => + ({ ...prevState, tryRegister: true })) + }}>register! +   

    { + maybeDemoContent(

    Registration is fast and free, and it gives you a registration bonus of 100 -

    ) - /*close JS block of optional content*/ } +

    ) + /*close JS block of optional content*/}
    ); // close return of registrations allowance. - } // close 'then' branch of registrations allowance. + // close 'then' branch of registrations allowance. } // close helper function. return ( @@ -1884,7 +1914,7 @@ export function BankHome(): VNode { backendStateSetter={backendStateSetter} /> {regMsg()} {maybeDemoContent(

    - To view transactions of public accounts, please click here.

    )} -- cgit v1.2.3