pending transaction, finally!
This commit is contained in:
parent
9337734a24
commit
ab68ecc733
@ -128,7 +128,7 @@ export const decorators = [
|
|||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
if (kind.startsWith('mui')) {
|
if (kind.startsWith('mui') || kind.startsWith('component')) {
|
||||||
return <div style={{ display: 'flex', flexWrap: 'wrap' }}>
|
return <div style={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||||
<Story />
|
<Story />
|
||||||
</div>
|
</div>
|
||||||
|
30
packages/taler-wallet-webextension/babel.config-linaria.json
Normal file
30
packages/taler-wallet-webextension/babel.config-linaria.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
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)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Linaria need pre-process typscript files into javascript before running.
|
||||||
|
* We choose to use the default preact-cli config.
|
||||||
|
* This file should be used from @linaria/rollup plugin only
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"preact-cli/babel",
|
||||||
|
]
|
||||||
|
}
|
@ -71,6 +71,10 @@ const makePlugins = () => [
|
|||||||
image(),
|
image(),
|
||||||
|
|
||||||
linaria({
|
linaria({
|
||||||
|
babelOptions: {
|
||||||
|
babelrc: false,
|
||||||
|
configFile: './babel.config-linaria.json',
|
||||||
|
},
|
||||||
sourceMap: process.env.NODE_ENV !== 'production',
|
sourceMap: process.env.NODE_ENV !== 'production',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ export const PendingOperation = () => (
|
|||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Banner
|
<Banner
|
||||||
title="PENDING TRANSACTIONS"
|
title="PENDING TRANSACTIONS"
|
||||||
style={{ backgroundColor: "lightblue", padding: 8 }}
|
style={{ backgroundColor: "lightcyan", padding: 8 }}
|
||||||
elements={[
|
elements={[
|
||||||
{
|
{
|
||||||
icon: (
|
icon: (
|
||||||
|
@ -29,16 +29,24 @@ export function Banner({ title, elements, confirm, ...rest }: Props) {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
<Grid container wrap="nowrap" spacing={1} alignItems="center">
|
<Grid container columns={1}>
|
||||||
{elements.map((e, i) => (
|
{elements.map((e, i) => (
|
||||||
<Fragment key={i}>
|
<Grid
|
||||||
|
container
|
||||||
|
item
|
||||||
|
xs={1}
|
||||||
|
key={i}
|
||||||
|
wrap="nowrap"
|
||||||
|
spacing={1}
|
||||||
|
alignItems="center"
|
||||||
|
>
|
||||||
{e.icon && (
|
{e.icon && (
|
||||||
<Grid item>
|
<Grid item xs={"auto"}>
|
||||||
<Avatar>{e.icon}</Avatar>
|
<Avatar>{e.icon}</Avatar>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
<Grid item>{e.description}</Grid>
|
<Grid item>{e.description}</Grid>
|
||||||
</Fragment>
|
</Grid>
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
{confirm && (
|
{confirm && (
|
||||||
|
@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
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 { PendingTransactionsView as TestedComponent } from "./PendingTransactions";
|
||||||
|
import { Fragment, h, VNode } from "preact";
|
||||||
|
import { createExample } from "../test-utils";
|
||||||
|
import { Transaction, TransactionType } from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "component/PendingTransactions",
|
||||||
|
component: TestedComponent,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OnePendingTransaction = createExample(TestedComponent, {
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ThreePendingTransactions = createExample(TestedComponent, {
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export const TenPendingTransactions = createExample(TestedComponent, {
|
||||||
|
transactions: [
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
{
|
||||||
|
amountEffective: "USD:10",
|
||||||
|
type: TransactionType.Withdrawal,
|
||||||
|
timestamp: {
|
||||||
|
t_ms: 1,
|
||||||
|
},
|
||||||
|
} as Transaction,
|
||||||
|
],
|
||||||
|
});
|
@ -1,20 +1,42 @@
|
|||||||
import { Amounts, Transaction } from "@gnu-taler/taler-util";
|
import { Amounts, NotificationType, Transaction } from "@gnu-taler/taler-util";
|
||||||
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
|
import { PendingTaskInfo } from "@gnu-taler/taler-wallet-core";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, JSX } from "preact";
|
||||||
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { Avatar } from "../mui/Avatar";
|
import { Avatar } from "../mui/Avatar";
|
||||||
import { Typography } from "../mui/Typography";
|
import { Typography } from "../mui/Typography";
|
||||||
import Banner from "./Banner";
|
import Banner from "./Banner";
|
||||||
import { Time } from "./Time";
|
import { Time } from "./Time";
|
||||||
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
interface Props {
|
interface Props extends JSX.HTMLAttributes {}
|
||||||
transactions: Transaction[];
|
|
||||||
|
export function PendingTransactions({}: Props) {
|
||||||
|
const state = useAsyncAsHook(wxApi.getTransactions, [
|
||||||
|
NotificationType.WithdrawGroupFinished,
|
||||||
|
]);
|
||||||
|
const transactions =
|
||||||
|
!state || state.hasError ? [] : state.response.transactions;
|
||||||
|
|
||||||
|
if (!state || state.hasError) {
|
||||||
|
return <Fragment />;
|
||||||
|
}
|
||||||
|
return <PendingTransactionsView transactions={transactions} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PendingTransactions({ transactions }: Props) {
|
export function PendingTransactionsView({
|
||||||
|
transactions,
|
||||||
|
}: {
|
||||||
|
transactions: Transaction[];
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<Banner
|
<Banner
|
||||||
title="PENDING OPERATIONS"
|
title="PENDING OPERATIONS"
|
||||||
style={{ backgroundColor: "lightblue", padding: 8 }}
|
style={{
|
||||||
|
backgroundColor: "lightcyan",
|
||||||
|
maxHeight: 150,
|
||||||
|
padding: 8,
|
||||||
|
overflowY: transactions.length > 3 ? "scroll" : "hidden",
|
||||||
|
}}
|
||||||
elements={transactions.map((t) => {
|
elements={transactions.map((t) => {
|
||||||
const amount = Amounts.parseOrThrow(t.amountEffective);
|
const amount = Amounts.parseOrThrow(t.amountEffective);
|
||||||
return {
|
return {
|
||||||
|
@ -15,7 +15,7 @@ interface Props {
|
|||||||
startIcon?: VNode;
|
startIcon?: VNode;
|
||||||
variant?: "contained" | "outlined" | "text";
|
variant?: "contained" | "outlined" | "text";
|
||||||
color?: "primary" | "secondary" | "success" | "error" | "info" | "warning";
|
color?: "primary" | "secondary" | "success" | "error" | "info" | "warning";
|
||||||
onClick: () => void;
|
onClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseStyle = css`
|
const baseStyle = css`
|
||||||
|
@ -28,7 +28,6 @@ import { JustInDevMode } from "../components/JustInDevMode";
|
|||||||
import { Loading } from "../components/Loading";
|
import { Loading } from "../components/Loading";
|
||||||
import { LoadingError } from "../components/LoadingError";
|
import { LoadingError } from "../components/LoadingError";
|
||||||
import { MultiActionButton } from "../components/MultiActionButton";
|
import { MultiActionButton } from "../components/MultiActionButton";
|
||||||
import PendingTransactions from "../components/PendingTransactions";
|
|
||||||
import { ButtonBoxPrimary, ButtonPrimary } from "../components/styled";
|
import { ButtonBoxPrimary, ButtonPrimary } from "../components/styled";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
|
||||||
import { AddNewActionView } from "../wallet/AddNewActionView";
|
import { AddNewActionView } from "../wallet/AddNewActionView";
|
||||||
@ -46,19 +45,10 @@ export function BalancePage({
|
|||||||
goToWalletHistory,
|
goToWalletHistory,
|
||||||
}: Props): VNode {
|
}: Props): VNode {
|
||||||
const [addingAction, setAddingAction] = useState(false);
|
const [addingAction, setAddingAction] = useState(false);
|
||||||
const state = useAsyncAsHook(
|
const state = useAsyncAsHook(wxApi.getBalance, [
|
||||||
async () => ({
|
NotificationType.WithdrawGroupFinished,
|
||||||
balance: await wxApi.getBalance(),
|
]);
|
||||||
pending: await wxApi.getTransactions(),
|
const balances = !state || state.hasError ? [] : state.response.balances;
|
||||||
}),
|
|
||||||
[NotificationType.WithdrawGroupFinished],
|
|
||||||
);
|
|
||||||
const balances =
|
|
||||||
!state || state.hasError ? [] : state.response.balance.balances;
|
|
||||||
const pending =
|
|
||||||
!state || state.hasError
|
|
||||||
? []
|
|
||||||
: state.response.pending.transactions.filter((t) => t.pending);
|
|
||||||
|
|
||||||
if (!state) {
|
if (!state) {
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
@ -80,7 +70,6 @@ export function BalancePage({
|
|||||||
return (
|
return (
|
||||||
<BalanceView
|
<BalanceView
|
||||||
balances={balances}
|
balances={balances}
|
||||||
pending={pending}
|
|
||||||
goToWalletManualWithdraw={goToWalletManualWithdraw}
|
goToWalletManualWithdraw={goToWalletManualWithdraw}
|
||||||
goToWalletDeposit={goToWalletDeposit}
|
goToWalletDeposit={goToWalletDeposit}
|
||||||
goToWalletHistory={goToWalletHistory}
|
goToWalletHistory={goToWalletHistory}
|
||||||
@ -90,7 +79,6 @@ export function BalancePage({
|
|||||||
}
|
}
|
||||||
export interface BalanceViewProps {
|
export interface BalanceViewProps {
|
||||||
balances: Balance[];
|
balances: Balance[];
|
||||||
pending: Transaction[];
|
|
||||||
goToWalletManualWithdraw: () => void;
|
goToWalletManualWithdraw: () => void;
|
||||||
goToAddAction: () => void;
|
goToAddAction: () => void;
|
||||||
goToWalletDeposit: (currency: string) => void;
|
goToWalletDeposit: (currency: string) => void;
|
||||||
@ -99,7 +87,6 @@ export interface BalanceViewProps {
|
|||||||
|
|
||||||
export function BalanceView({
|
export function BalanceView({
|
||||||
balances,
|
balances,
|
||||||
pending,
|
|
||||||
goToWalletManualWithdraw,
|
goToWalletManualWithdraw,
|
||||||
goToWalletDeposit,
|
goToWalletDeposit,
|
||||||
goToWalletHistory,
|
goToWalletHistory,
|
||||||
@ -117,9 +104,6 @@ export function BalanceView({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
{/* {pending.length > 0 ? (
|
|
||||||
<PendingTransactions transactions={pending} />
|
|
||||||
) : undefined} */}
|
|
||||||
<section>
|
<section>
|
||||||
<BalanceTable
|
<BalanceTable
|
||||||
balances={balances}
|
balances={balances}
|
||||||
|
@ -26,6 +26,7 @@ import { Fragment, h, render, VNode } from "preact";
|
|||||||
import Router, { route, Route } from "preact-router";
|
import Router, { route, Route } from "preact-router";
|
||||||
import { Match } from "preact-router/match";
|
import { Match } from "preact-router/match";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
|
import PendingTransactions from "./components/PendingTransactions";
|
||||||
import { PopupBox } from "./components/styled";
|
import { PopupBox } from "./components/styled";
|
||||||
import { DevContextProvider } from "./context/devContext";
|
import { DevContextProvider } from "./context/devContext";
|
||||||
import { IoCProviderForRuntime } from "./context/iocContext";
|
import { IoCProviderForRuntime } from "./context/iocContext";
|
||||||
@ -82,6 +83,7 @@ function Application(): VNode {
|
|||||||
<DevContextProvider>
|
<DevContextProvider>
|
||||||
{({ devMode }: { devMode: boolean }) => (
|
{({ devMode }: { devMode: boolean }) => (
|
||||||
<IoCProviderForRuntime>
|
<IoCProviderForRuntime>
|
||||||
|
<PendingTransactions />
|
||||||
<Match>
|
<Match>
|
||||||
{({ path }: { path: string }) => <PopupNavBar path={path} />}
|
{({ path }: { path: string }) => <PopupNavBar path={path} />}
|
||||||
</Match>
|
</Match>
|
||||||
|
@ -27,6 +27,7 @@ import Router, { route, Route } from "preact-router";
|
|||||||
import Match from "preact-router/match";
|
import Match from "preact-router/match";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { LogoHeader } from "./components/LogoHeader";
|
import { LogoHeader } from "./components/LogoHeader";
|
||||||
|
import PendingTransactions from "./components/PendingTransactions";
|
||||||
import {
|
import {
|
||||||
NavigationHeader,
|
NavigationHeader,
|
||||||
NavigationHeaderHolder,
|
NavigationHeaderHolder,
|
||||||
@ -112,6 +113,15 @@ function Application(): VNode {
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Match>
|
</Match>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: "lightcyan",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PendingTransactions />
|
||||||
|
</div>
|
||||||
<WalletBox>
|
<WalletBox>
|
||||||
{globalNotification && (
|
{globalNotification && (
|
||||||
<SuccessBox onClick={clearNotification}>
|
<SuccessBox onClick={clearNotification}>
|
||||||
|
Loading…
Reference in New Issue
Block a user