pending transaction, finally!

This commit is contained in:
Sebastian 2022-03-11 11:14:27 -03:00
parent 9337734a24
commit ab68ecc733
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
11 changed files with 236 additions and 33 deletions

View File

@ -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>

View 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",
]
}

View File

@ -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',
}), }),

View File

@ -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: (

View File

@ -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 && (

View File

@ -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,
],
});

View File

@ -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 {

View File

@ -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`

View File

@ -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}

View File

@ -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>

View File

@ -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}>