aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2022-06-02 12:20:36 -0300
committerSebastian <sebasjm@gmail.com>2022-06-02 12:20:36 -0300
commit5d9390bb3437171353db99e7afd8cbcca432ba5c (patch)
treea71d71d26f32d8d4334c8d49f8766d8a287340de
parentaf7b107f455b01e136db2211c357cc59a506139a (diff)
typechecked dynamic path
-rw-r--r--packages/taler-wallet-webextension/src/NavigationBar.tsx119
-rw-r--r--packages/taler-wallet-webextension/src/components/PendingTransactions.tsx4
-rw-r--r--packages/taler-wallet-webextension/src/components/TransactionItem.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/popup/Application.tsx39
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Application.tsx68
-rw-r--r--packages/taler-wallet-webextension/src/wallet/BackupPage.tsx7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx9
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx3
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Settings.tsx4
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.tsx14
10 files changed, 146 insertions, 123 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index 58783a087..9c8e1ea29 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -40,43 +40,94 @@ import settingsIcon from "./svg/settings_black_24dp.svg";
* @author sebasjm
*/
-export enum Pages {
- welcome = "/welcome",
-
- balance = "/balance",
- balance_history = "/balance/history/:currency?",
- balance_manual_withdraw = "/balance/manual-withdraw/:currency?",
- balance_deposit = "/balance/deposit/:currency",
- balance_transaction = "/balance/transaction/:tid",
-
- dev = "/dev",
-
- backup = "/backup",
- backup_provider_detail = "/backup/provider/:pid",
- backup_provider_add = "/backup/provider/add",
-
- settings = "/settings",
- settings_exchange_add = "/settings/exchange/add/:currency?",
-
- cta = "/cta/:action",
- cta_pay = "/cta/pay",
- cta_refund = "/cta/refund",
- cta_tips = "/cta/tip",
- cta_withdraw = "/cta/withdraw",
- cta_deposit = "/cta/deposit",
+type PageLocation<DynamicPart extends object> = {
+ pattern: string;
+ (params: DynamicPart): string;
+};
+
+function replaceAll(
+ pattern: string,
+ vars: Record<string, string>,
+ values: Record<string, any>,
+): string {
+ let result = pattern;
+ for (const v in vars) {
+ result = result.replace(vars[v], values[v]);
+ }
+ return result;
}
+function pageDefinition<T extends object>(pattern: string): PageLocation<T> {
+ const patternParams = pattern.match(/(:[\w?]*)/g);
+ if (!patternParams)
+ throw Error(
+ `page definition pattern ${pattern} doesn't have any parameter`,
+ );
+
+ const vars = patternParams.reduce((prev, cur) => {
+ const pName = cur.match(/(\w+)/g);
+
+ //skip things like :? in the path pattern
+ if (!pName || !pName[0]) return prev;
+ const name = pName[0];
+ return { ...prev, [name]: cur };
+ }, {} as Record<string, string>);
+
+ const f = (values: T): string => replaceAll(pattern, vars, values);
+ f.pattern = pattern;
+ return f;
+}
+
+export const Pages = {
+ welcome: "/welcome",
+ balance: "/balance",
+ balanceHistory: pageDefinition<{ currency?: string }>(
+ "/balance/history/:currency?",
+ ),
+ balanceManualWithdraw: pageDefinition<{ currency?: string }>(
+ "/balance/manual-withdraw/:currency?",
+ ),
+ balanceDeposit: pageDefinition<{ currency: string }>(
+ "/balance/deposit/:currency",
+ ),
+ balanceTransaction: pageDefinition<{ tid: string }>(
+ "/balance/transaction/:tid",
+ ),
+ dev: "/dev",
+
+ backup: "/backup",
+ backupProviderDetail: pageDefinition<{ pid: string }>(
+ "/backup/provider/:pid",
+ ),
+ backupProviderAdd: "/backup/provider/add",
+
+ settings: "/settings",
+ settingsExchangeAdd: pageDefinition<{ currency?: string }>(
+ "/settings/exchange/add/:currency?",
+ ),
+
+ cta: pageDefinition<{ action: string }>("/cta/:action"),
+ ctaPay: "/cta/pay",
+ ctaRefund: "/cta/refund",
+ ctaTips: "/cta/tip",
+ ctaWithdraw: "/cta/withdraw",
+ ctaDeposit: "/cta/deposit",
+};
+
export function PopupNavBar({ path = "" }: { path?: string }): VNode {
const { i18n } = useTranslationContext();
return (
<NavigationHeader>
- <a href="/balance" class={path.startsWith("/balance") ? "active" : ""}>
+ <a
+ href={Pages.balance}
+ class={path.startsWith("/balance") ? "active" : ""}
+ >
<i18n.Translate>Balance</i18n.Translate>
</a>
- <a href="/backup" class={path.startsWith("/backup") ? "active" : ""}>
+ <a href={Pages.backup} class={path.startsWith("/backup") ? "active" : ""}>
<i18n.Translate>Backup</i18n.Translate>
</a>
- <a href="/settings">
+ <a href={Pages.settings}>
<SvgIcon
title={i18n.str`Settings`}
dangerouslySetInnerHTML={{ __html: settingsIcon }}
@@ -92,21 +143,27 @@ export function WalletNavBar({ path = "" }: { path?: string }): VNode {
return (
<NavigationHeaderHolder>
<NavigationHeader>
- <a href="/balance" class={path.startsWith("/balance") ? "active" : ""}>
+ <a
+ href={Pages.balance}
+ class={path.startsWith("/balance") ? "active" : ""}
+ >
<i18n.Translate>Balance</i18n.Translate>
</a>
- <a href="/backup" class={path.startsWith("/backup") ? "active" : ""}>
+ <a
+ href={Pages.backup}
+ class={path.startsWith("/backup") ? "active" : ""}
+ >
<i18n.Translate>Backup</i18n.Translate>
</a>
<JustInDevMode>
- <a href="/dev" class={path.startsWith("/dev") ? "active" : ""}>
+ <a href={Pages.dev} class={path.startsWith("/dev") ? "active" : ""}>
<i18n.Translate>Dev</i18n.Translate>
</a>
</JustInDevMode>
<a
- href="/settings"
+ href={Pages.settings}
class={path.startsWith("/settings") ? "active" : ""}
>
<i18n.Translate>Settings</i18n.Translate>
diff --git a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
index 2fc2d2d38..55287903a 100644
--- a/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
+++ b/packages/taler-wallet-webextension/src/components/PendingTransactions.tsx
@@ -14,7 +14,7 @@ import Banner from "./Banner.js";
import { Time } from "./Time.js";
interface Props extends JSX.HTMLAttributes {
- goToTransaction: (id: string) => void;
+ goToTransaction: (id: string) => Promise<void>;
}
export function PendingTransactions({ goToTransaction }: Props): VNode {
@@ -46,7 +46,7 @@ export function PendingTransactionsView({
transactions,
goToTransaction,
}: {
- goToTransaction: (id: string) => void;
+ goToTransaction: (id: string) => Promise<void>;
transactions: Transaction[];
}): VNode {
return (
diff --git a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
index bfffa3267..127d0411a 100644
--- a/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
+++ b/packages/taler-wallet-webextension/src/components/TransactionItem.tsx
@@ -120,7 +120,7 @@ function TransactionLayout(props: TransactionLayoutProps): VNode {
const { i18n } = useTranslationContext();
return (
<HistoryRow
- href={Pages.balance_transaction.replace(":tid", props.id)}
+ href={Pages.balanceTransaction({ tid: props.id })}
style={{
backgroundColor: props.pending ? "lightcyan" : "inherit",
alignItems: "center",
diff --git a/packages/taler-wallet-webextension/src/popup/Application.tsx b/packages/taler-wallet-webextension/src/popup/Application.tsx
index ba2886a41..d78677a9e 100644
--- a/packages/taler-wallet-webextension/src/popup/Application.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Application.tsx
@@ -45,8 +45,9 @@ function CheckTalerActionComponent(): VNode {
const [talerActionUrl] = useTalerActionURL();
useEffect(() => {
- if (talerActionUrl)
- route(Pages.cta.replace(":action", encodeURIComponent(talerActionUrl)));
+ if (talerActionUrl) {
+ route(Pages.cta({ action: encodeURIComponent(talerActionUrl) }));
+ }
}, [talerActionUrl]);
return <Fragment />;
@@ -60,8 +61,8 @@ export function Application(): VNode {
{({ devMode }: { devMode: boolean }) => (
<IoCProviderForRuntime>
<PendingTransactions
- goToTransaction={(txId: string) =>
- redirectTo(Pages.balance_transaction.replace(":tid", txId))
+ goToTransaction={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
}
/>
<Match>
@@ -74,24 +75,18 @@ export function Application(): VNode {
path={Pages.balance}
component={BalancePage}
goToWalletManualWithdraw={() =>
- redirectTo(
- Pages.balance_manual_withdraw.replace(":currency?", ""),
- )
+ redirectTo(Pages.balanceManualWithdraw({}))
}
goToWalletDeposit={(currency: string) =>
- redirectTo(
- Pages.balance_deposit.replace(":currency", currency),
- )
+ redirectTo(Pages.balanceDeposit({ currency }))
}
goToWalletHistory={(currency: string) =>
- redirectTo(
- Pages.balance_history.replace(":currency?", currency),
- )
+ redirectTo(Pages.balanceHistory({ currency }))
}
/>
<Route
- path={Pages.cta}
+ path={Pages.cta.pattern}
component={function Action({ action }: { action: string }) {
const [, setDismissed] = useTalerActionURL();
@@ -110,37 +105,37 @@ export function Application(): VNode {
<Route
path={Pages.backup}
component={BackupPage}
- onAddProvider={() => redirectTo(Pages.backup_provider_add)}
+ onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
/>
<Route
- path={Pages.backup_provider_detail}
+ path={Pages.backupProviderDetail.pattern}
component={ProviderDetailPage}
onBack={() => redirectTo(Pages.backup)}
/>
<Route
- path={Pages.balance_transaction}
+ path={Pages.balanceTransaction.pattern}
component={RedirectToWalletPage}
/>
<Route
- path={Pages.balance_manual_withdraw}
+ path={Pages.balanceManualWithdraw.pattern}
component={RedirectToWalletPage}
/>
<Route
- path={Pages.balance_deposit}
+ path={Pages.balanceDeposit.pattern}
component={RedirectToWalletPage}
/>
<Route
- path={Pages.balance_history}
+ path={Pages.balanceHistory.pattern}
component={RedirectToWalletPage}
/>
<Route
- path={Pages.backup_provider_add}
+ path={Pages.backupProviderAdd}
component={RedirectToWalletPage}
/>
<Route path={Pages.settings} component={RedirectToWalletPage} />
<Route
- path={Pages.settings_exchange_add}
+ path={Pages.settingsExchangeAdd.pattern}
component={RedirectToWalletPage}
/>
<Route path={Pages.dev} component={RedirectToWalletPage} />
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index 37ea80d96..84aa0dd84 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -93,10 +93,8 @@ export function Application(): VNode {
}}
>
<PendingTransactions
- goToTransaction={(txId: string) =>
- redirectTo(
- Pages.balance_transaction.replace(":tid", txId),
- )
+ goToTransaction={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
}
/>
</div>
@@ -122,50 +120,37 @@ export function Application(): VNode {
*/}
<Route
- path={Pages.balance_history}
+ path={Pages.balanceHistory.pattern}
component={HistoryPage}
goToWalletDeposit={(currency: string) =>
- redirectTo(
- Pages.balance_deposit.replace(":currency", currency),
- )
+ redirectTo(Pages.balanceDeposit({ currency }))
}
goToWalletManualWithdraw={(currency?: string) =>
- redirectTo(
- Pages.balance_manual_withdraw.replace(
- ":currency?",
- currency || "",
- ),
- )
+ redirectTo(Pages.balanceManualWithdraw({ currency }))
}
/>
<Route
- path={Pages.balance_transaction}
+ path={Pages.balanceTransaction.pattern}
component={TransactionPage}
goToWalletHistory={(currency?: string) =>
- redirectTo(
- Pages.balance_history.replace(":currency?", currency || ""),
- )
+ redirectTo(Pages.balanceHistory({ currency }))
}
/>
<Route
- path={Pages.balance_manual_withdraw}
+ path={Pages.balanceManualWithdraw.pattern}
component={ManualWithdrawPage}
onCancel={() => redirectTo(Pages.balance)}
/>
<Route
- path={Pages.balance_deposit}
+ path={Pages.balanceDeposit.pattern}
component={DepositPage}
onCancel={(currency: string) => {
- redirectTo(
- Pages.balance_history.replace(":currency?", currency),
- );
+ redirectTo(Pages.balanceHistory({ currency }));
}}
onSuccess={(currency: string) => {
- redirectTo(
- Pages.balance_history.replace(":currency?", currency),
- );
+ redirectTo(Pages.balanceHistory({ currency }));
setGlobalNotification(
<i18n.Translate>
All done, your transaction is in progress
@@ -184,15 +169,15 @@ export function Application(): VNode {
<Route
path={Pages.backup}
component={BackupPage}
- onAddProvider={() => redirectTo(Pages.backup_provider_add)}
+ onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
/>
<Route
- path={Pages.backup_provider_detail}
+ path={Pages.backupProviderDetail.pattern}
component={ProviderDetailPage}
onBack={() => redirectTo(Pages.backup)}
/>
<Route
- path={Pages.backup_provider_add}
+ path={Pages.backupProviderAdd}
component={ProviderAddPage}
onBack={() => redirectTo(Pages.backup)}
/>
@@ -201,7 +186,7 @@ export function Application(): VNode {
* SETTINGS
*/}
<Route
- path={Pages.settings_exchange_add}
+ path={Pages.settingsExchangeAdd.pattern}
component={ExchangeAddPage}
onBack={() => redirectTo(Pages.balance)}
/>
@@ -216,22 +201,17 @@ export function Application(): VNode {
* CALL TO ACTION
*/}
<Route
- path={Pages.cta_pay}
+ path={Pages.ctaPay}
component={PayPage}
goToWalletManualWithdraw={(currency?: string) =>
- redirectTo(
- Pages.balance_manual_withdraw.replace(
- ":currency?",
- currency || "",
- ),
- )
+ redirectTo(Pages.balanceManualWithdraw({ currency }))
}
goBack={() => redirectTo(Pages.balance)}
/>
- <Route path={Pages.cta_refund} component={RefundPage} />
- <Route path={Pages.cta_tips} component={TipPage} />
- <Route path={Pages.cta_withdraw} component={WithdrawPage} />
- <Route path={Pages.cta_deposit} component={DepositPageCTA} />
+ <Route path={Pages.ctaRefund} component={RefundPage} />
+ <Route path={Pages.ctaTips} component={TipPage} />
+ <Route path={Pages.ctaWithdraw} component={WithdrawPage} />
+ <Route path={Pages.ctaDeposit} component={DepositPageCTA} />
{/**
* NOT FOUND
@@ -240,13 +220,13 @@ export function Application(): VNode {
<Route
path={Pages.balance}
component={Redirect}
- to={Pages.balance_history.replace(":currency?", "")}
+ to={Pages.balanceHistory({})}
/>
<Route
default
component={Redirect}
- to={Pages.balance_history.replace(":currency?", "")}
+ to={Pages.balanceHistory({})}
/>
</Router>
</WalletBox>
@@ -268,5 +248,7 @@ function Redirect({ to }: { to: string }): null {
}
function shouldShowPendingOperations(path: string): boolean {
+ // FIXME: replace includes with a match API like preact router does
+ // [Pages.balanceHistory, Pages.dev, Pages.settings, Pages.backup]
return ["/balance/history/", "/dev", "/settings", "/backup"].includes(path);
}
diff --git a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
index 1f23be856..b1c34c213 100644
--- a/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/BackupPage.tsx
@@ -167,10 +167,9 @@ function BackupLayout(props: TransactionLayoutProps): VNode {
<RowBorderGray>
<div style={{ color: !props.active ? "grey" : undefined }}>
<a
- href={Pages.backup_provider_detail.replace(
- ":pid",
- encodeURIComponent(props.id),
- )}
+ href={Pages.backupProviderDetail({
+ pid: encodeURIComponent(props.id),
+ })}
>
<span>{props.title}</span>
</a>
diff --git a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx
index 502e9f8ad..d2a9c1366 100644
--- a/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/CreateManualWithdraw.tsx
@@ -165,10 +165,7 @@ export function CreateManualWithdraw({
</i18n.Translate>
</BoldLight>
<LinkPrimary
- href={Pages.settings_exchange_add.replace(
- ":currency?",
- initialCurrency,
- )}
+ href={Pages.settingsExchangeAdd({ currency: initialCurrency })}
style={{ marginLeft: "auto" }}
>
<i18n.Translate>Add Exchange</i18n.Translate>
@@ -194,7 +191,7 @@ export function CreateManualWithdraw({
<i18n.Translate>No exchange configured</i18n.Translate>
</BoldLight>
<LinkPrimary
- href={Pages.settings_exchange_add.replace(":currency?", "")}
+ href={Pages.settingsExchangeAdd({})}
style={{ marginLeft: "auto" }}
>
<i18n.Translate>Add Exchange</i18n.Translate>
@@ -242,7 +239,7 @@ export function CreateManualWithdraw({
</Input>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LinkPrimary
- href={Pages.settings_exchange_add.replace(":currency?", "")}
+ href={Pages.settingsExchangeAdd({})}
style={{ marginLeft: "auto" }}
>
<i18n.Translate>Add Exchange</i18n.Translate>
diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
index e71ea48f0..074b0d356 100644
--- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx
@@ -156,9 +156,6 @@ export function View({
[exchange_name: string]: CalculatedCoinfInfo[];
},
);
- function Item({ children }: any) {
- return <div>{children}</div>;
- }
return (
<div>
<p>
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
index be75c1eac..55f046259 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -178,9 +178,7 @@ export function SettingsView({
)}
<div style={{ display: "flex", justifyContent: "space-between" }}>
<div />
- <LinkPrimary
- href={Pages.settings_exchange_add.replace(":currency?", "")}
- >
+ <LinkPrimary href={Pages.settingsExchangeAdd({})}>
<i18n.Translate>Add an exchange</i18n.Translate>
</LinkPrimary>
</div>
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index b78039ddd..89f7064c5 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -352,10 +352,9 @@ export function TransactionView({
<td>
{<Amount value={r.amountEffective} />}{" "}
<a
- href={Pages.balance_transaction.replace(
- ":tid",
- r.transactionId,
- )}
+ href={Pages.balanceTransaction({
+ tid: r.transactionId,
+ })}
>
was refunded
</a>{" "}
@@ -556,10 +555,9 @@ export function TransactionView({
title={<i18n.Translate>Original order ID</i18n.Translate>}
text={
<a
- href={Pages.balance_transaction.replace(
- ":tid",
- transaction.refundedTransactionId,
- )}
+ href={Pages.balanceTransaction({
+ tid: transaction.refundedTransactionId,
+ })}
>
{transaction.info.orderId}
</a>