summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/taler-wallet-webextension/.storybook/preview.js28
-rw-r--r--packages/taler-wallet-webextension/src/components/ErrorMessage.tsx18
-rw-r--r--packages/taler-wallet-webextension/src/components/styled/index.tsx36
-rw-r--r--packages/taler-wallet-webextension/src/popup/BackupPage.tsx25
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx46
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx142
6 files changed, 155 insertions, 140 deletions
diff --git a/packages/taler-wallet-webextension/.storybook/preview.js b/packages/taler-wallet-webextension/.storybook/preview.js
index 1c07ba402..0fda6ac0e 100644
--- a/packages/taler-wallet-webextension/.storybook/preview.js
+++ b/packages/taler-wallet-webextension/.storybook/preview.js
@@ -52,8 +52,32 @@ export const decorators = [
(Story, { kind }) => {
if (kind.startsWith('popup')) {
return <div class="popup-container">
- <link key="1" rel="stylesheet" type="text/css" href="/style/pure.css" />
- <link key="2" rel="stylesheet" type="text/css" href="/style/popup.css" />
+ <style>{`
+ html {
+ font-family: sans-serif; /* 1 */
+ }
+ body {
+ margin: 0;
+ }`}
+ </style>
+ <style>{`
+ html {
+ }
+ h1 {
+ font-size: 2em;
+ }
+ input {
+ font: inherit;
+ }
+ body {
+ margin: 0;
+ font-size: 100%;
+ padding: 0;
+ overflow: hidden;
+ background-color: #f8faf7;
+ font-family: Arial, Helvetica, sans-serif;
+ }`}
+ </style>
<div style={{ padding: 8, width: 'calc(400px - 16px - 2px)', height: 'calc(320px - 34px - 16px - 2px)', border: 'black solid 1px' }}>
<Story />
</div>
diff --git a/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx b/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx
new file mode 100644
index 000000000..eaf015224
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/ErrorMessage.tsx
@@ -0,0 +1,18 @@
+import { useState } from "preact/hooks";
+import arrowDown from '../../static/img/chevron-down.svg';
+import { ErrorBox } from "./styled";
+
+export function ErrorMessage({ title, description }: { title?: string; description?: string; }) {
+ const [showErrorDetail, setShowErrorDetail] = useState(false);
+ if (!title)
+ return null;
+ return <ErrorBox>
+ <div>
+ <p>{title}</p>
+ { description && <button onClick={() => { setShowErrorDetail(v => !v); }}>
+ <img style={{ height: '1.5em' }} src={arrowDown} />
+ </button> }
+ </div>
+ {showErrorDetail && <p>{description}</p>}
+ </ErrorBox>;
+}
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index ffcafd70f..434e3350a 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -4,6 +4,13 @@ import type * as Linaria from '@linaria/core';
import { styled } from '@linaria/react';
+export const PaymentStatus = styled.span<{color:string}>`
+ padding: 5px;
+ border-radius: 5px;
+ color: white;
+ background-color: ${p => p.color};
+`
+
export const PopupBox = styled.div`
height: calc(320px - 34px - 16px);
display: flex;
@@ -11,23 +18,40 @@ export const PopupBox = styled.div`
justify-content: space-between;
& > section {
+ // this margin will send the section up when used with a header
+ margin-bottom: auto;
overflow: auto;
+
+ table td {
+ padding: 5px 10px;
+ }
+ table tr {
+ border-bottom: 1px solid black;
+ border-top: 1px solid black;
+ }
+ }
+
+ & > header {
+ flex-direction: row;
+ justify-content: space-between;
+ display: flex;
+ margin-bottom: 5px;
+
+ & > div {
+ align-self: center;
+ }
}
& > footer {
padding-top: 5px;
flex-direction: row;
- justify-content: flex-end;
+ justify-content: space-between;
display: flex;
- & > button {
+ & button {
margin-left: 5px;
}
}
- & > section > h1 {
- margin-top: 0.3em;
- margin-bottom: 0.3em;
- }
`
export const Button = styled.button`
diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
index 6e60acc74..c2067ad21 100644
--- a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
@@ -20,8 +20,8 @@ import { ProviderInfo, ProviderPaymentStatus } from "@gnu-taler/taler-wallet-cor
import { differenceInMonths, formatDuration, intervalToDuration } from "date-fns";
import { FunctionalComponent, Fragment, JSX, VNode, AnyComponent } from "preact";
import {
- BoldLight, ButtonPrimary, ButtonSuccess, Centered,
- CenteredText, CenteredTextBold, PopupBox, Row,
+ BoldLight, ButtonPrimary, ButtonSuccess, Centered,
+ CenteredText, CenteredTextBold, PopupBox, Row,
SmallText, SmallTextLight
} from "../components/styled";
import { useBackupStatus } from "../hooks/useBackupStatus";
@@ -47,7 +47,7 @@ export interface ViewProps {
export function BackupView({ providers, onAddProvider, onSyncAll }: ViewProps): VNode {
return (
- <PopupBox style={{ justifyContent: !providers.length ? 'center' : 'space-between' }}>
+ <PopupBox>
<section>
{providers.map((provider) => <BackupLayout
status={provider.paymentStatus}
@@ -57,18 +57,21 @@ export function BackupView({ providers, onAddProvider, onSyncAll }: ViewProps):
title={provider.syncProviderBaseUrl}
/>
)}
- {!providers.length && <Centered>
+ {!providers.length && <Centered style={{marginTop: 100}}>
<BoldLight>No backup providers configured</BoldLight>
<ButtonSuccess onClick={onAddProvider}><i18n.Translate>Add provider</i18n.Translate></ButtonSuccess>
</Centered>}
</section>
{!!providers.length && <footer>
- <ButtonPrimary onClick={onSyncAll}>{
- providers.length > 1 ?
- <i18n.Translate>Sync all backups</i18n.Translate> :
- <i18n.Translate>Sync now</i18n.Translate>
- }</ButtonPrimary>
- <ButtonSuccess onClick={onAddProvider}>Add provider</ButtonSuccess>
+ <div />
+ <div>
+ <ButtonPrimary onClick={onSyncAll}>{
+ providers.length > 1 ?
+ <i18n.Translate>Sync all backups</i18n.Translate> :
+ <i18n.Translate>Sync now</i18n.Translate>
+ }</ButtonPrimary>
+ <ButtonSuccess onClick={onAddProvider}>Add provider</ButtonSuccess>
+ </div>
</footer>}
</PopupBox>
)
@@ -111,7 +114,7 @@ function BackupLayout(props: TransactionLayoutProps): JSX.Element {
function ExpirationText({ until }: { until: Timestamp }) {
return <Fragment>
<CenteredText> Expires in </CenteredText>
- <CenteredTextBold {...({color:colorByTimeToExpire(until)})}> {daysUntil(until)} </CenteredTextBold>
+ <CenteredTextBold {...({ color: colorByTimeToExpire(until) })}> {daysUntil(until)} </CenteredTextBold>
</Fragment>
}
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
index 4b5da05f4..92579e36a 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderAddPage.tsx
@@ -1,6 +1,9 @@
import { Amounts, BackupBackupProviderTerms, i18n } from "@gnu-taler/taler-util";
-import { Fragment, VNode } from "preact";
+import { VNode } from "preact";
import { useState } from "preact/hooks";
+import { Checkbox } from "../components/Checkbox";
+import { ErrorMessage } from "../components/ErrorMessage";
+import { Button, ButtonPrimary, Input, LightText, PopupBox, SmallTextLight } from "../components/styled/index";
import * as wxApi from "../wxApi";
interface Props {
@@ -49,26 +52,6 @@ export function ProviderAddPage({ onBack }: 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 {
initialValue?: string;
@@ -76,23 +59,6 @@ export interface SetUrlViewProps {
onVerify: (s: string) => Promise<string | undefined>;
withError?: string;
}
-import arrowDown from '../../static/img/chevron-down.svg';
-import { Button, ButtonPrimary, ErrorBox, Input, LightText, PopupBox, SmallTextLight } from "../components/styled/index";
-import { Checkbox } from "../components/Checkbox";
-
-function ErrorMessage({ title, description }: { title?: string, description?: string }) {
- const [showErrorDetail, setShowErrorDetail] = useState(false);
- if (!title) return null
- return <ErrorBox>
- <div>
- <p>{title}</p>
- <button onClick={() => { setShowErrorDetail(v => !v) }} >
- <img style={{ height: '1.5em' }} src={arrowDown} />
- </button>
- </div>
- {showErrorDetail && <p>{description}</p>}
- </ErrorBox>
-}
export function SetUrlView({ initialValue, onCancel, onVerify, withError }: SetUrlViewProps) {
const [value, setValue] = useState<string>(initialValue || "")
@@ -113,7 +79,7 @@ export function SetUrlView({ initialValue, onCancel, onVerify, withError }: SetU
</Input>
</p>
</section>
- <footer style={{ justifyContent: 'space-between' }}>
+ <footer>
<Button onClick={onCancel}><i18n.Translate> &lt; Back</i18n.Translate></Button>
<ButtonPrimary
disabled={!value}
@@ -150,7 +116,7 @@ export function ConfirmProviderView({ url, provider, onCancel, onConfirm }: Conf
</p>
<Checkbox label="Accept terms of service" name="terms" onToggle={() => setAccepted(old => !old)} enabled={accepted}/>
</section>
- <footer style={{ justifyContent: 'space-between' }}>
+ <footer>
<Button onClick={onCancel}><i18n.Translate> &lt; Back</i18n.Translate></Button>
<ButtonPrimary
disabled={!accepted}
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
index 0d48ab070..2482dee18 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
@@ -19,6 +19,8 @@ import { i18n, Timestamp } from "@gnu-taler/taler-util";
import { ProviderInfo, ProviderPaymentStatus, ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
import { format, formatDuration, intervalToDuration } from "date-fns";
import { Fragment, VNode } from "preact";
+import { ErrorMessage } from "../components/ErrorMessage";
+import { Button, ButtonDestructive, ButtonPrimary, PaymentStatus, PopupBox } from "../components/styled";
import { useProviderStatus } from "../hooks/useProviderStatus";
interface Props {
@@ -52,24 +54,14 @@ export interface ViewProps {
}
export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewProps): VNode {
- function Footer() {
- return <footer style={{ marginTop: 'auto', display: 'flex', flexShrink: 0 }}>
- <button class="pure-button" onClick={onBack}><i18n.Translate>back</i18n.Translate></button>
- <div style={{ width: '100%', flexDirection: 'row', justifyContent: 'flex-end', display: 'flex' }}>
- {info && <button class="pure-button button-destructive" disabled onClick={onDelete}><i18n.Translate>remove</i18n.Translate></button>}
- {info && <button class="pure-button button-secondary" disabled style={{ marginLeft: 5 }} onClick={onExtend}><i18n.Translate>extend</i18n.Translate></button>}
- {info && <button class="pure-button button-secondary" style={{ marginLeft: 5 }} onClick={onSync}><i18n.Translate>sync now</i18n.Translate></button>}
- </div>
- </footer>
- }
function Error() {
if (info?.lastError) {
- return <Fragment>
- <div class="errorbox" style={{ marginTop: 10 }} >
- <div style={{ height: 0, textAlign: 'right', color: 'gray', fontSize: 'small' }}>last time tried {!info.lastAttemptedBackupTimestamp || info.lastAttemptedBackupTimestamp.t_ms === 'never' ? 'never' : format(new Date(info.lastAttemptedBackupTimestamp.t_ms), 'dd/MM/yyyy HH:mm:ss')}</div>
- <p>{info.lastError.hint}</p>
- </div>
- </Fragment>
+ return <ErrorMessage title={info.lastError.hint} />
+ // <div class="errorbox" style={{ marginTop: 10 }} >
+ // <div style={{ height: 0, textAlign: 'right', color: 'gray', fontSize: 'small' }}>last time tried {!info.lastAttemptedBackupTimestamp || info.lastAttemptedBackupTimestamp.t_ms === 'never' ? 'never' : format(new Date(info.lastAttemptedBackupTimestamp.t_ms), 'dd/MM/yyyy HH:mm:ss')}</div>
+ // <p>{info.lastError.hint}</p>
+ // </div>
+ // </Fragment>
}
if (info?.backupProblem) {
switch (info.backupProblem.type) {
@@ -89,7 +81,8 @@ export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewP
}
return null
}
- function colorByStatus(status: ProviderPaymentType | undefined) {
+
+ function colorByStatus(status: ProviderPaymentType) {
switch (status) {
case ProviderPaymentType.InsufficientBalance:
return 'rgb(223, 117, 20)'
@@ -103,14 +96,10 @@ export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewP
return 'rgb(202, 60, 60)'
case ProviderPaymentType.TermsChanged:
return 'rgb(202, 60, 60)'
- default:
- break;
}
- return undefined
}
- function descriptionByStatus(status: ProviderPaymentStatus | undefined) {
- if (!status) return ''
+ function descriptionByStatus(status: ProviderPaymentStatus) {
switch (status.type) {
case ProviderPaymentType.InsufficientBalance:
return 'no enough balance to make the payment'
@@ -125,69 +114,60 @@ export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewP
}
case ProviderPaymentType.Pending:
return ''
- default:
- break;
}
- return undefined
}
return (
- <div style={{ height: 'calc(320px - 34px - 16px)', overflow: 'auto' }}>
- <style>{`
- table td {
- padding: 5px 10px;
- }
- `}</style>
- <div style={{ display: 'flex', flexDirection: 'column' }}>
- <section style={{ flex: '1 0 auto', height: 'calc(320px - 34px - 34px - 16px)', overflow: 'auto' }}>
- <span style={{ padding: 5, display: 'inline-block', backgroundColor: colorByStatus(info?.paymentStatus.type), borderRadius: 5, color: 'white' }}>{info?.paymentStatus.type}</span>
- {/* {info && <span style={{ float: "right", fontSize: "small", color: "gray", padding: 5 }}>
- From <b>{info.syncProviderBaseUrl}</b>
- </span>} */}
- {info && <div style={{ float: 'right', fontSize: "large", padding: 5 }}>{info.terms?.annualFee} / year</div>}
-
- <Error />
-
- <h3>{info?.syncProviderBaseUrl}</h3>
- <div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", }}>
- <div>{daysSince(info?.lastSuccessfulBackupTimestamp)} </div>
- </div>
-
- <p>{descriptionByStatus(info?.paymentStatus)}</p>
-
- {info?.paymentStatus.type === ProviderPaymentType.TermsChanged && <div>
- <p>terms has changed, extending the service will imply accepting the new terms of service</p>
- <table>
- <thead>
- <tr>
- <td></td>
- <td>old</td>
- <td> -&gt;</td>
- <td>new</td>
- </tr>
- </thead>
- <tbody>
-
- <tr>
- <td>fee</td>
- <td>{info.paymentStatus.oldTerms.annualFee}</td>
- <td>-&gt;</td>
- <td>{info.paymentStatus.newTerms.annualFee}</td>
- </tr>
- <tr>
- <td>storage</td>
- <td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
- <td>-&gt;</td>
- <td>{info.paymentStatus.newTerms.storageLimitInMegabytes}</td>
- </tr>
- </tbody>
- </table>
- </div>}
-
- </section>
- <Footer />
- </div>
- </div>
+ <PopupBox>
+ <header>
+ <PaymentStatus color={colorByStatus(info.paymentStatus.type)}>{info.paymentStatus.type}</PaymentStatus>
+
+ {info.terms && <div>{info.terms.annualFee} / year</div>}
+ </header>
+ <section>
+ <Error />
+ <h3>{info.syncProviderBaseUrl}</h3>
+ <p>{daysSince(info?.lastSuccessfulBackupTimestamp)} </p>
+ <p>{descriptionByStatus(info.paymentStatus)}</p>
+ {info.paymentStatus.type === ProviderPaymentType.TermsChanged && <div>
+ <p>terms has changed, extending the service will imply accepting the new terms of service</p>
+ <table>
+ <thead>
+ <tr>
+ <td></td>
+ <td>old</td>
+ <td> -&gt;</td>
+ <td>new</td>
+ </tr>
+ </thead>
+ <tbody>
+
+ <tr>
+ <td>fee</td>
+ <td>{info.paymentStatus.oldTerms.annualFee}</td>
+ <td>-&gt;</td>
+ <td>{info.paymentStatus.newTerms.annualFee}</td>
+ </tr>
+ <tr>
+ <td>storage</td>
+ <td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
+ <td>-&gt;</td>
+ <td>{info.paymentStatus.newTerms.storageLimitInMegabytes}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>}
+
+ </section>
+ <footer>
+ <Button onClick={onBack}><i18n.Translate> &lt; back</i18n.Translate></Button>
+ <div>
+ <ButtonDestructive disabled onClick={onDelete}><i18n.Translate>remove</i18n.Translate></ButtonDestructive>
+ <ButtonPrimary disabled onClick={onExtend}><i18n.Translate>extend</i18n.Translate></ButtonPrimary>
+ <ButtonPrimary onClick={onSync}><i18n.Translate>sync now</i18n.Translate></ButtonPrimary>
+ </div>
+ </footer>
+ </PopupBox>
)
}