aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-08-19 00:34:47 -0300
committerSebastian <sebasjm@gmail.com>2021-08-19 00:35:21 -0300
commit97a05ff659af274dcfcd9c76bf19100bbd51ce0e (patch)
tree9cce837ec9a5ec06279dc48eac75e1993ede983f /packages/taler-wallet-webextension
parentb015f76e7268cb5caff14a0ed88cb5e8fa53dc2e (diff)
new wallet history and view refactoring
Diffstat (limited to 'packages/taler-wallet-webextension')
-rw-r--r--packages/taler-wallet-webextension/.storybook/preview.js87
-rw-r--r--packages/taler-wallet-webextension/package.json2
-rw-r--r--packages/taler-wallet-webextension/rollup.config.js11
-rw-r--r--packages/taler-wallet-webextension/src/NavigationBar.tsx (renamed from packages/taler-wallet-webextension/src/popup/popup.tsx)33
-rw-r--r--packages/taler-wallet-webextension/src/components/LogoHeader.tsx13
-rw-r--r--packages/taler-wallet-webextension/src/components/styled/index.tsx107
-rw-r--r--packages/taler-wallet-webextension/src/cta/Pay.stories.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Pay.stories.tsx)11
-rw-r--r--packages/taler-wallet-webextension/src/cta/Pay.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Pay.tsx)0
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund.stories.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Refund.stories.tsx)12
-rw-r--r--packages/taler-wallet-webextension/src/cta/Refund.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Refund.tsx)0
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip.stories.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Tip.stories.tsx)11
-rw-r--r--packages/taler-wallet-webextension/src/cta/Tip.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Tip.tsx)0
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Withdraw.stories.tsx)25
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw.tsx (renamed from packages/taler-wallet-webextension/src/wallet/Withdraw.tsx)28
-rw-r--r--packages/taler-wallet-webextension/src/cta/payback.tsx (renamed from packages/taler-wallet-webextension/src/wallet/payback.tsx)0
-rw-r--r--packages/taler-wallet-webextension/src/cta/reset-required.tsx (renamed from packages/taler-wallet-webextension/src/wallet/reset-required.tsx)0
-rw-r--r--packages/taler-wallet-webextension/src/cta/return-coins.tsx (renamed from packages/taler-wallet-webextension/src/wallet/return-coins.tsx)0
-rw-r--r--packages/taler-wallet-webextension/src/popup/BackupPage.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/popup/History.tsx34
-rw-r--r--packages/taler-wallet-webextension/src/popup/Popup.stories.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/popup/Transaction.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/popupEntryPoint.tsx4
-rw-r--r--packages/taler-wallet-webextension/src/test-utils.ts8
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.stories.tsx294
-rw-r--r--packages/taler-wallet-webextension/src/wallet/History.tsx248
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx8
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Welcome.tsx11
-rw-r--r--packages/taler-wallet-webextension/src/walletEntryPoint.tsx70
-rw-r--r--packages/taler-wallet-webextension/static/img/logo-2021.svg1
-rw-r--r--packages/taler-wallet-webextension/static/style/wallet.css1
30 files changed, 867 insertions, 158 deletions
diff --git a/packages/taler-wallet-webextension/.storybook/preview.js b/packages/taler-wallet-webextension/.storybook/preview.js
index 02a4e43d4..1b6f62400 100644
--- a/packages/taler-wallet-webextension/.storybook/preview.js
+++ b/packages/taler-wallet-webextension/.storybook/preview.js
@@ -15,7 +15,8 @@
*/
import { Fragment } from "preact"
-import { NavBar } from '../src/popup/popup'
+import { NavBar } from '../src/NavigationBar'
+import { LogoHeader } from '../src/components/LogoHeader'
import { TranslationProvider } from '../src/context/translation'
export const parameters = {
@@ -43,7 +44,7 @@ export const globalTypes = {
export const decorators = [
(Story, { kind }) => {
if (kind.startsWith('popup')) {
-
+
function Body() {
const isTestingHeader = (/.*\/header\/?.*/.test(kind));
if (isTestingHeader) {
@@ -51,16 +52,16 @@ export const decorators = [
return <div style={{ width: 400, height: 320 }}>
<Story />
</div>
- } else {
- const path = !isTestingHeader ? /popup(\/.*).*/.exec(kind)[1] : ''
- // add a fake header so it looks similar
- return <Fragment>
- <NavBar path={path} devMode={path === '/dev'} />
- <div style={{ width: 400, height: 290 }}>
- <Story />
- </div>
- </Fragment>
}
+
+ const path = /popup(\/.*).*/.exec(kind)[1];
+ // add a fake header so it looks similar
+ return <Fragment>
+ <NavBar path={path} devMode={path === '/dev'} />
+ <div style={{ width: 400, height: 290 }}>
+ <Story />
+ </div>
+ </Fragment>
}
return <div class="popup-container">
@@ -95,11 +96,71 @@ export const decorators = [
</div>
</div>
}
- if (kind.startsWith('wallet')) {
- return <div class="wallet-container">
+ if (kind.startsWith('cta')) {
+ return <div>
+ <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;
+ background-color: #f8faf7;
+ font-family: Arial, Helvetica, sans-serif;
+ }`}
+ </style>
<link key="1" rel="stylesheet" type="text/css" href="/style/pure.css" />
<link key="2" rel="stylesheet" type="text/css" href="/style/wallet.css" />
<Story />
+ </div>
+ }
+ if (kind.startsWith('wallet')) {
+ const path = /wallet(\/.*).*/.exec(kind)[1];
+ return <div class="wallet-container">
+ <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;
+ background-color: #f8faf7;
+ font-family: Arial, Helvetica, sans-serif;
+ }`}
+ </style>
+ <LogoHeader />
+ <NavBar path={path} devMode={path === '/dev'} />
+ {/* <link key="1" rel="stylesheet" type="text/css" href="/style/pure.css" />
+ <link key="2" rel="stylesheet" type="text/css" href="/style/wallet.css" /> */}
+ <Story />
</div>
}
return <div>
diff --git a/packages/taler-wallet-webextension/package.json b/packages/taler-wallet-webextension/package.json
index a5908af25..e41c6cb86 100644
--- a/packages/taler-wallet-webextension/package.json
+++ b/packages/taler-wallet-webextension/package.json
@@ -12,7 +12,7 @@
"test": "jest ./tests",
"compile": "tsc && rollup -c",
"build-storybook": "build-storybook",
- "storybook": "start-storybook -s static -p 6006",
+ "storybook": "start-storybook -s . -p 6006",
"watch": "tsc --watch & rollup -w -c"
},
"dependencies": {
diff --git a/packages/taler-wallet-webextension/rollup.config.js b/packages/taler-wallet-webextension/rollup.config.js
index 7e7ec0032..5a3f0db5f 100644
--- a/packages/taler-wallet-webextension/rollup.config.js
+++ b/packages/taler-wallet-webextension/rollup.config.js
@@ -1,14 +1,13 @@
// rollup.config.js
+import linaria from '@linaria/rollup';
+import alias from '@rollup/plugin-alias';
import commonjs from "@rollup/plugin-commonjs";
-import nodeResolve from "@rollup/plugin-node-resolve";
+import image from '@rollup/plugin-image';
import json from "@rollup/plugin-json";
-import builtins from "builtin-modules";
+import nodeResolve from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";
-import ignore from "rollup-plugin-ignore"
-import image from '@rollup/plugin-image';
-import linaria from '@linaria/rollup';
import css from 'rollup-plugin-css-only';
-import alias from '@rollup/plugin-alias';
+import ignore from "rollup-plugin-ignore";
const makePlugins = () => [
alias({
diff --git a/packages/taler-wallet-webextension/src/popup/popup.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index 4aee48fb7..e07032d0a 100644
--- a/packages/taler-wallet-webextension/src/popup/popup.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -27,10 +27,11 @@
import { i18n } from "@gnu-taler/taler-util";
import { ComponentChildren, JSX } from "preact";
import Match from "preact-router/match";
-import { useDevContext } from "../context/devContext";
-import { PopupNavigation } from '../components/styled'
+import { useDevContext } from "./context/devContext";
+import { PopupNavigation } from './components/styled'
export enum Pages {
+ welcome = '/welcome',
balance = '/balance',
settings = '/settings',
dev = '/dev',
@@ -39,6 +40,15 @@ export enum Pages {
transaction = '/transaction/:tid',
provider_detail = '/provider/:pid',
provider_add = '/provider/add',
+
+ reset_required = '/reset-required',
+ payback = '/payback',
+ return_coins = '/return-coins',
+
+ pay = '/pay',
+ refund = '/refund',
+ tips = '/tips',
+ withdraw = '/withdraw',
}
interface TabProps {
@@ -59,18 +69,23 @@ function Tab(props: TabProps): JSX.Element {
);
}
-export function NavBar({devMode, path}:{path:string, devMode:boolean}) {
+export function NavBar({ devMode, path }: { path: string, devMode: boolean }) {
return <PopupNavigation devMode={devMode}>
- <Tab target="/balance" current={path}>{i18n.str`Balance`}</Tab>
- <Tab target="/history" current={path}>{i18n.str`History`}</Tab>
- <Tab target="/backup" current={path}>{i18n.str`Backup`}</Tab>
- <Tab target="/settings" current={path}>{i18n.str`Settings`}</Tab>
- {devMode && <Tab target="/dev" current={path}>{i18n.str`Dev`}</Tab>}
+ <div>
+ <Tab target="/balance" current={path}>{i18n.str`Balance`}</Tab>
+ <Tab target="/history" current={path}>{i18n.str`History`}</Tab>
+ <Tab target="/backup" current={path}>{i18n.str`Backup`}</Tab>
+ <Tab target="/settings" current={path}>{i18n.str`Settings`}</Tab>
+ {devMode && <Tab target="/dev" current={path}>{i18n.str`Dev`}</Tab>}
+ </div>
</PopupNavigation>
}
export function WalletNavBar() {
const { devMode } = useDevContext()
- return <Match>{({ path }: any) => <NavBar devMode={devMode} path={path} />}</Match>
+ return <Match>{({ path }: any) => {
+ console.log("path", path)
+ return <NavBar devMode={devMode} path={path} />
+ }}</Match>
}
diff --git a/packages/taler-wallet-webextension/src/components/LogoHeader.tsx b/packages/taler-wallet-webextension/src/components/LogoHeader.tsx
new file mode 100644
index 000000000..0217289eb
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/LogoHeader.tsx
@@ -0,0 +1,13 @@
+export function LogoHeader() {
+ return <div style={{
+ display: 'flex',
+ justifyContent: 'space-around',
+ margin: '2em',
+ }}>
+ <img style={{
+ width: 150,
+ height: 70,
+ }} src="/static/img/logo-2021.svg" width="150" />
+ </div>
+
+} \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index 7f709db46..6067fa446 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -11,7 +11,7 @@ export const PaymentStatus = styled.div<{ color: string }>`
background-color: ${p => p.color};
`
-export const WalletPage = styled.section`
+export const WalletAction = styled.section`
border: solid 5px black;
border-radius: 10px;
margin-left: auto;
@@ -28,8 +28,73 @@ export const WalletPage = styled.section`
}
`
+export const DateSeparator = styled.div`
+ color: gray;
+ margin: .2em;
+ margin-top: 1em;
+`
+export const WalletBox = styled.div<{ noPadding?: boolean }>`
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: center;
+ & > * {
+ width: 400px;
+ }
+ & > section {
+ padding-left: ${({ noPadding }) => noPadding ? '0px' : '8px'};
+ padding-right: ${({ noPadding }) => noPadding ? '0px' : '8px'};
+ // 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;
+ padding: 8px;
+ margin-bottom: 5px;
+
+ & > div {
+ align-self: center;
+ }
+
+ & > h3 {
+ margin: 0px;
+ }
+
+ & > .title {
+ /* margin: 1em; */
+ font-size: large;
+ color: #3c4e92;
+ }
+ }
+
+ & > footer {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ flex-direction: row;
+ justify-content: space-between;
+ display: flex;
+ & button {
+ margin-right: 8px;
+ margin-left: 8px;
+ }
+ }
+`
+
export const PopupBox = styled.div<{ noPadding?: boolean }>`
height: 290px;
+ width: 400px;
display: flex;
flex-direction: column;
justify-content: space-between;
@@ -194,10 +259,32 @@ export const RowBorderGray = styled(Row)`
export const RowLightBorderGray = styled(Row2)`
border: 1px solid lightgray;
- /* border-radius: 0.5em; */
+ border-top: 0px;
+
+ ${DateSeparator} + & {
+ border: 1px solid lightgray;
+ background-color: red;
+ }
`
-export const HistoryRow = styled(RowLightBorderGray)`
+export const HistoryRow = styled.a`
+ text-decoration: none;
+
+ display: flex;
+ justify-content: space-between;
+ padding: 0.5em;
+
+ border: 1px solid lightgray;
+ border-top: 0px;
+
+ ${DateSeparator} + & {
+ border: 1px solid lightgray;
+ }
+
+ :hover {
+ background-color: lightgray;
+ }
+
& > ${Column}:last-of-type {
margin-left: auto;
align-self: center;
@@ -284,11 +371,17 @@ export const ErrorBox = styled.div`
}
}
`
-export const PopupNavigation = styled.div<{devMode?:boolean}>`
+export const PopupNavigation = styled.div<{ devMode?: boolean }>`
background-color:#0042b2;
height: 35px;
-
- & > a {
+ justify-content: space-around;
+ display: flex;
+
+ & > div {
+ width: 400px;
+ }
+
+ & > div > a {
color: #f8faf7;
display: inline-block;
width: calc(400px / ${({ devMode }) => !devMode ? 4 : 5});
@@ -298,7 +391,7 @@ export const PopupNavigation = styled.div<{devMode?:boolean}>`
line-height: 35px;
}
- & > a.active {
+ & > div > a.active {
background-color: #f8faf7;
color: #0042b2;
font-weight: bold;
diff --git a/packages/taler-wallet-webextension/src/wallet/Pay.stories.tsx b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
index 0297d6264..38e3d0f35 100644
--- a/packages/taler-wallet-webextension/src/wallet/Pay.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Pay.stories.tsx
@@ -20,23 +20,16 @@
*/
import { ContractTerms, PreparePayResultType } from '@gnu-taler/taler-util';
-import { FunctionalComponent, h } from 'preact';
+import { createExample } from '../test-utils';
import { PaymentRequestView as TestedComponent } from './Pay';
-
export default {
- title: 'wallet/pay',
+ title: 'cta/pay',
component: TestedComponent,
argTypes: {
},
};
-function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
- const r = (args: any) => <Component {...args} />
- r.args = props
- return r
-}
-
export const InsufficientBalance = createExample(TestedComponent, {
payStatus: {
status: PreparePayResultType.InsufficientBalance,
diff --git a/packages/taler-wallet-webextension/src/wallet/Pay.tsx b/packages/taler-wallet-webextension/src/cta/Pay.tsx
index a5849bb28..a5849bb28 100644
--- a/packages/taler-wallet-webextension/src/wallet/Pay.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Pay.tsx
diff --git a/packages/taler-wallet-webextension/src/wallet/Refund.stories.tsx b/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx
index 044141f0c..88e714cb7 100644
--- a/packages/taler-wallet-webextension/src/wallet/Refund.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Refund.stories.tsx
@@ -19,24 +19,18 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { ContractTerms, OrderShortInfo, PreparePayResultType } from '@gnu-taler/taler-util';
-import { FunctionalComponent, h } from 'preact';
+import { OrderShortInfo } from '@gnu-taler/taler-util';
+import { createExample } from '../test-utils';
import { View as TestedComponent } from './Refund';
export default {
- title: 'wallet/refund',
+ title: 'cta/refund',
component: TestedComponent,
argTypes: {
},
};
-function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
- const r = (args: any) => <Component {...args} />
- r.args = props
- return r
-}
-
export const Complete = createExample(TestedComponent, {
applyResult: {
amountEffectivePaid: 'USD:10',
diff --git a/packages/taler-wallet-webextension/src/wallet/Refund.tsx b/packages/taler-wallet-webextension/src/cta/Refund.tsx
index bb26d933b..bb26d933b 100644
--- a/packages/taler-wallet-webextension/src/wallet/Refund.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Refund.tsx
diff --git a/packages/taler-wallet-webextension/src/wallet/Tip.stories.tsx b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
index ffd976144..389b183f0 100644
--- a/packages/taler-wallet-webextension/src/wallet/Tip.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Tip.stories.tsx
@@ -19,24 +19,17 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { ContractTerms, PreparePayResultType } from '@gnu-taler/taler-util';
-import { FunctionalComponent, h } from 'preact';
+import { createExample } from '../test-utils';
import { View as TestedComponent } from './Tip';
export default {
- title: 'wallet/tip',
+ title: 'cta/tip',
component: TestedComponent,
argTypes: {
},
};
-function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
- const r = (args: any) => <Component {...args} />
- r.args = props
- return r
-}
-
export const Accepted = createExample(TestedComponent, {
prepareTipResult: {
accepted: true,
diff --git a/packages/taler-wallet-webextension/src/wallet/Tip.tsx b/packages/taler-wallet-webextension/src/cta/Tip.tsx
index 69886668b..69886668b 100644
--- a/packages/taler-wallet-webextension/src/wallet/Tip.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Tip.tsx
diff --git a/packages/taler-wallet-webextension/src/wallet/Withdraw.stories.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
index fef36b820..747f855fa 100644
--- a/packages/taler-wallet-webextension/src/wallet/Withdraw.stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.stories.tsx
@@ -19,32 +19,27 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { h } from 'preact';
-import { View, ViewProps } from './Withdraw';
+import { createExample } from '../test-utils';
+import { View as TestedComponent } from './Withdraw';
export default {
- title: 'wallet/withdraw',
- component: View,
+ title: 'cta/withdraw',
+ component: TestedComponent,
argTypes: {
},
};
-export const WithoutDetails = (a: any) => <View {...a} />;
-WithoutDetails.args = {
-} as ViewProps
-
-export const CompleteWithExchange = (a: any) => <View {...a} />;
-CompleteWithExchange.args = {
+export const CompleteWithExchange = createExample(TestedComponent, {
details: {
amount: 'USD:2',
+ possibleExchanges: [],
},
selectedExchange: 'Some exchange'
-} as ViewProps
-
-export const CompleteWithoutExchange = (a: any) => <View {...a} />;
-CompleteWithoutExchange.args = {
+})
+export const CompleteWithoutExchange = createExample(TestedComponent, {
details: {
amount: 'USD:2',
+ possibleExchanges: [],
},
-} as ViewProps
+})
diff --git a/packages/taler-wallet-webextension/src/wallet/Withdraw.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
index 442ee7dae..b5182b070 100644
--- a/packages/taler-wallet-webextension/src/wallet/Withdraw.tsx
+++ b/packages/taler-wallet-webextension/src/cta/Withdraw.tsx
@@ -32,14 +32,13 @@ import {
} from "../wxApi";
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
import { JSX } from "preact/jsx-runtime";
-import { WalletPage } from '../components/styled';
+import { WalletAction } from '../components/styled';
interface Props {
talerWithdrawUri?: string;
}
export interface ViewProps {
- talerWithdrawUri?: string;
details: WithdrawUriInfoResponse;
selectedExchange?: string;
accept: () => Promise<void>;
@@ -50,7 +49,7 @@ export interface ViewProps {
export function View({ details, selectedExchange, accept, setCancelled, setSelecting }: ViewProps) {
return (
- <WalletPage>
+ <WalletAction>
<div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
<h1 style="font-family: monospace; font-size: 250%;">
<span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
@@ -101,26 +100,19 @@ export function View({ details, selectedExchange, accept, setCancelled, setSelec
</div>
</div>
</div>
- </WalletPage>
+ </WalletAction>
)
}
export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element {
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
- const [selectedExchange, setSelectedExchange] = useState<
- string | undefined
- >(undefined);
+ const [selectedExchange, setSelectedExchange] = useState<string | undefined>(undefined);
const [cancelled, setCancelled] = useState(false);
const [selecting, setSelecting] = useState(false);
- const [errMsg, setErrMsg] = useState<string | undefined>("");
+ const [error, setError] = useState<boolean>(false);
const [updateCounter, setUpdateCounter] = useState(1);
const [state, setState] = useState(1)
- // setTimeout(() => {
- // console.log('tick...')
- // setState(s => s + 1)
- // }, 1000);
-
useEffect(() => {
return onUpdateNotification(() => {
console.log('updating...')
@@ -132,20 +124,19 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element
console.log('on effect yes', talerWithdrawUri)
if (!talerWithdrawUri) return
const fetchData = async (): Promise<void> => {
- console.log('que pasa')
try {
const res = await getWithdrawalDetailsForUri({ talerWithdrawUri });
- console.log('res', res)
setDetails(res);
if (res.defaultExchangeBaseUrl) {
setSelectedExchange(res.defaultExchangeBaseUrl);
}
} catch (e) {
- console.error(e)
+ console.error('error',JSON.stringify(e,undefined,2))
+ setError(true)
}
};
fetchData();
- }, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter, state]);
+ }, [selectedExchange, selecting, talerWithdrawUri, updateCounter, state]);
if (!talerWithdrawUri) {
return <span><i18n.Translate>missing withdraw uri</i18n.Translate></span>;
@@ -169,6 +160,9 @@ export function WithdrawPage({ talerWithdrawUri, ...rest }: Props): JSX.Element
if (cancelled) {
return <span><i18n.Translate>Withdraw operation has been cancelled.</i18n.Translate></span>;
}
+ if (error) {
+ return <span><i18n.Translate>This URI is not valid anymore.</i18n.Translate></span>;
+ }
return <View accept={accept}
setCancelled={setCancelled} setSelecting={setSelecting}
diff --git a/packages/taler-wallet-webextension/src/wallet/payback.tsx b/packages/taler-wallet-webextension/src/cta/payback.tsx
index 4233b1f96..4233b1f96 100644
--- a/packages/taler-wallet-webextension/src/wallet/payback.tsx
+++ b/packages/taler-wallet-webextension/src/cta/payback.tsx
diff --git a/packages/taler-wallet-webextension/src/wallet/reset-required.tsx b/packages/taler-wallet-webextension/src/cta/reset-required.tsx
index 87751561c..87751561c 100644
--- a/packages/taler-wallet-webextension/src/wallet/reset-required.tsx
+++ b/packages/taler-wallet-webextension/src/cta/reset-required.tsx
diff --git a/packages/taler-wallet-webextension/src/wallet/return-coins.tsx b/packages/taler-wallet-webextension/src/cta/return-coins.tsx
index 2273d1454..2273d1454 100644
--- a/packages/taler-wallet-webextension/src/wallet/return-coins.tsx
+++ b/packages/taler-wallet-webextension/src/cta/return-coins.tsx
diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
index 940d1f2a4..72139e1f8 100644
--- a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
@@ -25,7 +25,7 @@ import {
SmallText, SmallTextLight
} from "../components/styled";
import { useBackupStatus } from "../hooks/useBackupStatus";
-import { Pages } from "./popup";
+import { Pages } from "../NavigationBar";
interface Props {
onAddProvider: () => void;
diff --git a/packages/taler-wallet-webextension/src/popup/History.tsx b/packages/taler-wallet-webextension/src/popup/History.tsx
index b6b65314e..7c9eae54b 100644
--- a/packages/taler-wallet-webextension/src/popup/History.tsx
+++ b/packages/taler-wallet-webextension/src/popup/History.tsx
@@ -14,11 +14,19 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { AmountJson, Amounts, AmountString, Balance, Timestamp, Transaction, TransactionsResponse, TransactionType } from "@gnu-taler/taler-util";
+import { AmountString, Balance, Timestamp, Transaction, TransactionsResponse, TransactionType } from "@gnu-taler/taler-util";
+import { formatDistance } from "date-fns";
import { JSX } from "preact";
import { useEffect, useState } from "preact/hooks";
+import imageBank from '../../static/img/ri-bank-line.svg';
+import imageHandHeart from '../../static/img/ri-hand-heart-line.svg';
+import imageRefresh from '../../static/img/ri-refresh-line.svg';
+import imageRefund from '../../static/img/ri-refund-2-line.svg';
+import imageShoppingCart from '../../static/img/ri-shopping-cart-line.svg';
+import { Column, ExtraLargeText, HistoryRow, PopupBox, SmallTextLight } from "../components/styled";
+import { useBalances } from "../hooks/useBalances";
import * as wxApi from "../wxApi";
-import { Pages } from "./popup";
+import { Pages } from "../NavigationBar";
export function HistoryPage(props: any): JSX.Element {
@@ -45,7 +53,7 @@ export function HistoryPage(props: any): JSX.Element {
function amountToString(c: AmountString) {
const idx = c.indexOf(':')
- return `${c.substring(idx+1)} ${c.substring(0,idx)}`
+ return `${c.substring(idx + 1)} ${c.substring(0, idx)}`
}
@@ -68,20 +76,14 @@ export function HistoryView({ list, balances }: { list: Transaction[], balances:
))}
</section>
<footer style={{ justifyContent: 'space-around' }}>
- <a style={{ color: 'darkgreen', textDecoration:'none' }} href={Pages.transaction.replace(':tid', 'asd')}>VIEW MORE TRANSACTIONS</a>
+ <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>
}
-import imageBank from '../../static/img/ri-bank-line.svg';
-import imageShoppingCart from '../../static/img/ri-shopping-cart-line.svg';
-import imageRefund from '../../static/img/ri-refund-2-line.svg';
-import imageHandHeart from '../../static/img/ri-hand-heart-line.svg';
-import imageRefresh from '../../static/img/ri-refresh-line.svg';
-import { Column, ExtraLargeText, HistoryRow, PopupBox, Row, RowBorderGray, SmallTextLight } from "../components/styled";
-import { useBalances } from "../hooks/useBalances";
-import { formatDistance } from "date-fns";
-
function TransactionItem(props: { tx: Transaction }): JSX.Element {
const tx = props.tx;
switch (tx.type) {
@@ -171,18 +173,16 @@ function TransactionLayout(props: TransactionLayoutProps): JSX.Element {
const now = new Date();
const dateStr = formatDistance(date, now, { addSuffix: true })
return (
- <HistoryRow>
+ <HistoryRow href={Pages.transaction.replace(':tid', props.id)}>
<img src={props.iconPath} />
<Column>
<ExtraLargeText>
- <a href={Pages.transaction.replace(':tid', props.id)}><span>{props.title}</span></a>
+ <span>{props.title}</span>
{props.pending ? (
<span style={{ color: "darkblue" }}> (Pending)</span>
) : null}
</ExtraLargeText>
<SmallTextLight>{dateStr}</SmallTextLight>
-
- {/* <div>{props.subtitle}</div> */}
</Column>
<TransactionAmount
pending={props.pending}
diff --git a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx
index ec3634d9b..ce5b11c32 100644
--- a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx
@@ -20,7 +20,7 @@
*/
import { Fragment, FunctionalComponent } from 'preact';
-import { NavBar as TestedComponent } from './popup';
+import { NavBar as TestedComponent } from '../NavigationBar';
export default {
title: 'popup/header',
diff --git a/packages/taler-wallet-webextension/src/popup/Transaction.tsx b/packages/taler-wallet-webextension/src/popup/Transaction.tsx
index fd7389c04..8177b74ad 100644
--- a/packages/taler-wallet-webextension/src/popup/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Transaction.tsx
@@ -20,7 +20,7 @@ import { Fragment, JSX, VNode } from "preact";
import { route } from 'preact-router';
import { useEffect, useState } from "preact/hooks";
import * as wxApi from "../wxApi";
-import { Pages } from "./popup";
+import { Pages } from "../NavigationBar";
import emptyImg from "../../static/img/empty.png"
import { Button, ButtonDestructive, ButtonPrimary, ListOfProducts, PopupBox, Row, RowBorderGray, SmallTextLight } from "../components/styled";
import { ErrorMessage } from "../components/ErrorMessage";
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
index faa5149ac..4a9fe9abc 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
@@ -34,7 +34,7 @@ import { DeveloperPage as DeveloperPage } from "./popup/Debug";
import { HistoryPage } from "./popup/History";
import {
Pages, WalletNavBar
-} from "./popup/popup";
+} from "./NavigationBar";
import { ProviderAddPage } from "./popup/ProviderAddPage";
import { ProviderDetailPage } from "./popup/ProviderDetailPage";
import { SettingsPage } from "./popup/Settings";
@@ -129,4 +129,4 @@ function Redirect({ to }: { to: string }): null {
route(to, true)
})
return null
-} \ No newline at end of file
+}
diff --git a/packages/taler-wallet-webextension/src/test-utils.ts b/packages/taler-wallet-webextension/src/test-utils.ts
new file mode 100644
index 000000000..16262b3c2
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/test-utils.ts
@@ -0,0 +1,8 @@
+import { FunctionalComponent, h as render } from 'preact';
+
+export function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
+ const r = (args: any) => render(Component, args)
+ r.args = props
+ return r
+}
+
diff --git a/packages/taler-wallet-webextension/src/wallet/History.stories.tsx b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
new file mode 100644
index 000000000..f50fd3b68
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/History.stories.tsx
@@ -0,0 +1,294 @@
+/*
+ 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 {
+ PaymentStatus,
+ TransactionCommon, TransactionDeposit, TransactionPayment,
+ TransactionRefresh, TransactionRefund, TransactionTip, TransactionType,
+ TransactionWithdrawal,
+ WithdrawalType
+} from '@gnu-taler/taler-util';
+import { FunctionalComponent } from 'preact';
+import { HistoryView as TestedComponent } from './History';
+
+export default {
+ title: 'wallet/history/list',
+ component: TestedComponent,
+};
+
+let count = 0
+const commonTransaction = () => ({
+ amountRaw: 'USD:10',
+ amountEffective: 'USD:9',
+ pending: false,
+ timestamp: {
+ t_ms: new Date().getTime() - (count++ * 1000*60*60*7)
+ },
+ transactionId: '12',
+} as TransactionCommon)
+
+const exampleData = {
+ withdraw: {
+ ...commonTransaction(),
+ type: TransactionType.Withdrawal,
+ exchangeBaseUrl: 'http://exchange.taler',
+ withdrawalDetails: {
+ confirmed: false,
+ exchangePaytoUris: ['payto://x-taler-bank/bank/account'],
+ type: WithdrawalType.ManualTransfer,
+ }
+ } as TransactionWithdrawal,
+ payment: {
+ ...commonTransaction(),
+ amountEffective: 'USD:11',
+ type: TransactionType.Payment,
+ info: {
+ contractTermsHash: 'ASDZXCASD',
+ merchant: {
+ name: 'the merchant',
+ },
+ orderId: '2021.167-03NPY6MCYMVGT',
+ products: [],
+ summary: 'the summary',
+ fulfillmentMessage: '',
+ },
+ proposalId: '1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0',
+ status: PaymentStatus.Accepted,
+ } as TransactionPayment,
+ deposit: {
+ ...commonTransaction(),
+ type: TransactionType.Deposit,
+ depositGroupId: '#groupId',
+ targetPaytoUri: 'payto://x-taler-bank/bank/account',
+ } as TransactionDeposit,
+ refresh: {
+ ...commonTransaction(),
+ type: TransactionType.Refresh,
+ exchangeBaseUrl: 'http://exchange.taler',
+ } as TransactionRefresh,
+ tip: {
+ ...commonTransaction(),
+ type: TransactionType.Tip,
+ merchantBaseUrl: 'http://merchant.taler',
+ } as TransactionTip,
+ refund: {
+ ...commonTransaction(),
+ type: TransactionType.Refund,
+ refundedTransactionId: 'payment:1EMJJH8EP1NX3XF7733NCYS2DBEJW4Q2KA5KEB37MCQJQ8Q5HMC0',
+ info: {
+ contractTermsHash: 'ASDZXCASD',
+ merchant: {
+ name: 'the merchant',
+ },
+ orderId: '2021.167-03NPY6MCYMVGT',
+ products: [],
+ summary: 'the summary',
+ fulfillmentMessage: '',
+ },
+ } as TransactionRefund,
+}
+
+function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
+ const r = (args: any) => <Component {...args} />
+ r.args = props
+ return r
+}
+
+export const Empty = createExample(TestedComponent, {
+ list: [],
+ balances: [{
+ available: 'TESTKUDOS:10',
+ pendingIncoming: 'TESTKUDOS:0',
+ pendingOutgoing: 'TESTKUDOS:0',
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ }]
+});
+
+
+export const One = createExample(TestedComponent, {
+ list: [exampleData.withdraw],
+ balances: [{
+ available: 'USD:10',
+ pendingIncoming: 'USD:0',
+ pendingOutgoing: 'USD:0',
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ }]
+});
+
+export const Several = createExample(TestedComponent, {
+ list: [
+ exampleData.withdraw,
+ exampleData.payment,
+ exampleData.withdraw,
+ exampleData.payment,
+ exampleData.refresh,
+ exampleData.refund,
+ exampleData.tip,
+ exampleData.deposit,
+ ],
+ balances: [{
+ available: 'TESTKUDOS:10',
+ pendingIncoming: 'TESTKUDOS:0',
+ pendingOutgoing: 'TESTKUDOS:0',
+ hasPendingTransactions: false,
+ requiresUserInput: false,
+ }]
+});
+
+export const SeveralWithTwoCurrencies = createExample(TestedComponent, {
+ list: [
+ exampleData.withdraw,
+ exampleData.payment,
+ exampleData.withdraw,
+ exampleData.payment,
+ exampleData.refresh,
+ exampleData.refund,
+ 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,
+ }]
+});
+
+// export const WithdrawPending = createExample(TestedComponent, {
+// transaction: { ...exampleData.withdraw, pending: true },
+// });
+
+
+// export const Payment = createExample(TestedComponent, {
+// transaction: exampleData.payment
+// });
+
+// export const PaymentWithoutFee = createExample(TestedComponent, {
+// transaction: {
+// ...exampleData.payment,
+// amountRaw: 'USD:11',
+
+// }
+// });
+
+// export const PaymentPending = createExample(TestedComponent, {
+// transaction: { ...exampleData.payment, pending: true },
+// });
+
+// export const PaymentWithProducts = createExample(TestedComponent, {
+// transaction: {
+// ...exampleData.payment,
+// info: {
+// ...exampleData.payment.info,
+// summary: 'this order has 5 products',
+// products: [{
+// description: 't-shirt',
+// unit: 'shirts',
+// quantity: 1,
+// }, {
+// description: 't-shirt',
+// unit: 'shirts',
+// quantity: 1,
+// }, {
+// description: 'e-book',
+// }, {
+// description: 'beer',
+// unit: 'pint',
+// quantity: 15,
+// }, {
+// description: 'beer',
+// unit: 'pint',
+// quantity: 15,
+// }]
+// }
+// } as TransactionPayment,
+// });
+
+// export const PaymentWithLongSummary = createExample(TestedComponent, {
+// transaction: {
+// ...exampleData.payment,
+// info: {
+// ...exampleData.payment.info,
+// summary: 'this is a very long summary that will occupy severals lines, this is a very long summary that will occupy severals lines, this is a very long summary that will occupy severals lines, this is a very long summary that will occupy severals lines, ',
+// products: [{
+// description: 'an xl sized t-shirt with some drawings on it, color pink',
+// unit: 'shirts',
+// quantity: 1,
+// }, {
+// description: 'beer',
+// unit: 'pint',
+// quantity: 15,
+// }]
+// }
+// } as TransactionPayment,
+// });
+
+
+// export const Deposit = createExample(TestedComponent, {
+// transaction: exampleData.deposit
+// });
+
+// export const DepositPending = createExample(TestedComponent, {
+// transaction: { ...exampleData.deposit, pending: true }
+// });
+
+// export const Refresh = createExample(TestedComponent, {
+// transaction: exampleData.refresh
+// });
+
+// export const Tip = createExample(TestedComponent, {
+// transaction: exampleData.tip
+// });
+
+// export const TipPending = createExample(TestedComponent, {
+// transaction: { ...exampleData.tip, pending: true }
+// });
+
+// export const Refund = createExample(TestedComponent, {
+// transaction: exampleData.refund
+// });
+
+// export const RefundPending = createExample(TestedComponent, {
+// transaction: { ...exampleData.refund, pending: true }
+// });
+
+// export const RefundWithProducts = createExample(TestedComponent, {
+// transaction: {
+// ...exampleData.refund,
+// info: {
+// ...exampleData.refund.info,
+// products: [{
+// description: 't-shirt',
+// }, {
+// description: 'beer',
+// }]
+// }
+// } as TransactionRefund,
+// });
diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx b/packages/taler-wallet-webextension/src/wallet/History.tsx
new file mode 100644
index 000000000..6ef5047ae
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/History.tsx
@@ -0,0 +1,248 @@
+/*
+ This file is part of TALER
+ (C) 2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { AmountString, Balance, Timestamp, Transaction, TransactionsResponse, TransactionType } from "@gnu-taler/taler-util";
+import { format } from "date-fns";
+import { Fragment, JSX } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import imageBank from '../../static/img/ri-bank-line.svg';
+import imageHandHeart from '../../static/img/ri-hand-heart-line.svg';
+import imageRefresh from '../../static/img/ri-refresh-line.svg';
+import imageRefund from '../../static/img/ri-refund-2-line.svg';
+import imageShoppingCart from '../../static/img/ri-shopping-cart-line.svg';
+import { Column, ExtraLargeText, HistoryRow, WalletBox, DateSeparator, SmallTextLight } from "../components/styled";
+import { useBalances } from "../hooks/useBalances";
+import * as wxApi from "../wxApi";
+import { Pages } from "../NavigationBar";
+
+
+export function HistoryPage(props: any): JSX.Element {
+ const [transactions, setTransactions] = useState<
+ TransactionsResponse | undefined
+ >(undefined);
+ const balance = useBalances()
+ const balanceWithoutError = balance?.error ? [] : (balance?.response.balances || [])
+
+ useEffect(() => {
+ const fetchData = async (): Promise<void> => {
+ const res = await wxApi.getTransactions();
+ setTransactions(res);
+ };
+ fetchData();
+ }, []);
+
+ if (!transactions) {
+ return <div>Loading ...</div>;
+ }
+
+ 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)}`
+}
+
+
+
+export function HistoryView({ list, balances }: { list: Transaction[], balances: Balance[] }) {
+ const byDate = list.reduce(function (rv, x) {
+ const theDate = x.timestamp.t_ms === "never" ? "never" : format(x.timestamp.t_ms, 'dd MMMM yyyy');
+ (rv[theDate] = rv[theDate] || []).push(x);
+ return rv;
+ }, {} as { [x: string]: Transaction[] });
+
+ return <WalletBox noPadding>
+ {balances.length > 0 && <header>
+ {balances.length === 1 && <div class="title">
+ Balance: <span>{amountToString(balances[0].available)}</span>
+ </div>}
+ {balances.length > 1 && <div class="title">
+ Balance: <ul style={{ margin: 0 }}>
+ {balances.map(b => <li>{b.available}</li>)}
+ </ul>
+ </div>}
+ </header>}
+ <section>
+ {Object.keys(byDate).map(d => {
+ return <Fragment>
+ <DateSeparator>{d}</DateSeparator>
+ {byDate[d].map((tx, i) => (
+ <TransactionItem key={i} tx={tx} />
+ ))}
+ </Fragment>
+ })}
+ </section>
+ </WalletBox>
+}
+
+function TransactionItem(props: { tx: Transaction }): JSX.Element {
+ const tx = props.tx;
+ switch (tx.type) {
+ case TransactionType.Withdrawal:
+ return (
+ <TransactionLayout
+ id={tx.transactionId}
+ amount={tx.amountEffective}
+ debitCreditIndicator={"credit"}
+ title="Withdrawal"
+ subtitle={`via ${tx.exchangeBaseUrl}`}
+ timestamp={tx.timestamp}
+ iconPath={imageBank}
+ pending={tx.pending}
+ ></TransactionLayout>
+ );
+ case TransactionType.Payment:
+ return (
+ <TransactionLayout
+ id={tx.transactionId}
+ amount={tx.amountEffective}
+ debitCreditIndicator={"debit"}
+ title="Payment"
+ subtitle={tx.info.summary}
+ timestamp={tx.timestamp}
+ iconPath={imageShoppingCart}
+ pending={tx.pending}
+ ></TransactionLayout>
+ );
+ case TransactionType.Refund:
+ return (
+ <TransactionLayout
+ id={tx.transactionId}
+ amount={tx.amountEffective}
+ debitCreditIndicator={"credit"}
+ title="Refund"
+ subtitle={tx.info.summary}
+ timestamp={tx.timestamp}
+ iconPath={imageRefund}
+ pending={tx.pending}
+ ></TransactionLayout>
+ );
+ case TransactionType.Tip:
+ return (
+ <TransactionLayout
+ id={tx.transactionId}
+ amount={tx.amountEffective}
+ debitCreditIndicator={"credit"}
+ title="Tip"
+ subtitle={`from ${new URL(tx.merchantBaseUrl).hostname}`}
+ timestamp={tx.timestamp}
+ iconPath={imageHandHeart}
+ pending={tx.pending}
+ ></TransactionLayout>
+ );
+ case TransactionType.Refresh:
+ return (
+ <TransactionLayout
+ id={tx.transactionId}
+ amount={tx.amountEffective}
+ debitCreditIndicator={"credit"}
+ title="Refresh"
+ subtitle={`via exchange ${tx.exchangeBaseUrl}`}
+ timestamp={tx.timestamp}
+ iconPath={imageRefresh}
+ pending={tx.pending}
+ ></TransactionLayout>
+ );
+ case TransactionType.Deposit:
+ return (
+ <TransactionLayout
+ id={tx.transactionId}
+ amount={tx.amountEffective}
+ debitCreditIndicator={"debit"}
+ title="Refresh"
+ subtitle={`to ${tx.targetPaytoUri}`}
+ timestamp={tx.timestamp}
+ iconPath={imageRefresh}
+ pending={tx.pending}
+ ></TransactionLayout>
+ );
+ }
+}
+
+function TransactionLayout(props: TransactionLayoutProps): JSX.Element {
+ const date = new Date(props.timestamp.t_ms);
+ const dateStr = format(date, 'HH:mm:ss')
+ return (
+ // <a href={Pages.transaction.replace(':tid', props.id)}>
+ <HistoryRow href={Pages.transaction.replace(':tid', props.id)}>
+ <img src={props.iconPath} />
+ <Column>
+ <ExtraLargeText>
+ <span>{props.title}</span>
+ {props.pending ? (
+ <span style={{ color: "darkblue" }}> (Pending)</span>
+ ) : null}
+ </ExtraLargeText>
+ <SmallTextLight>{dateStr}</SmallTextLight>
+ </Column>
+ <TransactionAmount
+ pending={props.pending}
+ amount={props.amount}
+ debitCreditIndicator={props.debitCreditIndicator}
+ />
+ </HistoryRow>
+ // </a>
+ );
+}
+
+interface TransactionLayoutProps {
+ debitCreditIndicator: "debit" | "credit" | "unknown";
+ amount: AmountString | "unknown";
+ timestamp: Timestamp;
+ title: string;
+ id: string;
+ subtitle: string;
+ iconPath: string;
+ pending: boolean;
+}
+
+interface TransactionAmountProps {
+ debitCreditIndicator: "debit" | "credit" | "unknown";
+ amount: AmountString | "unknown";
+ pending: boolean;
+}
+
+function TransactionAmount(props: TransactionAmountProps): JSX.Element {
+ const [currency, amount] = props.amount.split(":");
+ let sign: string;
+ switch (props.debitCreditIndicator) {
+ case "credit":
+ sign = "+";
+ break;
+ case "debit":
+ sign = "-";
+ break;
+ case "unknown":
+ sign = "";
+ }
+ return (
+ <Column style={{
+ color:
+ props.pending ? "gray" :
+ (sign === '+' ? 'darkgreen' :
+ (sign === '-' ? 'darkred' :
+ undefined))
+ }}>
+ <ExtraLargeText>
+ {sign}
+ {amount}
+ </ExtraLargeText>
+ <div>{currency}</div>
+ </Column>
+ );
+}
+
diff --git a/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx
index 4fa87a137..6579450b3 100644
--- a/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Welcome.stories.tsx
@@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { FunctionalComponent, h } from 'preact';
+import { createExample } from '../test-utils';
import { View as TestedComponent } from './Welcome';
@@ -28,12 +28,6 @@ export default {
component: TestedComponent,
};
-function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
- const r = (args: any) => <Component {...args} />
- r.args = props
- return r
-}
-
export const Normal = createExample(TestedComponent, {
permissionsEnabled: true,
diagnostics: {
diff --git a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx
index 4c33e1c72..0738e14b6 100644
--- a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx
@@ -24,7 +24,7 @@ import { JSX } from "preact/jsx-runtime";
import { Checkbox } from "../components/Checkbox";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
import { Diagnostics } from "../components/Diagnostics";
-import { WalletPage } from "../components/styled";
+import { WalletBox } from "../components/styled";
import { useDiagnostics } from "../hooks/useDiagnostics";
import { WalletDiagnostics } from "@gnu-taler/taler-util";
@@ -44,12 +44,7 @@ export interface ViewProps {
timedOut: boolean,
}
export function View({ permissionsEnabled, togglePermissions, diagnostics, timedOut }: ViewProps): JSX.Element {
- return (<WalletPage>
- <div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
- <h1 style="font-family: monospace; font-size: 250%;">
- <span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
- </h1>
- </div>
+ return (<WalletBox>
<h1>Browser Extension Installed!</h1>
<div>
<p>Thank you for installing the wallet.</p>
@@ -68,6 +63,6 @@ export function View({ permissionsEnabled, togglePermissions, diagnostics, timed
Learn how to top up your wallet balance »
</a>
</div>
- </WalletPage>
+ </WalletBox>
);
}
diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
index f487e54fc..f8191a0fb 100644
--- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
@@ -20,17 +20,24 @@
* @author Florian Dold <dold@taler.net>
*/
-import { render } from "preact";
+import { Fragment, render } from "preact";
import { setupI18n } from "@gnu-taler/taler-util";
import { strings } from "./i18n/strings";
import { createHashHistory } from 'history';
-import { WithdrawPage } from "./wallet/Withdraw";
import { WelcomePage } from "./wallet/Welcome";
-import { PayPage } from "./wallet/Pay";
-import { RefundPage } from "./wallet/Refund";
-import { TipPage } from './wallet/Tip';
+import { HistoryPage } from "./wallet/History";
+import { WithdrawPage } from "./cta/Withdraw";
+import { PayPage } from "./cta/Pay";
+import { RefundPage } from "./cta/Refund";
+import { TipPage } from './cta/Tip';
import Router, { route, Route } from "preact-router";
+import { DevContextProvider } from "./context/devContext";
+import { LogoHeader } from "./components/LogoHeader";
+import { useEffect } from "preact/hooks";
+import {
+ Pages, WalletNavBar
+} from "./NavigationBar";
function main(): void {
try {
@@ -53,32 +60,43 @@ if (document.readyState === "loading") {
main();
}
-
-enum Pages {
- welcome = '/welcome',
- pay = '/pay',
- payback = '/payback',
- refund = '/refund',
- reset_required = '/reset-required',
- return_coins = '/return-coins',
- tips = '/tips',
- withdraw = '/withdraw',
+function withLogoAndNavBar(Component: any) {
+ return () => <Fragment>
+ <LogoHeader />
+ <WalletNavBar />
+ <Component />
+ </Fragment>
}
function Application() {
- const h = createHashHistory();
- return <Router history={h} >
+ return <div>
+ <DevContextProvider>
+ <Router history={createHashHistory()} >
+
+ <Route path={Pages.welcome} component={withLogoAndNavBar(WelcomePage)} />
- <Route path={Pages.welcome} component={WelcomePage} />
- <Route path={Pages.pay} component={PayPage} />
- <Route path={Pages.refund} component={RefundPage} />
+ <Route path={Pages.history} component={withLogoAndNavBar(HistoryPage)} />
+ <Route path={Pages.transaction} component={withLogoAndNavBar(HistoryPage)} />
- <Route path={Pages.tips} component={TipPage} />
- <Route path={Pages.withdraw} component={WithdrawPage} />
+ <Route path={Pages.reset_required} component={() => <div>no yet implemented</div>} />
+ <Route path={Pages.payback} component={() => <div>no yet implemented</div>} />
+ <Route path={Pages.return_coins} component={() => <div>no yet implemented</div>} />
- <Route path={Pages.reset_required} component={() => <div>no yet implemented</div>} />
- <Route path={Pages.payback} component={() => <div>no yet implemented</div>} />
- <Route path={Pages.return_coins} component={() => <div>no yet implemented</div>} />
+ {/** call to action */}
+ <Route path={Pages.pay} component={PayPage} />
+ <Route path={Pages.refund} component={RefundPage} />
+ <Route path={Pages.tips} component={TipPage} />
+ <Route path={Pages.withdraw} component={WithdrawPage} />
+
+ <Route default component={Redirect} to={Pages.history} />
+ </Router>
+ </DevContextProvider>
+ </div>
+}
- </Router>
+function Redirect({ to }: { to: string }): null {
+ useEffect(() => {
+ route(to, true)
+ })
+ return null
}
diff --git a/packages/taler-wallet-webextension/static/img/logo-2021.svg b/packages/taler-wallet-webextension/static/img/logo-2021.svg
new file mode 100644
index 000000000..e72611eba
--- /dev/null
+++ b/packages/taler-wallet-webextension/static/img/logo-2021.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns="http://www.w3.org/2000/svg" width="670" height="300" viewBox="0 0 201 90"><g fill="#0042b3" fill-rule="evenodd" stroke-width=".3"><path d="M86.7 1.1c15.6 0 29 9.4 36 23.2h-5.9A35.1 35.1 0 0086.7 6.5C67 6.5 51 23.6 51 44.7c0 10.4 3.8 19.7 10 26.6a31.4 31.4 0 01-4.2 3A45.2 45.2 0 0146 44.7c0-24 18.2-43.6 40.7-43.6zm35.8 64.3a40.4 40.4 0 01-39 22.8c3-1.5 6-3.5 8.6-5.7a35.6 35.6 0 0024.6-17.1z"/><path d="M64.2 1.1l3.1.1c-3 1.6-5.9 3.5-8.5 5.8a37.5 37.5 0 00-30.2 37.7c0 14.3 7.3 26.7 18 33.3a29.6 29.6 0 01-8.5.2c-9-8-14.6-20-14.6-33.5 0-24 18.2-43.6 40.7-43.6zm5.4 81.4a35.6 35.6 0 0024.6-17.1h5.9a40.4 40.4 0 01-39 22.8c3-1.5 5.9-3.5 8.5-5.7zm24.8-58.2a37 37 0 00-12.6-12.8 29.6 29.6 0 018.5-.2c4 3.6 7.4 8 9.9 13z"/><path d="M41.8 1.1c1 0 2 0 3.1.2-3 1.5-5.9 3.4-8.5 5.6A37.5 37.5 0 006.1 44.7c0 21.1 16 38.3 35.7 38.3 12.6 0 23.6-7 30-17.6h5.8a40.4 40.4 0 01-35.8 23C19.3 88.4 1 68.8 1 44.7c0-24 18.2-43.6 40.7-43.6zm30.1 23.2a38.1 38.1 0 00-4.5-6.1c1.3-1.2 2.7-2.2 4.3-3 2.3 2.7 4.4 5.8 6 9.1z"/></g><path d="M76.1 34.4h9.2v-5H61.9v5H71v26h5.1zM92.6 52.9h13.7l3 7.4h5.3l-12.7-31.2h-4.7L84.5 60.3h5.2zm11.8-4.9h-9.9l5-12.4zM123.8 29.4h-4.6v31h20.6v-5h-16zM166.5 29.4H145v31h21.6v-5H150v-8.3h14.5v-4.9h-14.5v-8h16.4zM191.2 39.5c0 1.6-.5 2.8-1.6 3.8s-2.6 1.4-4.4 1.4h-7.4V34.3h7.4c1.9 0 3.4.4 4.4 1.3 1 .9 1.6 2.2 1.6 3.9zm6 20.8l-7.7-11.7c1-.3 1.9-.7 2.7-1.3a8.8 8.8 0 003.6-4.6c.4-1 .5-2.2.5-3.5 0-1.5-.2-2.9-.7-4.1a8.4 8.4 0 00-2.1-3.1c-1-.8-2-1.5-3.4-2-1.3-.4-2.8-.6-4.5-.6h-12.9v31h5V49.4h6.5l7 10.8z"/></svg> \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/static/style/wallet.css b/packages/taler-wallet-webextension/static/style/wallet.css
index 32a96dbc4..859789149 100644
--- a/packages/taler-wallet-webextension/static/style/wallet.css
+++ b/packages/taler-wallet-webextension/static/style/wallet.css
@@ -2,6 +2,7 @@ body {
font-size: 100%;
overflow-y: scroll;
margin-top: 2em;
+ font-family: Arial, Helvetica, sans-serif;
}
.wallet-container {