aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/popup
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-11-15 11:18:58 -0300
committerSebastian <sebasjm@gmail.com>2021-11-15 11:18:58 -0300
commit1d4815c66c395f4fcc86c30e20f3d005e3cb9ff5 (patch)
tree99e8241a5eb5af4d752be93a460004bc0c6255aa /packages/taler-wallet-webextension/src/popup
parent9692f589c687a2ba39a705ca4238cf123f444c61 (diff)
downloadwallet-core-1d4815c66c395f4fcc86c30e20f3d005e3cb9ff5.tar.xz
prettier
Diffstat (limited to 'packages/taler-wallet-webextension/src/popup')
-rw-r--r--packages/taler-wallet-webextension/src/popup/Backup.stories.tsx307
-rw-r--r--packages/taler-wallet-webextension/src/popup/BackupPage.tsx176
-rw-r--r--packages/taler-wallet-webextension/src/popup/Balance.stories.tsx253
-rw-r--r--packages/taler-wallet-webextension/src/popup/BalancePage.tsx219
-rw-r--r--packages/taler-wallet-webextension/src/popup/Debug.tsx8
-rw-r--r--packages/taler-wallet-webextension/src/popup/History.stories.tsx184
-rw-r--r--packages/taler-wallet-webextension/src/popup/History.tsx122
-rw-r--r--packages/taler-wallet-webextension/src/popup/Popup.stories.tsx29
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderAddConfirmProvider.stories.tsx41
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderAddSetUrl.stories.tsx40
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderDetail.stories.tsx323
-rw-r--r--packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx269
-rw-r--r--packages/taler-wallet-webextension/src/popup/Settings.stories.tsx19
-rw-r--r--packages/taler-wallet-webextension/src/popup/Settings.tsx93
-rw-r--r--packages/taler-wallet-webextension/src/popup/TalerActionFound.stories.tsx24
-rw-r--r--packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx161
16 files changed, 1310 insertions, 958 deletions
diff --git a/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx b/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx
index d256f6d98..232b0da73 100644
--- a/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Backup.stories.tsx
@@ -15,179 +15,184 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { ProviderPaymentType } from '@gnu-taler/taler-wallet-core';
-import { addDays } from 'date-fns';
-import { BackupView as TestedComponent } from './BackupPage';
-import { createExample } from '../test-utils';
+import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
+import { addDays } from "date-fns";
+import { BackupView as TestedComponent } from "./BackupPage";
+import { createExample } from "../test-utils";
export default {
- title: 'popup/backup/list',
+ title: "popup/backup/list",
component: TestedComponent,
argTypes: {
- onRetry: { action: 'onRetry' },
- onDelete: { action: 'onDelete' },
- onBack: { action: 'onBack' },
- }
+ onRetry: { action: "onRetry" },
+ onDelete: { action: "onDelete" },
+ onBack: { action: "onBack" },
+ },
};
-
export const LotOfProviders = createExample(TestedComponent, {
- providers: [{
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
- },
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
- ],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": 1656599921000
- }
- },
- "terms": {
- "annualFee": "ARS:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }, {
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
+ providers: [
+ {
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
+ },
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
+ ],
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: 1656599921000,
+ },
+ },
+ terms: {
+ annualFee: "ARS:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
- ],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": addDays(new Date(), 13).getTime()
- }
+ {
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
+ },
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
+ ],
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: addDays(new Date(), 13).getTime(),
+ },
+ },
+ terms: {
+ annualFee: "ARS:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "terms": {
- "annualFee": "ARS:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }, {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.Pending,
+ {
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.Pending,
+ },
+ terms: {
+ annualFee: "KUDOS:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "terms": {
- "annualFee": "KUDOS:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }, {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.InsufficientBalance,
+ {
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.InsufficientBalance,
+ },
+ terms: {
+ annualFee: "KUDOS:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "terms": {
- "annualFee": "KUDOS:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }, {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.TermsChanged,
- newTerms: {
- annualFee: 'USD:2',
- storageLimitInMegabytes: 8,
- supportedProtocolVersion: '2',
- },
- oldTerms: {
- annualFee: 'USD:1',
+ {
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.TermsChanged,
+ newTerms: {
+ annualFee: "USD:2",
+ storageLimitInMegabytes: 8,
+ supportedProtocolVersion: "2",
+ },
+ oldTerms: {
+ annualFee: "USD:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "1",
+ },
+ paidUntil: {
+ t_ms: "never",
+ },
+ },
+ terms: {
+ annualFee: "KUDOS:0.1",
storageLimitInMegabytes: 16,
- supportedProtocolVersion: '1',
-
+ supportedProtocolVersion: "0.0",
},
- paidUntil: {
- t_ms: 'never'
- }
},
- "terms": {
- "annualFee": "KUDOS:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }, {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.Unpaid,
+ {
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.Unpaid,
+ },
+ terms: {
+ annualFee: "KUDOS:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "terms": {
- "annualFee": "KUDOS:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }, {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.Unpaid,
+ {
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.Unpaid,
+ },
+ terms: {
+ annualFee: "KUDOS:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "terms": {
- "annualFee": "KUDOS:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }]
+ ],
});
-
export const OneProvider = createExample(TestedComponent, {
- providers: [{
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
- },
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
- ],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": 1656599921000
- }
+ providers: [
+ {
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
+ },
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
+ ],
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: 1656599921000,
+ },
+ },
+ terms: {
+ annualFee: "ARS:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
},
- "terms": {
- "annualFee": "ARS:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }]
+ ],
});
-
export const Empty = createExample(TestedComponent, {
- providers: []
+ providers: [],
});
-
diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
index dcc5e5313..894c8a791 100644
--- a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
@@ -14,15 +14,28 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-
import { i18n, Timestamp } from "@gnu-taler/taler-util";
-import { ProviderInfo, ProviderPaymentStatus } from "@gnu-taler/taler-wallet-core";
-import { differenceInMonths, formatDuration, intervalToDuration } from "date-fns";
+import {
+ ProviderInfo,
+ ProviderPaymentStatus,
+} from "@gnu-taler/taler-wallet-core";
+import {
+ differenceInMonths,
+ formatDuration,
+ intervalToDuration,
+} from "date-fns";
import { Fragment, JSX, VNode, h } from "preact";
import {
- BoldLight, ButtonPrimary, ButtonSuccess, Centered,
- CenteredText, CenteredBoldText, PopupBox, RowBorderGray,
- SmallText, SmallLightText
+ BoldLight,
+ ButtonPrimary,
+ ButtonSuccess,
+ Centered,
+ CenteredText,
+ CenteredBoldText,
+ PopupBox,
+ RowBorderGray,
+ SmallText,
+ SmallLightText,
} from "../components/styled";
import { useBackupStatus } from "../hooks/useBackupStatus";
import { Pages } from "../NavigationBar";
@@ -32,49 +45,68 @@ interface Props {
}
export function BackupPage({ onAddProvider }: Props): VNode {
- const status = useBackupStatus()
+ const status = useBackupStatus();
if (!status) {
- return <div>Loading...</div>
+ return <div>Loading...</div>;
}
- return <BackupView providers={status.providers} onAddProvider={onAddProvider} onSyncAll={status.sync} />;
+ return (
+ <BackupView
+ providers={status.providers}
+ onAddProvider={onAddProvider}
+ onSyncAll={status.sync}
+ />
+ );
}
export interface ViewProps {
- providers: ProviderInfo[],
+ providers: ProviderInfo[];
onAddProvider: () => void;
onSyncAll: () => Promise<void>;
}
-export function BackupView({ providers, onAddProvider, onSyncAll }: ViewProps): VNode {
+export function BackupView({
+ providers,
+ onAddProvider,
+ onSyncAll,
+}: ViewProps): VNode {
return (
<PopupBox>
<section>
- {providers.map((provider) => <BackupLayout
- status={provider.paymentStatus}
- timestamp={provider.lastSuccessfulBackupTimestamp}
- id={provider.syncProviderBaseUrl}
- active={provider.active}
- title={provider.name}
- />
+ {providers.map((provider) => (
+ <BackupLayout
+ status={provider.paymentStatus}
+ timestamp={provider.lastSuccessfulBackupTimestamp}
+ id={provider.syncProviderBaseUrl}
+ active={provider.active}
+ title={provider.name}
+ />
+ ))}
+ {!providers.length && (
+ <Centered style={{ marginTop: 100 }}>
+ <BoldLight>No backup providers configured</BoldLight>
+ <ButtonSuccess onClick={onAddProvider}>
+ <i18n.Translate>Add provider</i18n.Translate>
+ </ButtonSuccess>
+ </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>
- <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>}
+ {!!providers.length && (
+ <footer>
+ <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>
- )
+ );
}
interface TransactionLayoutProps {
@@ -92,55 +124,73 @@ function BackupLayout(props: TransactionLayoutProps): JSX.Element {
timeStyle: "short",
} as any);
-
return (
<RowBorderGray>
<div style={{ color: !props.active ? "grey" : undefined }}>
- <a href={Pages.provider_detail.replace(':pid', encodeURIComponent(props.id))}><span>{props.title}</span></a>
-
- {dateStr && <SmallText style={{marginTop: 5}}>Last synced: {dateStr}</SmallText>}
- {!dateStr && <SmallLightText style={{marginTop: 5}}>Not synced</SmallLightText>}
+ <a
+ href={Pages.provider_detail.replace(
+ ":pid",
+ encodeURIComponent(props.id),
+ )}
+ >
+ <span>{props.title}</span>
+ </a>
+
+ {dateStr && (
+ <SmallText style={{ marginTop: 5 }}>Last synced: {dateStr}</SmallText>
+ )}
+ {!dateStr && (
+ <SmallLightText style={{ marginTop: 5 }}>Not synced</SmallLightText>
+ )}
</div>
<div>
- {props.status?.type === 'paid' ?
- <ExpirationText until={props.status.paidUntil} /> :
+ {props.status?.type === "paid" ? (
+ <ExpirationText until={props.status.paidUntil} />
+ ) : (
<div>{props.status.type}</div>
- }
+ )}
</div>
</RowBorderGray>
);
}
function ExpirationText({ until }: { until: Timestamp }) {
- return <Fragment>
- <CenteredText> Expires in </CenteredText>
- <CenteredBoldText {...({ color: colorByTimeToExpire(until) })}> {daysUntil(until)} </CenteredBoldText>
- </Fragment>
+ return (
+ <Fragment>
+ <CenteredText> Expires in </CenteredText>
+ <CenteredBoldText {...{ color: colorByTimeToExpire(until) }}>
+ {" "}
+ {daysUntil(until)}{" "}
+ </CenteredBoldText>
+ </Fragment>
+ );
}
function colorByTimeToExpire(d: Timestamp) {
- if (d.t_ms === 'never') return 'rgb(28, 184, 65)'
- const months = differenceInMonths(d.t_ms, new Date())
- return months > 1 ? 'rgb(28, 184, 65)' : 'rgb(223, 117, 20)';
+ if (d.t_ms === "never") return "rgb(28, 184, 65)";
+ const months = differenceInMonths(d.t_ms, new Date());
+ return months > 1 ? "rgb(28, 184, 65)" : "rgb(223, 117, 20)";
}
function daysUntil(d: Timestamp) {
- if (d.t_ms === 'never') return undefined
+ if (d.t_ms === "never") return undefined;
const duration = intervalToDuration({
start: d.t_ms,
end: new Date(),
- })
+ });
const str = formatDuration(duration, {
- delimiter: ', ',
+ delimiter: ", ",
format: [
- duration?.years ? 'years' : (
- duration?.months ? 'months' : (
- duration?.days ? 'days' : (
- duration.hours ? 'hours' : 'minutes'
- )
- )
- )
- ]
- })
- return `${str}`
-} \ No newline at end of file
+ duration?.years
+ ? "years"
+ : duration?.months
+ ? "months"
+ : duration?.days
+ ? "days"
+ : duration.hours
+ ? "hours"
+ : "minutes",
+ ],
+ });
+ return `${str}`;
+}
diff --git a/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx b/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx
index 382f9b549..80203f6d3 100644
--- a/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx
@@ -15,28 +15,25 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { createExample, NullLink } from '../test-utils';
-import { BalanceView as TestedComponent } from './BalancePage';
+import { createExample, NullLink } from "../test-utils";
+import { BalanceView as TestedComponent } from "./BalancePage";
export default {
- title: 'popup/balance',
+ title: "popup/balance",
component: TestedComponent,
- argTypes: {
- }
+ argTypes: {},
};
-
-export const NotYetLoaded = createExample(TestedComponent, {
-});
+export const NotYetLoaded = createExample(TestedComponent, {});
export const GotError = createExample(TestedComponent, {
balance: {
hasError: true,
- message: 'Network error'
+ message: "Network error",
},
Linker: NullLink,
});
@@ -45,7 +42,7 @@ export const EmptyBalance = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: []
+ balances: [],
},
},
Linker: NullLink,
@@ -55,13 +52,15 @@ export const SomeCoins = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:10.5',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:10.5",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
@@ -71,13 +70,15 @@ export const SomeCoinsAndIncomingMoney = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:2.23',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:5.11',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:2.23",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:5.11",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
@@ -87,13 +88,15 @@ export const SomeCoinsAndOutgoingMoney = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:2.23',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:5.11',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:2.23",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:5.11",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
@@ -103,13 +106,15 @@ export const SomeCoinsAndMovingMoney = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:2.23',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:2',
- pendingOutgoing: 'USD:5.11',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:2.23",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:2",
+ pendingOutgoing: "USD:5.11",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
@@ -119,19 +124,22 @@ export const SomeCoinsInTwoCurrencies = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:2',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:5.1',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- },{
- available: 'EUR:4',
- hasPendingTransactions: false,
- pendingIncoming: 'EUR:0',
- pendingOutgoing: 'EUR:3.01',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:2",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:5.1",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "EUR:4",
+ hasPendingTransactions: false,
+ pendingIncoming: "EUR:0",
+ pendingOutgoing: "EUR:3.01",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
@@ -141,78 +149,89 @@ export const SomeCoinsInTreeCurrencies = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:1',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- },{
- available: 'COL:2000',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- },{
- available: 'EUR:4',
- hasPendingTransactions: false,
- pendingIncoming: 'EUR:15',
- pendingOutgoing: 'EUR:0',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:1",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "COL:2000",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "EUR:4",
+ hasPendingTransactions: false,
+ pendingIncoming: "EUR:15",
+ pendingOutgoing: "EUR:0",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
});
-
export const SomeCoinsInFiveCurrencies = createExample(TestedComponent, {
balance: {
hasError: false,
response: {
- balances: [{
- available: 'USD:13451',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- },{
- available: 'EUR:202.02',
- hasPendingTransactions: false,
- pendingIncoming: 'EUR:0',
- pendingOutgoing: 'EUR:0',
- requiresUserInput: false
- },{
- available: 'ARS:30',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- },{
- available: 'JPY:51223233',
- hasPendingTransactions: false,
- pendingIncoming: 'EUR:0',
- pendingOutgoing: 'EUR:0',
- requiresUserInput: false
- },{
- available: 'JPY:51223233',
- hasPendingTransactions: false,
- pendingIncoming: 'EUR:0',
- pendingOutgoing: 'EUR:0',
- requiresUserInput: false
- },{
- available: 'DEMOKUDOS:6',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- },{
- available: 'TESTKUDOS:6',
- hasPendingTransactions: false,
- pendingIncoming: 'USD:5',
- pendingOutgoing: 'USD:0',
- requiresUserInput: false
- }]
+ balances: [
+ {
+ available: "USD:13451",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "EUR:202.02",
+ hasPendingTransactions: false,
+ pendingIncoming: "EUR:0",
+ pendingOutgoing: "EUR:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "ARS:30",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "JPY:51223233",
+ hasPendingTransactions: false,
+ pendingIncoming: "EUR:0",
+ pendingOutgoing: "EUR:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "JPY:51223233",
+ hasPendingTransactions: false,
+ pendingIncoming: "EUR:0",
+ pendingOutgoing: "EUR:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "DEMOKUDOS:6",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ {
+ available: "TESTKUDOS:6",
+ hasPendingTransactions: false,
+ pendingIncoming: "USD:5",
+ pendingOutgoing: "USD:0",
+ requiresUserInput: false,
+ },
+ ],
},
},
Linker: NullLink,
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
index 8e5c5c42e..2913f60e0 100644
--- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -15,20 +15,37 @@
*/
import {
- amountFractionalBase, Amounts,
- Balance, BalancesResponse,
- i18n
+ amountFractionalBase,
+ Amounts,
+ Balance,
+ BalancesResponse,
+ i18n,
} from "@gnu-taler/taler-util";
import { JSX, h, Fragment } from "preact";
import { ErrorMessage } from "../components/ErrorMessage";
-import { PopupBox, Centered, ButtonPrimary, ErrorBox, Middle } from "../components/styled/index";
+import {
+ PopupBox,
+ Centered,
+ ButtonPrimary,
+ ErrorBox,
+ Middle,
+} from "../components/styled/index";
import { BalancesHook, useBalances } from "../hooks/useBalances";
import { PageLink, renderAmount } from "../renderHtml";
-
-export function BalancePage({ goToWalletManualWithdraw }: { goToWalletManualWithdraw: () => void }) {
- const balance = useBalances()
- return <BalanceView balance={balance} Linker={PageLink} goToWalletManualWithdraw={goToWalletManualWithdraw} />
+export function BalancePage({
+ goToWalletManualWithdraw,
+}: {
+ goToWalletManualWithdraw: () => void;
+}) {
+ const balance = useBalances();
+ return (
+ <BalanceView
+ balance={balance}
+ Linker={PageLink}
+ goToWalletManualWithdraw={goToWalletManualWithdraw}
+ />
+ );
}
export interface BalanceViewProps {
balance: BalancesHook;
@@ -46,22 +63,26 @@ function formatPending(entry: Balance): JSX.Element {
if (!Amounts.isZero(pendingIncoming)) {
incoming = (
- <span><i18n.Translate>
- <span style={{ color: "darkgreen" }} title="incoming amount">
- {"+"}
- {renderAmount(entry.pendingIncoming)}
- </span>{" "}
- </i18n.Translate></span>
+ <span>
+ <i18n.Translate>
+ <span style={{ color: "darkgreen" }} title="incoming amount">
+ {"+"}
+ {renderAmount(entry.pendingIncoming)}
+ </span>{" "}
+ </i18n.Translate>
+ </span>
);
}
if (!Amounts.isZero(pendingOutgoing)) {
payment = (
- <span><i18n.Translate>
- <span style={{ color: "darkred" }} title="outgoing amount">
- {"-"}
- {renderAmount(entry.pendingOutgoing)}
- </span>{" "}
- </i18n.Translate></span>
+ <span>
+ <i18n.Translate>
+ <span style={{ color: "darkred" }} title="outgoing amount">
+ {"-"}
+ {renderAmount(entry.pendingOutgoing)}
+ </span>{" "}
+ </i18n.Translate>
+ </span>
);
}
@@ -80,76 +101,110 @@ function formatPending(entry: Balance): JSX.Element {
);
}
-
-export function BalanceView({ balance, Linker, goToWalletManualWithdraw }: BalanceViewProps) {
-
+export function BalanceView({
+ balance,
+ Linker,
+ goToWalletManualWithdraw,
+}: BalanceViewProps) {
function Content() {
if (!balance) {
- return <span />
+ return <span />;
}
if (balance.hasError) {
- return (<section>
- <ErrorBox>{balance.message}</ErrorBox>
- <p>
- Click <Linker pageName="welcome">here</Linker> for help and
- diagnostics.
- </p>
- </section>)
+ return (
+ <section>
+ <ErrorBox>{balance.message}</ErrorBox>
+ <p>
+ Click <Linker pageName="welcome">here</Linker> for help and
+ diagnostics.
+ </p>
+ </section>
+ );
}
if (balance.response.balances.length === 0) {
- return (<section data-expanded>
- <Middle>
- <p><i18n.Translate>
- You have no balance to show. Need some{" "}
- <Linker pageName="/welcome">help</Linker> getting started?
- </i18n.Translate></p>
- </Middle>
- </section>)
+ return (
+ <section data-expanded>
+ <Middle>
+ <p>
+ <i18n.Translate>
+ You have no balance to show. Need some{" "}
+ <Linker pageName="/welcome">help</Linker> getting started?
+ </i18n.Translate>
+ </p>
+ </Middle>
+ </section>
+ );
}
- return <section data-expanded data-centered>
- <table style={{width:'100%'}}>{balance.response.balances.map((entry) => {
- const av = Amounts.parseOrThrow(entry.available);
- // Create our number formatter.
- let formatter;
- try {
- formatter = new Intl.NumberFormat('en-US', {
- style: 'currency',
- currency: av.currency,
- currencyDisplay: 'symbol'
- // These options are needed to round to whole numbers if that's what you want.
- //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
- //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
- });
- } catch {
- formatter = new Intl.NumberFormat('en-US', {
- // style: 'currency',
- // currency: av.currency,
- // These options are needed to round to whole numbers if that's what you want.
- //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
- //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
- });
- }
-
- const v = formatter.format(av.value + av.fraction / amountFractionalBase);
- const fontSize = v.length < 8 ? '3em' : (v.length < 13 ? '2em' : '1em')
- return (<tr>
- <td style={{ height: 50, fontSize, width: '60%', textAlign: 'right', padding: 0 }}>{v}</td>
- <td style={{ maxWidth: '2em', overflowX: 'hidden' }}>{av.currency}</td>
- <td style={{ fontSize: 'small', color: 'gray' }}>{formatPending(entry)}</td>
- </tr>
- );
- })}</table>
- </section>
+ return (
+ <section data-expanded data-centered>
+ <table style={{ width: "100%" }}>
+ {balance.response.balances.map((entry) => {
+ const av = Amounts.parseOrThrow(entry.available);
+ // Create our number formatter.
+ let formatter;
+ try {
+ formatter = new Intl.NumberFormat("en-US", {
+ style: "currency",
+ currency: av.currency,
+ currencyDisplay: "symbol",
+ // These options are needed to round to whole numbers if that's what you want.
+ //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
+ //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
+ });
+ } catch {
+ formatter = new Intl.NumberFormat("en-US", {
+ // style: 'currency',
+ // currency: av.currency,
+ // These options are needed to round to whole numbers if that's what you want.
+ //minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
+ //maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
+ });
+ }
+
+ const v = formatter.format(
+ av.value + av.fraction / amountFractionalBase,
+ );
+ const fontSize =
+ v.length < 8 ? "3em" : v.length < 13 ? "2em" : "1em";
+ return (
+ <tr>
+ <td
+ style={{
+ height: 50,
+ fontSize,
+ width: "60%",
+ textAlign: "right",
+ padding: 0,
+ }}
+ >
+ {v}
+ </td>
+ <td style={{ maxWidth: "2em", overflowX: "hidden" }}>
+ {av.currency}
+ </td>
+ <td style={{ fontSize: "small", color: "gray" }}>
+ {formatPending(entry)}
+ </td>
+ </tr>
+ );
+ })}
+ </table>
+ </section>
+ );
}
- return <PopupBox>
- {/* <section> */}
- <Content />
- {/* </section> */}
- <footer>
- <div />
- <ButtonPrimary onClick={goToWalletManualWithdraw}>Withdraw</ButtonPrimary>
- </footer>
- </PopupBox>
+ return (
+ <PopupBox>
+ {/* <section> */}
+ <Content />
+ {/* </section> */}
+ <footer>
+ <div />
+ <ButtonPrimary onClick={goToWalletManualWithdraw}>
+ Withdraw
+ </ButtonPrimary>
+ </footer>
+ </PopupBox>
+ );
}
diff --git a/packages/taler-wallet-webextension/src/popup/Debug.tsx b/packages/taler-wallet-webextension/src/popup/Debug.tsx
index ccc747466..8722c1cf8 100644
--- a/packages/taler-wallet-webextension/src/popup/Debug.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Debug.tsx
@@ -19,13 +19,14 @@ import { Diagnostics } from "../components/Diagnostics";
import { useDiagnostics } from "../hooks/useDiagnostics.js";
import * as wxApi from "../wxApi";
-
export function DeveloperPage(props: any): JSX.Element {
const [status, timedOut] = useDiagnostics();
return (
<div>
<p>Debug tools:</p>
- <button onClick={openExtensionPage("/static/popup.html")}>wallet tab</button>
+ <button onClick={openExtensionPage("/static/popup.html")}>
+ wallet tab
+ </button>
<br />
<button onClick={confirmReset}>reset</button>
<Diagnostics diagnostics={status} timedOut={timedOut} />
@@ -46,7 +47,7 @@ export async function confirmReset(): Promise<void> {
if (
confirm(
"Do you want to IRREVOCABLY DESTROY everything inside your" +
- " wallet and LOSE ALL YOUR COINS?",
+ " wallet and LOSE ALL YOUR COINS?",
)
) {
await wxApi.resetDb();
@@ -61,4 +62,3 @@ export function openExtensionPage(page: string) {
});
};
}
-
diff --git a/packages/taler-wallet-webextension/src/popup/History.stories.tsx b/packages/taler-wallet-webextension/src/popup/History.stories.tsx
index daa263a81..95f4a547a 100644
--- a/packages/taler-wallet-webextension/src/popup/History.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/History.stories.tsx
@@ -15,135 +15,149 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
import {
PaymentStatus,
- TransactionCommon, TransactionDeposit, TransactionPayment,
- TransactionRefresh, TransactionRefund, TransactionTip, TransactionType,
+ TransactionCommon,
+ TransactionDeposit,
+ TransactionPayment,
+ TransactionRefresh,
+ TransactionRefund,
+ TransactionTip,
+ TransactionType,
TransactionWithdrawal,
- WithdrawalType
-} from '@gnu-taler/taler-util';
-import { createExample } from '../test-utils';
-import { HistoryView as TestedComponent } from './History';
+ WithdrawalType,
+} from "@gnu-taler/taler-util";
+import { createExample } from "../test-utils";
+import { HistoryView as TestedComponent } from "./History";
export default {
- title: 'popup/history/list',
+ title: "popup/history/list",
component: TestedComponent,
};
const commonTransaction = {
- amountRaw: 'USD:10',
- amountEffective: 'USD:9',
+ amountRaw: "USD:10",
+ amountEffective: "USD:9",
pending: false,
timestamp: {
- t_ms: new Date().getTime()
+ t_ms: new Date().getTime(),
},
- transactionId: '12',
-} as TransactionCommon
+ transactionId: "12",
+} as TransactionCommon;
const exampleData = {
withdraw: {
...commonTransaction,
type: TransactionType.Withdrawal,
- exchangeBaseUrl: 'http://exchange.demo.taler.net',
+ exchangeBaseUrl: "http://exchange.demo.taler.net",
withdrawalDetails: {
confirmed: false,
- exchangePaytoUris: ['payto://x-taler-bank/bank/account'],
+ exchangePaytoUris: ["payto://x-taler-bank/bank/account"],
type: WithdrawalType.ManualTransfer,
- }
+ },
} as TransactionWithdrawal,
payment: {
...commonTransaction,
- amountEffective: 'USD:11',
+ amountEffective: "USD:11",
type: TransactionType.Payment,
info: {
- contractTermsHash: 'ASDZXCASD',
+ contractTermsHash: "ASDZXCASD",
merchant: {
- name: 'the merchant',
+ name: "the merchant",
},
- orderId: '2021.167-03NPY6MCYMVGT',
+ orderId: "2021.167-03NPY6MCYMVGT",
products: [],
- summary: 'the summary',
- fulfillmentMessage: '',
+ summary: "the summary",
+ fulfillmentMessage: "",
},
- proposalId: '1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0',
+ proposalId: "1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0",
status: PaymentStatus.Accepted,
} as TransactionPayment,
deposit: {
...commonTransaction,
type: TransactionType.Deposit,
- depositGroupId: '#groupId',
- targetPaytoUri: 'payto://x-taler-bank/bank/account',
+ depositGroupId: "#groupId",
+ targetPaytoUri: "payto://x-taler-bank/bank/account",
} as TransactionDeposit,
refresh: {
...commonTransaction,
type: TransactionType.Refresh,
- exchangeBaseUrl: 'http://exchange.taler',
+ exchangeBaseUrl: "http://exchange.taler",
} as TransactionRefresh,
tip: {
...commonTransaction,
type: TransactionType.Tip,
- merchantBaseUrl: 'http://merchant.taler',
+ merchantBaseUrl: "http://merchant.taler",
} as TransactionTip,
refund: {
...commonTransaction,
type: TransactionType.Refund,
- refundedTransactionId: 'payment:1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0',
+ refundedTransactionId:
+ "payment:1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0",
info: {
- contractTermsHash: 'ASDZXCASD',
+ contractTermsHash: "ASDZXCASD",
merchant: {
- name: 'the merchant',
+ name: "the merchant",
},
- orderId: '2021.167-03NPY6MCYMVGT',
+ orderId: "2021.167-03NPY6MCYMVGT",
products: [],
- summary: 'the summary',
- fulfillmentMessage: '',
+ summary: "the summary",
+ fulfillmentMessage: "",
},
} as TransactionRefund,
-}
+};
export const EmptyWithBalance = createExample(TestedComponent, {
list: [],
- balances: [{
- available: 'TESTKUDOS:10',
- pendingIncoming: 'TESTKUDOS:0',
- pendingOutgoing: 'TESTKUDOS:0',
- hasPendingTransactions: false,
- requiresUserInput: false,
- }]
+ balances: [
+ {
+ available: "TESTKUDOS:10",
+ pendingIncoming: "TESTKUDOS:0",
+ pendingOutgoing: "TESTKUDOS:0",
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ },
+ ],
});
export const EmptyWithNoBalance = createExample(TestedComponent, {
list: [],
- balances: []
+ balances: [],
});
export const One = createExample(TestedComponent, {
list: [exampleData.withdraw],
- balances: [{
- available: 'USD:10',
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- hasPendingTransactions: false,
- requiresUserInput: false,
- }]
+ balances: [
+ {
+ available: "USD:10",
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ },
+ ],
});
export const OnePending = createExample(TestedComponent, {
- list: [{
- ...exampleData.withdraw,
- pending: true,
- }],
- balances: [{
- available: 'USD:10',
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- hasPendingTransactions: false,
- requiresUserInput: false,
- }]
+ list: [
+ {
+ ...exampleData.withdraw,
+ pending: true,
+ },
+ ],
+ balances: [
+ {
+ available: "USD:10",
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ },
+ ],
});
export const Several = createExample(TestedComponent, {
@@ -157,13 +171,15 @@ export const Several = createExample(TestedComponent, {
exampleData.tip,
exampleData.deposit,
],
- balances: [{
- available: 'TESTKUDOS:10',
- pendingIncoming: 'TESTKUDOS:0',
- pendingOutgoing: 'TESTKUDOS:0',
- hasPendingTransactions: false,
- requiresUserInput: false,
- }]
+ balances: [
+ {
+ available: "TESTKUDOS:10",
+ pendingIncoming: "TESTKUDOS:0",
+ pendingOutgoing: "TESTKUDOS:0",
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ },
+ ],
});
export const SeveralWithTwoCurrencies = createExample(TestedComponent, {
@@ -177,18 +193,20 @@ export const SeveralWithTwoCurrencies = createExample(TestedComponent, {
exampleData.tip,
exampleData.deposit,
],
- balances: [{
- available: 'TESTKUDOS:10',
- pendingIncoming: 'TESTKUDOS:0',
- pendingOutgoing: 'TESTKUDOS:0',
- hasPendingTransactions: false,
- requiresUserInput: false,
- }, {
- available: 'USD:10',
- pendingIncoming: 'USD:0',
- pendingOutgoing: 'USD:0',
- hasPendingTransactions: false,
- requiresUserInput: false,
- }]
+ balances: [
+ {
+ available: "TESTKUDOS:10",
+ pendingIncoming: "TESTKUDOS:0",
+ pendingOutgoing: "TESTKUDOS:0",
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ },
+ {
+ available: "USD:10",
+ pendingIncoming: "USD:0",
+ pendingOutgoing: "USD:0",
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ },
+ ],
});
-
diff --git a/packages/taler-wallet-webextension/src/popup/History.tsx b/packages/taler-wallet-webextension/src/popup/History.tsx
index 1447da9b0..8fe6de16c 100644
--- a/packages/taler-wallet-webextension/src/popup/History.tsx
+++ b/packages/taler-wallet-webextension/src/popup/History.tsx
@@ -14,7 +14,13 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { AmountString, Balance, i18n, Transaction, TransactionsResponse } from "@gnu-taler/taler-util";
+import {
+ AmountString,
+ Balance,
+ i18n,
+ Transaction,
+ TransactionsResponse,
+} from "@gnu-taler/taler-util";
import { h, JSX } from "preact";
import { useEffect, useState } from "preact/hooks";
import { PopupBox } from "../components/styled";
@@ -22,13 +28,14 @@ import { TransactionItem } from "../components/TransactionItem";
import { useBalances } from "../hooks/useBalances";
import * as wxApi from "../wxApi";
-
export function HistoryPage(props: any): JSX.Element {
const [transactions, setTransactions] = useState<
TransactionsResponse | undefined
>(undefined);
- const balance = useBalances()
- const balanceWithoutError = balance?.hasError ? [] : (balance?.response.balances || [])
+ const balance = useBalances();
+ const balanceWithoutError = balance?.hasError
+ ? []
+ : balance?.response.balances || [];
useEffect(() => {
const fetchData = async (): Promise<void> => {
@@ -42,46 +49,79 @@ export function HistoryPage(props: any): JSX.Element {
return <div>Loading ...</div>;
}
- return <HistoryView balances={balanceWithoutError} list={[...transactions.transactions].reverse()} />;
+ return (
+ <HistoryView
+ balances={balanceWithoutError}
+ list={[...transactions.transactions].reverse()}
+ />
+ );
}
function amountToString(c: AmountString) {
- const idx = c.indexOf(':')
- return `${c.substring(idx + 1)} ${c.substring(0, idx)}`
+ const idx = c.indexOf(":");
+ return `${c.substring(idx + 1)} ${c.substring(0, idx)}`;
}
-
-
-export function HistoryView({ list, balances }: { list: Transaction[], balances: Balance[] }) {
- const multiCurrency = balances.length > 1
- return <PopupBox noPadding>
- {balances.length > 0 && <header>
- {multiCurrency ? <div class="title">
- Balance: <ul style={{ margin: 0 }}>
- {balances.map(b => <li>{b.available}</li>)}
- </ul>
- </div> : <div class="title">
- Balance: <span>{amountToString(balances[0].available)}</span>
- </div>}
- </header>}
- {list.length === 0 ? <section data-expanded data-centered>
- <p><i18n.Translate>
- You have no history yet, here you will be able to check your last transactions.
- </i18n.Translate></p>
- </section> :
- <section>
- {list.slice(0, 3).map((tx, i) => (
- <TransactionItem key={i} tx={tx} multiCurrency={multiCurrency} />
- ))}
- </section>
- }
- <footer style={{ justifyContent: 'space-around' }}>
- {list.length > 0 &&
- <a target="_blank"
- rel="noopener noreferrer"
- style={{ color: 'darkgreen', textDecoration: 'none' }}
- href={chrome.extension ? chrome.extension.getURL(`/static/wallet.html#/history`) : '#'}>VIEW MORE TRANSACTIONS</a>
- }
- </footer>
- </PopupBox>
+export function HistoryView({
+ list,
+ balances,
+}: {
+ list: Transaction[];
+ balances: Balance[];
+}) {
+ const multiCurrency = balances.length > 1;
+ return (
+ <PopupBox noPadding>
+ {balances.length > 0 && (
+ <header>
+ {multiCurrency ? (
+ <div class="title">
+ Balance:{" "}
+ <ul style={{ margin: 0 }}>
+ {balances.map((b) => (
+ <li>{b.available}</li>
+ ))}
+ </ul>
+ </div>
+ ) : (
+ <div class="title">
+ Balance: <span>{amountToString(balances[0].available)}</span>
+ </div>
+ )}
+ </header>
+ )}
+ {list.length === 0 ? (
+ <section data-expanded data-centered>
+ <p>
+ <i18n.Translate>
+ You have no history yet, here you will be able to check your last
+ transactions.
+ </i18n.Translate>
+ </p>
+ </section>
+ ) : (
+ <section>
+ {list.slice(0, 3).map((tx, i) => (
+ <TransactionItem key={i} tx={tx} multiCurrency={multiCurrency} />
+ ))}
+ </section>
+ )}
+ <footer style={{ justifyContent: "space-around" }}>
+ {list.length > 0 && (
+ <a
+ target="_blank"
+ rel="noopener noreferrer"
+ style={{ color: "darkgreen", textDecoration: "none" }}
+ href={
+ chrome.extension
+ ? chrome.extension.getURL(`/static/wallet.html#/history`)
+ : "#"
+ }
+ >
+ VIEW MORE TRANSACTIONS
+ </a>
+ )}
+ </footer>
+ </PopupBox>
+ );
}
diff --git a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx
index cd443e9d4..5009684c5 100644
--- a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx
@@ -15,30 +15,29 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { createExample } from '../test-utils';
-import { NavBar as TestedComponent } from '../NavigationBar';
+import { createExample } from "../test-utils";
+import { NavBar as TestedComponent } from "../NavigationBar";
export default {
- title: 'popup/header',
+ title: "popup/header",
// component: TestedComponent,
argTypes: {
- onRetry: { action: 'onRetry' },
- onDelete: { action: 'onDelete' },
- onBack: { action: 'onBack' },
- }
+ onRetry: { action: "onRetry" },
+ onDelete: { action: "onDelete" },
+ onBack: { action: "onBack" },
+ },
};
-
export const OnBalance = createExample(TestedComponent, {
- devMode:false,
- path:'/balance'
+ devMode: false,
+ path: "/balance",
});
export const OnHistoryWithDevMode = createExample(TestedComponent, {
- devMode:true,
- path:'/history'
+ devMode: true,
+ path: "/history",
});
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderAddConfirmProvider.stories.tsx b/packages/taler-wallet-webextension/src/popup/ProviderAddConfirmProvider.stories.tsx
index de1f67b96..0cff7f75f 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderAddConfirmProvider.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderAddConfirmProvider.stories.tsx
@@ -15,38 +15,37 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { createExample } from '../test-utils';
-import { ConfirmProviderView as TestedComponent } from './ProviderAddPage';
+import { createExample } from "../test-utils";
+import { ConfirmProviderView as TestedComponent } from "./ProviderAddPage";
export default {
- title: 'popup/backup/confirm',
+ title: "popup/backup/confirm",
component: TestedComponent,
argTypes: {
- onRetry: { action: 'onRetry' },
- onDelete: { action: 'onDelete' },
- onBack: { action: 'onBack' },
- }
+ onRetry: { action: "onRetry" },
+ onDelete: { action: "onDelete" },
+ onBack: { action: "onBack" },
+ },
};
-
export const DemoService = createExample(TestedComponent, {
- url: 'https://sync.demo.taler.net/',
+ url: "https://sync.demo.taler.net/",
provider: {
- annual_fee: 'KUDOS:0.1',
- storage_limit_in_megabytes: 20,
- supported_protocol_version: '1'
- }
+ annual_fee: "KUDOS:0.1",
+ storage_limit_in_megabytes: 20,
+ supported_protocol_version: "1",
+ },
});
export const FreeService = createExample(TestedComponent, {
- url: 'https://sync.taler:9667/',
+ url: "https://sync.taler:9667/",
provider: {
- annual_fee: 'ARS:0',
- storage_limit_in_megabytes: 20,
- supported_protocol_version: '1'
- }
+ annual_fee: "ARS:0",
+ storage_limit_in_megabytes: 20,
+ supported_protocol_version: "1",
+ },
});
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderAddSetUrl.stories.tsx b/packages/taler-wallet-webextension/src/popup/ProviderAddSetUrl.stories.tsx
index 2daf49e0c..9a2f97051 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderAddSetUrl.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderAddSetUrl.stories.tsx
@@ -15,39 +15,37 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { createExample } from '../test-utils';
-import { SetUrlView as TestedComponent } from './ProviderAddPage';
+import { createExample } from "../test-utils";
+import { SetUrlView as TestedComponent } from "./ProviderAddPage";
export default {
- title: 'popup/backup/add',
+ title: "popup/backup/add",
component: TestedComponent,
argTypes: {
- onRetry: { action: 'onRetry' },
- onDelete: { action: 'onDelete' },
- onBack: { action: 'onBack' },
- }
+ onRetry: { action: "onRetry" },
+ onDelete: { action: "onDelete" },
+ onBack: { action: "onBack" },
+ },
};
-
-export const Initial = createExample(TestedComponent, {
-});
+export const Initial = createExample(TestedComponent, {});
export const WithValue = createExample(TestedComponent, {
- initialValue: 'sync.demo.taler.net'
-});
+ initialValue: "sync.demo.taler.net",
+});
export const WithConnectionError = createExample(TestedComponent, {
- withError: 'Network error'
-});
+ withError: "Network error",
+});
export const WithClientError = createExample(TestedComponent, {
- withError: 'URL may not be right: (404) Not Found'
-});
+ withError: "URL may not be right: (404) Not Found",
+});
export const WithServerError = createExample(TestedComponent, {
- withError: 'Try another server: (500) Internal Server Error'
-});
+ withError: "Try another server: (500) Internal Server Error",
+});
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderDetail.stories.tsx b/packages/taler-wallet-webextension/src/popup/ProviderDetail.stories.tsx
index 4416608f8..fab21398a 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderDetail.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderDetail.stories.tsx
@@ -15,224 +15,221 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { ProviderPaymentType } from '@gnu-taler/taler-wallet-core';
-import { createExample } from '../test-utils';
-import { ProviderView as TestedComponent } from './ProviderDetailPage';
+import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
+import { createExample } from "../test-utils";
+import { ProviderView as TestedComponent } from "./ProviderDetailPage";
export default {
- title: 'popup/backup/details',
+ title: "popup/backup/details",
component: TestedComponent,
argTypes: {
- onRetry: { action: 'onRetry' },
- onDelete: { action: 'onDelete' },
- onBack: { action: 'onBack' },
- }
+ onRetry: { action: "onRetry" },
+ onDelete: { action: "onDelete" },
+ onBack: { action: "onBack" },
+ },
};
-
export const Active = createExample(TestedComponent, {
info: {
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
- },
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
+ },
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": 1656599921000
- }
- },
- "terms": {
- "annualFee": "EUR:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: 1656599921000,
+ },
+ },
+ terms: {
+ annualFee: "EUR:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
export const ActiveErrorSync = createExample(TestedComponent, {
info: {
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
},
lastAttemptedBackupTimestamp: {
- "t_ms": 1625063925078
+ t_ms: 1625063925078,
},
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": 1656599921000
- }
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: 1656599921000,
+ },
},
lastError: {
code: 2002,
- details: 'details',
- hint: 'error hint from the server',
- message: 'message'
- },
- "terms": {
- "annualFee": "EUR:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ details: "details",
+ hint: "error hint from the server",
+ message: "message",
+ },
+ terms: {
+ annualFee: "EUR:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
export const ActiveBackupProblemUnreadable = createExample(TestedComponent, {
info: {
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
- },
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
+ },
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": 1656599921000
- }
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: 1656599921000,
+ },
},
backupProblem: {
- type: 'backup-unreadable'
- },
- "terms": {
- "annualFee": "EUR:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ type: "backup-unreadable",
+ },
+ terms: {
+ annualFee: "EUR:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
export const ActiveBackupProblemDevice = createExample(TestedComponent, {
info: {
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.taler:9967/",
- "lastSuccessfulBackupTimestamp": {
- "t_ms": 1625063925078
- },
- "paymentProposalIds": [
- "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG"
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.taler:9967/",
+ lastSuccessfulBackupTimestamp: {
+ t_ms: 1625063925078,
+ },
+ paymentProposalIds: [
+ "43Q5WWRJPNS4SE9YKS54H9THDS94089EDGXW9EHBPN6E7M184XEG",
],
- "paymentStatus": {
- "type": ProviderPaymentType.Paid,
- "paidUntil": {
- "t_ms": 1656599921000
- }
+ paymentStatus: {
+ type: ProviderPaymentType.Paid,
+ paidUntil: {
+ t_ms: 1656599921000,
+ },
},
backupProblem: {
- type: 'backup-conflicting-device',
- myDeviceId: 'my-device-id',
- otherDeviceId: 'other-device-id',
+ type: "backup-conflicting-device",
+ myDeviceId: "my-device-id",
+ otherDeviceId: "other-device-id",
backupTimestamp: {
- "t_ms": 1656599921000
- }
- },
- "terms": {
- "annualFee": "EUR:1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ t_ms: 1656599921000,
+ },
+ },
+ terms: {
+ annualFee: "EUR:1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
export const InactiveUnpaid = createExample(TestedComponent, {
info: {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.Unpaid,
- },
- "terms": {
- "annualFee": "EUR:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.Unpaid,
+ },
+ terms: {
+ annualFee: "EUR:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
export const InactiveInsufficientBalance = createExample(TestedComponent, {
info: {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.InsufficientBalance,
- },
- "terms": {
- "annualFee": "EUR:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.InsufficientBalance,
+ },
+ terms: {
+ annualFee: "EUR:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
export const InactivePending = createExample(TestedComponent, {
info: {
- "active": false,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.Pending,
- },
- "terms": {
- "annualFee": "EUR:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ active: false,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.Pending,
+ },
+ terms: {
+ annualFee: "EUR:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
-
export const ActiveTermsChanged = createExample(TestedComponent, {
info: {
- "active": true,
- name:'sync.demo',
- "syncProviderBaseUrl": "http://sync.demo.taler.net/",
- "paymentProposalIds": [],
- "paymentStatus": {
- "type": ProviderPaymentType.TermsChanged,
+ active: true,
+ name: "sync.demo",
+ syncProviderBaseUrl: "http://sync.demo.taler.net/",
+ paymentProposalIds: [],
+ paymentStatus: {
+ type: ProviderPaymentType.TermsChanged,
paidUntil: {
- t_ms: 1656599921000
+ t_ms: 1656599921000,
},
newTerms: {
- "annualFee": "EUR:10",
- "storageLimitInMegabytes": 8,
- "supportedProtocolVersion": "0.0"
+ annualFee: "EUR:10",
+ storageLimitInMegabytes: 8,
+ supportedProtocolVersion: "0.0",
},
oldTerms: {
- "annualFee": "EUR:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- },
- "terms": {
- "annualFee": "EUR:0.1",
- "storageLimitInMegabytes": 16,
- "supportedProtocolVersion": "0.0"
- }
- }
+ annualFee: "EUR:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
+ terms: {
+ annualFee: "EUR:0.1",
+ storageLimitInMegabytes: 16,
+ supportedProtocolVersion: "0.0",
+ },
+ },
});
-
diff --git a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
index 04adbb21c..9617c9a41 100644
--- a/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/ProviderDetailPage.tsx
@@ -14,13 +14,23 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-
import { i18n, Timestamp } from "@gnu-taler/taler-util";
-import { ProviderInfo, ProviderPaymentStatus, ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
+import {
+ ProviderInfo,
+ ProviderPaymentStatus,
+ ProviderPaymentType,
+} from "@gnu-taler/taler-wallet-core";
import { format, formatDuration, intervalToDuration } from "date-fns";
import { Fragment, VNode, h } from "preact";
import { ErrorMessage } from "../components/ErrorMessage";
-import { Button, ButtonDestructive, ButtonPrimary, PaymentStatus, PopupBox, SmallLightText } from "../components/styled";
+import {
+ Button,
+ ButtonDestructive,
+ ButtonPrimary,
+ PaymentStatus,
+ PopupBox,
+ SmallLightText,
+} from "../components/styled";
import { useProviderStatus } from "../hooks/useProviderStatus";
interface Props {
@@ -29,20 +39,29 @@ interface Props {
}
export function ProviderDetailPage({ pid, onBack }: Props): VNode {
- const status = useProviderStatus(pid)
+ const status = useProviderStatus(pid);
if (!status) {
- return <div><i18n.Translate>Loading...</i18n.Translate></div>
+ return (
+ <div>
+ <i18n.Translate>Loading...</i18n.Translate>
+ </div>
+ );
}
if (!status.info) {
- onBack()
- return <div />
+ onBack();
+ return <div />;
}
- return <ProviderView info={status.info}
- onSync={status.sync}
- onDelete={() => status.remove().then(onBack)}
- onBack={onBack}
- onExtend={() => { null }}
- />;
+ return (
+ <ProviderView
+ info={status.info}
+ onSync={status.sync}
+ onDelete={() => status.remove().then(onBack)}
+ onBack={onBack}
+ onExtend={() => {
+ null;
+ }}
+ />
+ );
}
export interface ViewProps {
@@ -53,124 +72,185 @@ export interface ViewProps {
onExtend: () => void;
}
-export function ProviderView({ info, onDelete, onSync, onBack, onExtend }: ViewProps): VNode {
- const lb = info?.lastSuccessfulBackupTimestamp
- const isPaid = info.paymentStatus.type === ProviderPaymentType.Paid || info.paymentStatus.type === ProviderPaymentType.TermsChanged
+export function ProviderView({
+ info,
+ onDelete,
+ onSync,
+ onBack,
+ onExtend,
+}: ViewProps): VNode {
+ const lb = info?.lastSuccessfulBackupTimestamp;
+ const isPaid =
+ info.paymentStatus.type === ProviderPaymentType.Paid ||
+ info.paymentStatus.type === ProviderPaymentType.TermsChanged;
return (
<PopupBox>
<Error info={info} />
<header>
- <h3>{info.name} <SmallLightText>{info.syncProviderBaseUrl}</SmallLightText></h3>
- <PaymentStatus color={isPaid ? 'rgb(28, 184, 65)' : 'rgb(202, 60, 60)'}>{isPaid ? 'Paid' : 'Unpaid'}</PaymentStatus>
+ <h3>
+ {info.name}{" "}
+ <SmallLightText>{info.syncProviderBaseUrl}</SmallLightText>
+ </h3>
+ <PaymentStatus color={isPaid ? "rgb(28, 184, 65)" : "rgb(202, 60, 60)"}>
+ {isPaid ? "Paid" : "Unpaid"}
+ </PaymentStatus>
</header>
<section>
- <p><b>Last backup:</b> {lb == null || lb.t_ms == "never" ? "never" : format(lb.t_ms, 'dd MMM yyyy')} </p>
- <ButtonPrimary onClick={onSync}><i18n.Translate>Back up</i18n.Translate></ButtonPrimary>
- {info.terms && <Fragment>
- <p><b>Provider fee:</b> {info.terms && info.terms.annualFee} per year</p>
- </Fragment>
- }
+ <p>
+ <b>Last backup:</b>{" "}
+ {lb == null || lb.t_ms == "never"
+ ? "never"
+ : format(lb.t_ms, "dd MMM yyyy")}{" "}
+ </p>
+ <ButtonPrimary onClick={onSync}>
+ <i18n.Translate>Back up</i18n.Translate>
+ </ButtonPrimary>
+ {info.terms && (
+ <Fragment>
+ <p>
+ <b>Provider fee:</b> {info.terms && info.terms.annualFee} per year
+ </p>
+ </Fragment>
+ )}
<p>{descriptionByStatus(info.paymentStatus)}</p>
- <ButtonPrimary disabled onClick={onExtend}><i18n.Translate>Extend</i18n.Translate></ButtonPrimary>
-
- {info.paymentStatus.type === ProviderPaymentType.TermsChanged && <div>
- <p><i18n.Translate>terms has changed, extending the service will imply accepting the new terms of service</i18n.Translate></p>
- <table>
- <thead>
- <tr>
- <td></td>
- <td><i18n.Translate>old</i18n.Translate></td>
- <td> -&gt;</td>
- <td><i18n.Translate>new</i18n.Translate></td>
- </tr>
- </thead>
- <tbody>
-
- <tr>
- <td><i18n.Translate>fee</i18n.Translate></td>
- <td>{info.paymentStatus.oldTerms.annualFee}</td>
- <td>-&gt;</td>
- <td>{info.paymentStatus.newTerms.annualFee}</td>
- </tr>
- <tr>
- <td><i18n.Translate>storage</i18n.Translate></td>
- <td>{info.paymentStatus.oldTerms.storageLimitInMegabytes}</td>
- <td>-&gt;</td>
- <td>{info.paymentStatus.newTerms.storageLimitInMegabytes}</td>
- </tr>
- </tbody>
- </table>
- </div>}
+ <ButtonPrimary disabled onClick={onExtend}>
+ <i18n.Translate>Extend</i18n.Translate>
+ </ButtonPrimary>
+ {info.paymentStatus.type === ProviderPaymentType.TermsChanged && (
+ <div>
+ <p>
+ <i18n.Translate>
+ terms has changed, extending the service will imply accepting
+ the new terms of service
+ </i18n.Translate>
+ </p>
+ <table>
+ <thead>
+ <tr>
+ <td></td>
+ <td>
+ <i18n.Translate>old</i18n.Translate>
+ </td>
+ <td> -&gt;</td>
+ <td>
+ <i18n.Translate>new</i18n.Translate>
+ </td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <i18n.Translate>fee</i18n.Translate>
+ </td>
+ <td>{info.paymentStatus.oldTerms.annualFee}</td>
+ <td>-&gt;</td>
+ <td>{info.paymentStatus.newTerms.annualFee}</td>
+ </tr>
+ <tr>
+ <td>
+ <i18n.Translate>storage</i18n.Translate>
+ </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>
+ <Button onClick={onBack}>
+ <i18n.Translate> &lt; back</i18n.Translate>
+ </Button>
<div>
- <ButtonDestructive onClick={onDelete}><i18n.Translate>remove provider</i18n.Translate></ButtonDestructive>
+ <ButtonDestructive onClick={onDelete}>
+ <i18n.Translate>remove provider</i18n.Translate>
+ </ButtonDestructive>
</div>
</footer>
</PopupBox>
- )
+ );
}
function daysSince(d?: Timestamp) {
- if (!d || d.t_ms === 'never') return 'never synced'
+ if (!d || d.t_ms === "never") return "never synced";
const duration = intervalToDuration({
start: d.t_ms,
end: new Date(),
- })
+ });
const str = formatDuration(duration, {
- delimiter: ', ',
+ delimiter: ", ",
format: [
- duration?.years ? i18n.str`years` : (
- duration?.months ? i18n.str`months` : (
- duration?.days ? i18n.str`days` : (
- duration?.hours ? i18n.str`hours` : (
- duration?.minutes ? i18n.str`minutes` : i18n.str`seconds`
- )
- )
- )
- )
- ]
- })
- return `synced ${str} ago`
+ duration?.years
+ ? i18n.str`years`
+ : duration?.months
+ ? i18n.str`months`
+ : duration?.days
+ ? i18n.str`days`
+ : duration?.hours
+ ? i18n.str`hours`
+ : duration?.minutes
+ ? i18n.str`minutes`
+ : i18n.str`seconds`,
+ ],
+ });
+ return `synced ${str} ago`;
}
function Error({ info }: { info: ProviderInfo }) {
if (info.lastError) {
- return <ErrorMessage title={info.lastError.hint} />
+ return <ErrorMessage title={info.lastError.hint} />;
}
if (info.backupProblem) {
switch (info.backupProblem.type) {
case "backup-conflicting-device":
- return <ErrorMessage title={<Fragment>
- <i18n.Translate>There is conflict with another backup from <b>{info.backupProblem.otherDeviceId}</b></i18n.Translate>
- </Fragment>} />
+ return (
+ <ErrorMessage
+ title={
+ <Fragment>
+ <i18n.Translate>
+ There is conflict with another backup from{" "}
+ <b>{info.backupProblem.otherDeviceId}</b>
+ </i18n.Translate>
+ </Fragment>
+ }
+ />
+ );
case "backup-unreadable":
- return <ErrorMessage title="Backup is not readable" />
+ return <ErrorMessage title="Backup is not readable" />;
default:
- return <ErrorMessage title={<Fragment>
- <i18n.Translate>Unknown backup problem: {JSON.stringify(info.backupProblem)}</i18n.Translate>
- </Fragment>} />
+ return (
+ <ErrorMessage
+ title={
+ <Fragment>
+ <i18n.Translate>
+ Unknown backup problem: {JSON.stringify(info.backupProblem)}
+ </i18n.Translate>
+ </Fragment>
+ }
+ />
+ );
}
}
- return null
+ return null;
}
function colorByStatus(status: ProviderPaymentType) {
switch (status) {
case ProviderPaymentType.InsufficientBalance:
- return 'rgb(223, 117, 20)'
+ return "rgb(223, 117, 20)";
case ProviderPaymentType.Unpaid:
- return 'rgb(202, 60, 60)'
+ return "rgb(202, 60, 60)";
case ProviderPaymentType.Paid:
- return 'rgb(28, 184, 65)'
+ return "rgb(28, 184, 65)";
case ProviderPaymentType.Pending:
- return 'gray'
+ return "gray";
case ProviderPaymentType.InsufficientBalance:
- return 'rgb(202, 60, 60)'
+ return "rgb(202, 60, 60)";
case ProviderPaymentType.TermsChanged:
- return 'rgb(202, 60, 60)'
+ return "rgb(202, 60, 60)";
}
}
@@ -180,16 +260,19 @@ function descriptionByStatus(status: ProviderPaymentStatus) {
// return i18n.str`not paid yet`
case ProviderPaymentType.Paid:
case ProviderPaymentType.TermsChanged:
- if (status.paidUntil.t_ms === 'never') {
- return i18n.str`service paid`
+ if (status.paidUntil.t_ms === "never") {
+ return i18n.str`service paid`;
} else {
- return <Fragment>
- <b>Backup valid until:</b> {format(status.paidUntil.t_ms, 'dd MMM yyyy')}
- </Fragment>
+ return (
+ <Fragment>
+ <b>Backup valid until:</b>{" "}
+ {format(status.paidUntil.t_ms, "dd MMM yyyy")}
+ </Fragment>
+ );
}
case ProviderPaymentType.Unpaid:
case ProviderPaymentType.InsufficientBalance:
case ProviderPaymentType.Pending:
- return ''
+ return "";
}
}
diff --git a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx
index 06e33c9d3..ae8e54ba1 100644
--- a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx
@@ -15,29 +15,28 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { createExample } from '../test-utils';
-import { SettingsView as TestedComponent } from './Settings';
+import { createExample } from "../test-utils";
+import { SettingsView as TestedComponent } from "./Settings";
export default {
- title: 'popup/settings',
+ title: "popup/settings",
component: TestedComponent,
argTypes: {
setDeviceName: () => Promise.resolve(),
- }
+ },
};
export const AllOff = createExample(TestedComponent, {
- deviceName: 'this-is-the-device-name',
+ deviceName: "this-is-the-device-name",
setDeviceName: () => Promise.resolve(),
});
export const OneChecked = createExample(TestedComponent, {
- deviceName: 'this-is-the-device-name',
+ deviceName: "this-is-the-device-name",
permissionsEnabled: true,
setDeviceName: () => Promise.resolve(),
});
-
diff --git a/packages/taler-wallet-webextension/src/popup/Settings.tsx b/packages/taler-wallet-webextension/src/popup/Settings.tsx
index 8595c87ff..3b83f0762 100644
--- a/packages/taler-wallet-webextension/src/popup/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Settings.tsx
@@ -14,7 +14,6 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-
import { i18n } from "@gnu-taler/taler-util";
import { VNode, h } from "preact";
import { Checkbox } from "../components/Checkbox";
@@ -28,15 +27,21 @@ import { useLang } from "../hooks/useLang";
export function SettingsPage(): VNode {
const [permissionsEnabled, togglePermissions] = useExtendedPermissions();
- const { devMode, toggleDevMode } = useDevContext()
- const { name, update } = useBackupDeviceName()
- const [lang, changeLang] = useLang()
- return <SettingsView
- lang={lang} changeLang={changeLang}
- deviceName={name} setDeviceName={update}
- permissionsEnabled={permissionsEnabled} togglePermissions={togglePermissions}
- developerMode={devMode} toggleDeveloperMode={toggleDevMode}
- />;
+ const { devMode, toggleDevMode } = useDevContext();
+ const { name, update } = useBackupDeviceName();
+ const [lang, changeLang] = useLang();
+ return (
+ <SettingsView
+ lang={lang}
+ changeLang={changeLang}
+ deviceName={name}
+ setDeviceName={update}
+ permissionsEnabled={permissionsEnabled}
+ togglePermissions={togglePermissions}
+ developerMode={devMode}
+ toggleDeveloperMode={toggleDevMode}
+ />
+ );
}
export interface ViewProps {
@@ -50,23 +55,31 @@ export interface ViewProps {
toggleDeveloperMode: () => void;
}
-import { strings as messages } from '../i18n/strings'
+import { strings as messages } from "../i18n/strings";
type LangsNames = {
- [P in keyof typeof messages]: string
-}
+ [P in keyof typeof messages]: string;
+};
const names: LangsNames = {
- es: 'Español [es]',
- en: 'English [en]',
- fr: 'Français [fr]',
- de: 'Deutsch [de]',
- sv: 'Svenska [sv]',
- it: 'Italiano [it]',
-}
-
+ es: "Español [es]",
+ en: "English [en]",
+ fr: "Français [fr]",
+ de: "Deutsch [de]",
+ sv: "Svenska [sv]",
+ it: "Italiano [it]",
+};
-export function SettingsView({ lang, changeLang, deviceName, setDeviceName, permissionsEnabled, togglePermissions, developerMode, toggleDeveloperMode }: ViewProps): VNode {
+export function SettingsView({
+ lang,
+ changeLang,
+ deviceName,
+ setDeviceName,
+ permissionsEnabled,
+ togglePermissions,
+ developerMode,
+ toggleDeveloperMode,
+}: ViewProps): VNode {
return (
<PopupBox>
<section>
@@ -86,25 +99,39 @@ export function SettingsView({ lang, changeLang, deviceName, setDeviceName, perm
label={i18n.str`Device name`}
description="(This is how you will recognize the wallet in the backup provider)"
/> */}
- <h2><i18n.Translate>Permissions</i18n.Translate></h2>
- <Checkbox label="Automatically open wallet based on page content"
+ <h2>
+ <i18n.Translate>Permissions</i18n.Translate>
+ </h2>
+ <Checkbox
+ label="Automatically open wallet based on page content"
name="perm"
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
- enabled={permissionsEnabled} onToggle={togglePermissions}
+ enabled={permissionsEnabled}
+ onToggle={togglePermissions}
/>
<h2>Config</h2>
- <Checkbox label="Developer mode"
+ <Checkbox
+ label="Developer mode"
name="devMode"
description="(More options and information useful for debugging)"
- enabled={developerMode} onToggle={toggleDeveloperMode}
+ enabled={developerMode}
+ onToggle={toggleDeveloperMode}
/>
</section>
- <footer style={{ justifyContent: 'space-around' }}>
- <a target="_blank"
+ <footer style={{ justifyContent: "space-around" }}>
+ <a
+ target="_blank"
rel="noopener noreferrer"
- style={{ color: 'darkgreen', textDecoration: 'none' }}
- href={chrome.extension ? chrome.extension.getURL(`/static/wallet.html#/settings`) : '#'}>VIEW MORE SETTINGS</a>
+ style={{ color: "darkgreen", textDecoration: "none" }}
+ href={
+ chrome.extension
+ ? chrome.extension.getURL(`/static/wallet.html#/settings`)
+ : "#"
+ }
+ >
+ VIEW MORE SETTINGS
+ </a>
</footer>
</PopupBox>
- )
-} \ No newline at end of file
+ );
+}
diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.stories.tsx b/packages/taler-wallet-webextension/src/popup/TalerActionFound.stories.tsx
index 88c7c725e..f20403d6a 100644
--- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.stories.tsx
@@ -15,38 +15,38 @@
*/
/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
-import { createExample } from '../test-utils';
-import { TalerActionFound as TestedComponent } from './TalerActionFound';
+import { createExample } from "../test-utils";
+import { TalerActionFound as TestedComponent } from "./TalerActionFound";
export default {
- title: 'popup/TalerActionFound',
+ title: "popup/TalerActionFound",
component: TestedComponent,
};
export const PayAction = createExample(TestedComponent, {
- url: 'taler://pay/something'
+ url: "taler://pay/something",
});
export const WithdrawalAction = createExample(TestedComponent, {
- url: 'taler://withdraw/something'
+ url: "taler://withdraw/something",
});
export const TipAction = createExample(TestedComponent, {
- url: 'taler://tip/something'
+ url: "taler://tip/something",
});
export const NotifyAction = createExample(TestedComponent, {
- url: 'taler://notify-reserve/something'
+ url: "taler://notify-reserve/something",
});
export const RefundAction = createExample(TestedComponent, {
- url: 'taler://refund/something'
+ url: "taler://refund/something",
});
export const InvalidAction = createExample(TestedComponent, {
- url: 'taler://something/asd'
+ url: "taler://something/asd",
});
diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
index ef0ec341c..cbdcbeb15 100644
--- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
+++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
@@ -1,5 +1,31 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
-import { ButtonPrimary, ButtonSuccess, PopupBox } from "../components/styled/index";
+import {
+ ButtonPrimary,
+ ButtonSuccess,
+ PopupBox,
+} from "../components/styled/index";
+import { h } from "preact";
export interface Props {
url: string;
@@ -8,54 +34,89 @@ export interface Props {
export function TalerActionFound({ url, onDismiss }: Props) {
const uriType = classifyTalerUri(url);
- return <PopupBox>
- <section>
- <h1>Taler Action </h1>
- {uriType === TalerUriType.TalerPay && <div>
- <p>This page has pay action.</p>
- <ButtonSuccess onClick={() => { chrome.tabs.create({ "url": actionForTalerUri(uriType, url) }); }}>
- Open pay page
- </ButtonSuccess>
- </div>}
- {uriType === TalerUriType.TalerWithdraw && <div>
- <p>This page has a withdrawal action.</p>
- <ButtonSuccess onClick={() => { chrome.tabs.create({ "url": actionForTalerUri(uriType, url) }); }}>
- Open withdraw page
- </ButtonSuccess>
- </div>}
- {uriType === TalerUriType.TalerTip && <div>
- <p>This page has a tip action.</p>
- <ButtonSuccess onClick={() => { chrome.tabs.create({ "url": actionForTalerUri(uriType, url) }); }}>
- Open tip page
- </ButtonSuccess>
- </div>}
- {uriType === TalerUriType.TalerNotifyReserve && <div>
- <p>This page has a notify reserve action.</p>
- <ButtonSuccess onClick={() => { chrome.tabs.create({ "url": actionForTalerUri(uriType, url) }); }}>
- Notify
- </ButtonSuccess>
- </div>}
- {uriType === TalerUriType.TalerRefund && <div>
- <p>This page has a refund action.</p>
- <ButtonSuccess onClick={() => { chrome.tabs.create({ "url": actionForTalerUri(uriType, url) }); }}>
- Open refund page
- </ButtonSuccess>
- </div>}
- {uriType === TalerUriType.Unknown && <div>
- <p>This page has a malformed taler uri.</p>
- <p>{url}</p>
- </div>}
-
- </section>
- <footer>
- <div />
- <ButtonPrimary onClick={() => onDismiss()}> Dismiss </ButtonPrimary>
- </footer>
- </PopupBox>;
-
+ return (
+ <PopupBox>
+ <section>
+ <h1>Taler Action </h1>
+ {uriType === TalerUriType.TalerPay && (
+ <div>
+ <p>This page has pay action.</p>
+ <ButtonSuccess
+ onClick={() => {
+ chrome.tabs.create({ url: actionForTalerUri(uriType, url) });
+ }}
+ >
+ Open pay page
+ </ButtonSuccess>
+ </div>
+ )}
+ {uriType === TalerUriType.TalerWithdraw && (
+ <div>
+ <p>This page has a withdrawal action.</p>
+ <ButtonSuccess
+ onClick={() => {
+ chrome.tabs.create({ url: actionForTalerUri(uriType, url) });
+ }}
+ >
+ Open withdraw page
+ </ButtonSuccess>
+ </div>
+ )}
+ {uriType === TalerUriType.TalerTip && (
+ <div>
+ <p>This page has a tip action.</p>
+ <ButtonSuccess
+ onClick={() => {
+ chrome.tabs.create({ url: actionForTalerUri(uriType, url) });
+ }}
+ >
+ Open tip page
+ </ButtonSuccess>
+ </div>
+ )}
+ {uriType === TalerUriType.TalerNotifyReserve && (
+ <div>
+ <p>This page has a notify reserve action.</p>
+ <ButtonSuccess
+ onClick={() => {
+ chrome.tabs.create({ url: actionForTalerUri(uriType, url) });
+ }}
+ >
+ Notify
+ </ButtonSuccess>
+ </div>
+ )}
+ {uriType === TalerUriType.TalerRefund && (
+ <div>
+ <p>This page has a refund action.</p>
+ <ButtonSuccess
+ onClick={() => {
+ chrome.tabs.create({ url: actionForTalerUri(uriType, url) });
+ }}
+ >
+ Open refund page
+ </ButtonSuccess>
+ </div>
+ )}
+ {uriType === TalerUriType.Unknown && (
+ <div>
+ <p>This page has a malformed taler uri.</p>
+ <p>{url}</p>
+ </div>
+ )}
+ </section>
+ <footer>
+ <div />
+ <ButtonPrimary onClick={() => onDismiss()}> Dismiss </ButtonPrimary>
+ </footer>
+ </PopupBox>
+ );
}
-function actionForTalerUri(uriType: TalerUriType, talerUri: string): string | undefined {
+function actionForTalerUri(
+ uriType: TalerUriType,
+ talerUri: string,
+): string | undefined {
switch (uriType) {
case TalerUriType.TalerWithdraw:
return makeExtensionUrlWithParams("static/wallet.html#/withdraw", {
@@ -91,8 +152,10 @@ function makeExtensionUrlWithParams(
): string {
const innerUrl = new URL(chrome.extension.getURL("/" + url));
if (params) {
- const hParams = Object.keys(params).map(k => `${k}=${params[k]}`).join('&')
- innerUrl.hash = innerUrl.hash + '?' + hParams
+ const hParams = Object.keys(params)
+ .map((k) => `${k}=${params[k]}`)
+ .join("&");
+ innerUrl.hash = innerUrl.hash + "?" + hParams;
}
return innerUrl.href;
}