summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx')
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx127
1 files changed, 97 insertions, 30 deletions
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
index 7b8712eca..1e4a44df1 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
@@ -1,37 +1,60 @@
import { Amounts, BackupBackupProviderTerms, i18n } from "@gnu-taler/taler-util";
-import { privateDecrypt } from "crypto";
-import { add, addYears } from "date-fns";
-import { VNode } from "preact";
+import { Fragment, VNode } from "preact";
import { useState } from "preact/hooks";
import * as wxApi from "../wxApi";
-import ProviderAddConfirmProviderStories from "./ProviderAddConfirmProvider.stories";
interface Props {
currency: string;
}
-export function ProviderAddPage({ currency }: Props): VNode {
+function getJsonIfOk(r: Response) {
+ if (r.ok) {
+ return r.json()
+ } else {
+ if (r.status >= 400 && r.status < 500) {
+ throw new Error(`URL may not be right: (${r.status}) ${r.statusText}`)
+ } else {
+ throw new Error(`Try another server: (${r.status}) ${r.statusText || 'internal server error'}`)
+ }
+ }
+}
+
+
+export function ProviderAddPage({ }: Props): VNode {
const [verifying, setVerifying] = useState<{ url: string, provider: BackupBackupProviderTerms } | undefined>(undefined)
+ const [readingTerms, setReadingTerms] = useState<boolean | undefined>(undefined)
+ const alreadyCheckedTheTerms = readingTerms === false
+
if (!verifying) {
return <SetUrlView
- currency={currency}
onCancel={() => {
setVerifying(undefined);
}}
onVerify={(url) => {
- return fetch(url).then(r => r.json())
- .then((provider) => setVerifying({ url, provider }))
+ return fetch(`${url}/config`)
+ .catch(e => { throw new Error(`Network error`) })
+ .then(getJsonIfOk)
+ .then((provider) => { setVerifying({ url, provider }); return undefined })
.catch((e) => e.message)
}}
/>
}
+ if (readingTerms) {
+ return <TermsOfService
+ onCancel={() => setReadingTerms(undefined)}
+ onAccept={() => setReadingTerms(false)}
+ />
+ }
return <ConfirmProviderView
provider={verifying.provider}
- currency={currency}
+ termsChecked={alreadyCheckedTheTerms}
url={verifying.url}
onCancel={() => {
setVerifying(undefined);
}}
+ onShowTerms={() => {
+ setReadingTerms(true)
+ }}
onConfirm={() => {
wxApi.addBackupProvider(verifying.url).then(_ => history.go(-1))
}}
@@ -39,33 +62,75 @@ export function ProviderAddPage({ currency }: Props): VNode {
/>
}
+interface TermsOfServiceProps {
+ onCancel: () => void;
+ onAccept: () => void;
+}
+
+function TermsOfService({ onCancel, onAccept }: TermsOfServiceProps) {
+ return <div style={{ display: 'flex', flexDirection: 'column' }}>
+ <section style={{ height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
+ <div>
+ Here we will place the complete text of terms of service
+ </div>
+ </section>
+ <footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
+ <button class="pure-button" onClick={onCancel}><i18n.Translate>cancel</i18n.Translate></button>
+ <div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
+ <button class="pure-button" onClick={onAccept}><i18n.Translate>accept</i18n.Translate></button>
+ </div>
+ </footer>
+ </div>
+}
+
export interface SetUrlViewProps {
- currency: string,
+ initialValue?: string;
onCancel: () => void;
onVerify: (s: string) => Promise<string | undefined>;
+ withError?: string;
}
+import arrowDown from '../../static/img/chevron-down.svg';
-export function SetUrlView({ currency, onCancel, onVerify }: SetUrlViewProps) {
- const [value, setValue] = useState<string>("")
- const [error, setError] = useState<string | undefined>(undefined)
+export function SetUrlView({ initialValue, onCancel, onVerify, withError }: SetUrlViewProps) {
+ const [value, setValue] = useState<string>(initialValue || "")
+ const [error, setError] = useState<string | undefined>(withError)
+ const [showErrorDetail, setShowErrorDetail] = useState(false);
return <div style={{ display: 'flex', flexDirection: 'column' }}>
<section style={{ height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
<div>
- Add backup provider for storing <b>{currency}</b>
+ Add backup provider for saving coins
</div>
- {error && <div class="errorbox" style={{ marginTop: 10 }} >
- <p>{error}</p>
- </div>}
<h3>Backup provider URL</h3>
- <input style={{ width: 'calc(100% - 8px)' }} value={value} onChange={(e) => setValue(e.currentTarget.value)} />
+ <div style={{ width: '3em', display: 'inline-block' }}>https://</div>
+ <input style={{ width: 'calc(100% - 8px - 4em)', marginLeft: 5 }} value={value} onChange={(e) => setValue(e.currentTarget.value)} />
<p>
Backup providers may charge for their service
</p>
+ {error && <Fragment>
+ <div class="errorbox" style={{ marginTop: 10 }} >
+ <div style={{ width: '100%', flexDirection: 'row', justifyContent: 'space-between', display: 'flex' }}>
+ <p style={{ alignSelf: 'center' }}>Could not get provider information</p>
+ <p>
+ <button style={{ fontSize: '100%', padding: 0, height: 28, width: 28 }} onClick={() => { setShowErrorDetail(v => !v) }} >
+ <img style={{ height: '1.5em' }} src={arrowDown} />
+ </button>
+ </p>
+ </div>
+ {showErrorDetail && <div>{error}</div>}
+ </div>
+ </Fragment>
+ }
</section>
<footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
<button class="pure-button" onClick={onCancel}><i18n.Translate>cancel</i18n.Translate></button>
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
- <button class="pure-button button-secondary" style={{ marginLeft: 5 }} onClick={() => onVerify(value).then(r => r ? setError(r) : undefined)}><i18n.Translate>verify service terms</i18n.Translate></button>
+ <button class="pure-button button-secondary" style={{ marginLeft: 5 }}
+ disabled={!value}
+ onClick={() => {
+ let url = value.startsWith('http://') || value.startsWith('https://') ? value : `https://${value}`
+ url = url.endsWith('/') ? url.substring(0, url.length - 1) : url;
+ return onVerify(url).then(r => r ? setError(r) : undefined)
+ }}><i18n.Translate>next</i18n.Translate></button>
</div>
</footer>
</div>
@@ -73,19 +138,16 @@ export function SetUrlView({ currency, onCancel, onVerify }: SetUrlViewProps) {
export interface ConfirmProviderViewProps {
provider: BackupBackupProviderTerms,
- currency: string,
url: string,
onCancel: () => void;
- onConfirm: () => void
+ onConfirm: () => void;
+ onShowTerms: () => void;
+ termsChecked: boolean;
}
-export function ConfirmProviderView({ url, provider, currency, onCancel, onConfirm }: ConfirmProviderViewProps) {
+export function ConfirmProviderView({ url, termsChecked, onShowTerms, provider, onCancel, onConfirm }: ConfirmProviderViewProps) {
return <div style={{ display: 'flex', flexDirection: 'column' }}>
-
<section style={{ height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
- <div>
- Verify provider service terms for storing <b>{currency}</b>
- </div>
- <h3>{url}</h3>
+ <div>Verify provider service terms for <b>{url}</b> backup provider</div>
<p>
{Amounts.isZero(provider.annual_fee) ? 'free of charge' : provider.annual_fee} for a year of backup service
</p>
@@ -98,9 +160,14 @@ export function ConfirmProviderView({ url, provider, currency, onCancel, onConfi
<i18n.Translate>cancel</i18n.Translate>
</button>
<div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
- <button class="pure-button button-success" style={{ marginLeft: 5 }} onClick={onConfirm}>
- <i18n.Translate>confirm</i18n.Translate>
- </button>
+ {termsChecked ?
+ <button class="pure-button button-success" style={{ marginLeft: 5 }} onClick={onConfirm}>
+ <i18n.Translate>confirm</i18n.Translate>
+ </button> :
+ <button class="pure-button button-success" style={{ marginLeft: 5 }} onClick={onShowTerms}>
+ <i18n.Translate>review terms</i18n.Translate>
+ </button>
+ }
</div>
</footer>
</div>