diff options
author | Sebastian <sebasjm@gmail.com> | 2021-07-12 14:47:13 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-07-12 14:48:59 -0300 |
commit | 0cf52a2812dd0cfab9bfdf2dcd81fe4787f4dcb0 (patch) | |
tree | 79b4049999cadd4e324b54a177990bc1ea4d09d6 | |
parent | 1c0cce3f5812cd2796ab9693b47f035427ca5340 (diff) |
styles for provider detail page
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> < 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> < 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> -></td> - <td>new</td> - </tr> - </thead> - <tbody> - - <tr> - <td>fee</td> - <td>{info.paymentStatus.oldTerms.annualFee}</td> - <td>-></td> - <td>{info.paymentStatus.newTerms.annualFee}</td> - </tr> - <tr> - <td>storage</td> - <td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td> - <td>-></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> -></td> + <td>new</td> + </tr> + </thead> + <tbody> + + <tr> + <td>fee</td> + <td>{info.paymentStatus.oldTerms.annualFee}</td> + <td>-></td> + <td>{info.paymentStatus.newTerms.annualFee}</td> + </tr> + <tr> + <td>storage</td> + <td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td> + <td>-></td> + <td>{info.paymentStatus.newTerms.storageLimitInMegabytes}</td> + </tr> + </tbody> + </table> + </div>} + + </section> + <footer> + <Button onClick={onBack}><i18n.Translate> < 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> ) } |