aboutsummaryrefslogtreecommitdiff
path: root/packages/auditor-backoffice-ui
diff options
context:
space:
mode:
Diffstat (limited to 'packages/auditor-backoffice-ui')
-rw-r--r--packages/auditor-backoffice-ui/package.json5
-rw-r--r--packages/auditor-backoffice-ui/src/Application.tsx240
-rw-r--r--packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx87
-rw-r--r--packages/auditor-backoffice-ui/src/InstanceRoutes.tsx856
-rw-r--r--packages/auditor-backoffice-ui/src/components/exception/loading.tsx40
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/FormProvider.tsx16
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/Input.tsx116
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/InputCurrency.tsx67
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/InputNumber.tsx60
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/InputSelector.tsx94
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/InputToggle.tsx91
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/InputWithAddon.tsx116
-rw-r--r--packages/auditor-backoffice-ui/src/components/forms/useField.tsx92
-rw-r--r--packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx8
-rw-r--r--packages/auditor-backoffice-ui/src/components/menu/index.tsx374
-rw-r--r--packages/auditor-backoffice-ui/src/components/modal/index.tsx408
-rw-r--r--packages/auditor-backoffice-ui/src/context/backend.ts42
-rw-r--r--packages/auditor-backoffice-ui/src/declaration.d.ts625
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/backend.ts372
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/critical.ts15
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/entity.ts29
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/finance.ts20
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/index.ts105
-rw-r--r--packages/auditor-backoffice-ui/src/hooks/operational.ts25
-rw-r--r--packages/auditor-backoffice-ui/src/index.tsx2
-rw-r--r--packages/auditor-backoffice-ui/src/paths/default/Table.tsx119
-rw-r--r--packages/auditor-backoffice-ui/src/paths/default/index.tsx48
-rw-r--r--packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx145
-rw-r--r--packages/auditor-backoffice-ui/src/paths/details/index.tsx3
-rw-r--r--packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx220
-rw-r--r--packages/auditor-backoffice-ui/src/paths/finance/index.tsx30
-rw-r--r--packages/auditor-backoffice-ui/src/paths/login/index.tsx213
-rw-r--r--packages/auditor-backoffice-ui/src/paths/notfound/index.tsx16
-rw-r--r--packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx69
-rw-r--r--packages/auditor-backoffice-ui/src/paths/operations/index.tsx30
-rw-r--r--packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx51
-rw-r--r--packages/auditor-backoffice-ui/src/paths/security/index.tsx33
-rw-r--r--packages/auditor-backoffice-ui/src/paths/settings/index.tsx132
-rw-r--r--packages/auditor-backoffice-ui/src/schemas/index.ts245
-rw-r--r--packages/auditor-backoffice-ui/src/scss/_aside.scss7
-rw-r--r--packages/auditor-backoffice-ui/src/utils/amount.ts72
-rw-r--r--packages/auditor-backoffice-ui/src/utils/constants.ts197
-rw-r--r--packages/auditor-backoffice-ui/src/utils/regex.test.ts88
-rw-r--r--packages/auditor-backoffice-ui/src/utils/table.ts57
-rw-r--r--packages/auditor-backoffice-ui/src/utils/types.ts7
45 files changed, 1774 insertions, 3913 deletions
diff --git a/packages/auditor-backoffice-ui/package.json b/packages/auditor-backoffice-ui/package.json
index bbebabf39..78a09b1fd 100644
--- a/packages/auditor-backoffice-ui/package.json
+++ b/packages/auditor-backoffice-ui/package.json
@@ -1,15 +1,14 @@
{
"private": true,
"name": "@gnu-taler/auditor-backoffice-ui",
- "version": "0.12.2",
+ "version": "0.13.5",
"license": "AGPL-3.0-or-later",
"type": "module",
"scripts": {
"clean": "rm -rf dist lib tsconfig.tsbuildinfo",
- "build": "./build.mjs",
"check": "tsc",
"compile": "tsc && ./build.mjs",
- "dev": "preact watch --port ${PORT:=8080} --no-sw --no-esm",
+ "dev": "./dev.mjs",
"test": "./test.mjs && mocha --require source-map-support/register 'dist/**/*.test.js' 'dist/**/test.js'",
"lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
"i18n:extract": "pogen extract",
diff --git a/packages/auditor-backoffice-ui/src/Application.tsx b/packages/auditor-backoffice-ui/src/Application.tsx
index 3b6aa8dd3..4188a53a6 100644
--- a/packages/auditor-backoffice-ui/src/Application.tsx
+++ b/packages/auditor-backoffice-ui/src/Application.tsx
@@ -20,35 +20,33 @@
* @author Nic Eigel
*/
-import {HttpStatusCode, LibtoolVersion} from "@gnu-taler/taler-util";
+import { HttpStatusCode, LibtoolVersion } from "@gnu-taler/taler-util";
import {
- ErrorType,
- TranslationProvider,
- useTranslationContext
+ ErrorType,
+ TranslationProvider,
+ useTranslationContext,
} from "@gnu-taler/web-util/browser";
-import {Fragment, VNode, h, render} from "preact";
-import {useMemo} from "preact/hooks";
-import {ApplicationReadyRoutes} from "./ApplicationReadyRoutes.js";
-import {Loading} from "./components/exception/loading.js";
+import { Fragment, VNode, h } from "preact";
+import { useMemo } from "preact/hooks";
+import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes.js";
+import { Loading } from "./components/exception/loading.js";
import {
- NotConnectedAppMenu,
- NotificationCard
+ NotConnectedAppMenu,
+ NotificationCard,
} from "./components/menu/index.js";
-import {
- BackendContextProvider
-} from "./context/backend.js";
-import {ConfigContextProvider} from "./context/config.js";
-import {useBackendConfig} from "./hooks/backend.js";
+import { BackendContextProvider } from "./context/backend.js";
+import { ConfigContextProvider } from "./context/config.js";
+import { useBackendConfig } from "./hooks/backend.js";
import { strings } from "./i18n/strings.js";
export function Application(): VNode {
- return (
- <BackendContextProvider>
- <TranslationProvider source={strings}>
- <ApplicationStatusRoutes/>
- </TranslationProvider>
- </BackendContextProvider>
- );
+ return (
+ <BackendContextProvider>
+ <TranslationProvider source={strings}>
+ <ApplicationStatusRoutes />
+ </TranslationProvider>
+ </BackendContextProvider>
+ );
}
/**
@@ -57,110 +55,110 @@ export function Application(): VNode {
* @returns
*/
function ApplicationStatusRoutes(): VNode {
- const result = useBackendConfig();
- const {i18n} = useTranslationContext();
+ const result = useBackendConfig();
+ const { i18n } = useTranslationContext();
- const configData = result.ok && result.data
- ? result.data
- : undefined;
- const ctx = useMemo(() => (configData), [configData]);
+ const configData = result.ok && result.data ? result.data : undefined;
+ const ctx = useMemo(() => configData, [configData]);
- if (!result.ok) {
- if (result.loading) return <Loading/>;
- if (
- result.type === ErrorType.CLIENT &&
- result.status === HttpStatusCode.Unauthorized
- ) {
- return (
- <Fragment>
- <NotConnectedAppMenu title="Login"/>
- <NotificationCard
- notification={{
- message: i18n.str`Checking the /config endpoint got authorization error`,
- type: "ERROR",
- description: `The /config endpoint of the backend server should be accessible`,
- }}
- />
- </Fragment>
- );
- }
- if (
- result.type === ErrorType.CLIENT &&
- result.status === HttpStatusCode.NotFound
- ) {
- return (
- <Fragment>
- <NotConnectedAppMenu title="Error"/>
- <NotificationCard
- notification={{
- message: i18n.str`Could not find /config endpoint on this URL`,
- type: "ERROR",
- description: `Check the URL or contact the system administrator.`,
- }}
- />
- </Fragment>
- );
- }
- if (result.type === ErrorType.SERVER) {
- <Fragment>
- <NotConnectedAppMenu title="Error"/>
- <NotificationCard
- notification={{
- message: i18n.str`Server response with an error code`,
- type: "ERROR",
- description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
- }}
- />
- </Fragment>;
- }
- if (result.type === ErrorType.UNREADABLE) {
- <Fragment>
- <NotConnectedAppMenu title="Error"/>
- <NotificationCard
- notification={{
- message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
- type: "ERROR",
- description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
- }}
- />
- </Fragment>;
- }
- return (
- <Fragment>
- <NotConnectedAppMenu title="Error"/>
- <NotificationCard
- notification={{
- message: i18n.str`Unexpected Error`,
- type: "ERROR",
- description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
- }}
- />
- </Fragment>
- );
+ if (!result.ok) {
+ if (result.loading) return <Loading />;
+ if (
+ result.type === ErrorType.CLIENT &&
+ result.status === HttpStatusCode.Unauthorized
+ ) {
+ return (
+ <Fragment>
+ <NotConnectedAppMenu title="Login" />
+ <NotificationCard
+ notification={{
+ message: i18n.str`Checking the /config endpoint got authorization error`,
+ type: "ERROR",
+ description: `The /config endpoint of the backend server should be accessible`,
+ }}
+ />
+ </Fragment>
+ );
}
-
- const SUPPORTED_VERSION = "1:0:1"
- if (result.data && !LibtoolVersion.compare(
- SUPPORTED_VERSION,
- result.data.version,
- )?.compatible) {
- return <Fragment>
- <NotConnectedAppMenu title="Error"/>
- <NotificationCard
- notification={{
- message: i18n.str`Incompatible version`,
- type: "ERROR",
- description: i18n.str`Auditor backend server version ${result.data.version} is not compatible with the supported version ${SUPPORTED_VERSION}`,
- }}
- />
+ if (
+ result.type === ErrorType.CLIENT &&
+ result.status === HttpStatusCode.NotFound
+ ) {
+ return (
+ <Fragment>
+ <NotConnectedAppMenu title="Error" />
+ <NotificationCard
+ notification={{
+ message: i18n.str`Could not find /config endpoint on this URL`,
+ type: "ERROR",
+ description: `Check the URL or contact the system administrator.`,
+ }}
+ />
</Fragment>
+ );
+ }
+ if (result.type === ErrorType.SERVER) {
+ <Fragment>
+ <NotConnectedAppMenu title="Error" />
+ <NotificationCard
+ notification={{
+ message: i18n.str`Server response with an error code`,
+ type: "ERROR",
+ description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
+ }}
+ />
+ </Fragment>;
}
+ if (result.type === ErrorType.UNREADABLE) {
+ <Fragment>
+ <NotConnectedAppMenu title="Error" />
+ <NotificationCard
+ notification={{
+ message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
+ type: "ERROR",
+ description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
+ }}
+ />
+ </Fragment>;
+ }
+ return (
+ <Fragment>
+ <NotConnectedAppMenu title="Error" />
+ <NotificationCard
+ notification={{
+ message: i18n.str`Unexpected Error`,
+ type: "ERROR",
+ description: i18n.str`Got message "${result.message}" from ${result.info?.url}`,
+ }}
+ />
+ </Fragment>
+ );
+ }
+ const SUPPORTED_VERSION = "1:0:1";
+ if (
+ result.data &&
+ !LibtoolVersion.compare(SUPPORTED_VERSION, result.data.version)?.compatible
+ ) {
return (
- <div class="has-navbar-fixed-top">
- <ConfigContextProvider value={ctx!}>
- <ApplicationReadyRoutes/>
- </ConfigContextProvider>
- </div>
+ <Fragment>
+ <NotConnectedAppMenu title="Error" />
+ <NotificationCard
+ notification={{
+ message: i18n.str`Incompatible version`,
+ type: "ERROR",
+ description: i18n.str`Auditor backend server version ${result.data.version} is not compatible with the supported version ${SUPPORTED_VERSION}`,
+ }}
+ />
+ </Fragment>
);
-} \ No newline at end of file
+ }
+
+ return (
+ <div class="has-navbar-fixed-top">
+ <ConfigContextProvider value={ctx!}>
+ <ApplicationReadyRoutes />
+ </ConfigContextProvider>
+ </div>
+ );
+}
diff --git a/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx b/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx
index 576792d6f..9e0bda499 100644
--- a/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx
+++ b/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx
@@ -19,71 +19,52 @@
* @author Sebastian Javier Marchano (sebasjm)
* @author Nic Eigel
*/
-import {ErrorType, useTranslationContext} from "@gnu-taler/web-util/browser";
-import {createHashHistory} from "history";
-import {Fragment, VNode, h} from "preact";
-import {Route, Router, route} from "preact-router";
-import {useEffect, useErrorBoundary, useState} from "preact/hooks";
-import {InstanceRoutes} from "./InstanceRoutes.js";
-import {
- NotConnectedAppMenu,
- NotYetReadyAppMenu,
- NotificationCard,
-} from "./components/menu/index.js";
-import { useBackendContext, useBackendTokenContext } from "./context/backend.js";
-import {Settings} from "./paths/settings/index.js";
-import { useBackendConfig, useBackendToken } from "./hooks/backend.js";
+import { createHashHistory } from "history";
+import { Fragment, VNode, h } from "preact";
+import { Route, Router } from "preact-router";
+import { useState } from "preact/hooks";
+import { InstanceRoutes } from "./InstanceRoutes.js";
import { Loading } from "./components/exception/loading.js";
+import { NotYetReadyAppMenu } from "./components/menu/index.js";
+import { useBackendToken } from "./hooks/backend.js";
import { LoginPage } from "./paths/login/index.js";
+import { Settings } from "./paths/settings/index.js";
/**
* Check if admin against /management/instances
* @returns
*/
export function ApplicationReadyRoutes(): VNode {
- const {i18n} = useTranslationContext();
- const [unauthorized, setUnauthorized] = useState(false)
- const [backendToken, setToken] = useState(false)
- const { url: backendURL} = useBackendContext();
- const { token } = useBackendTokenContext();
+ //TODO FIX bearer
+ const result = useBackendToken();
+ if (result.loading) return <Loading />;
+ if (!result.ok) {
+ return <LoginPage />;
+ }
+ const [showSettings, setShowSettings] = useState(false);
- //TODO FIX bearer
- const result = useBackendToken();
- if (result.loading) return <Loading/>;
- if (!result.ok) {
- return (
- <LoginPage />
- );
- }
- const [showSettings, setShowSettings] = useState(false)
-
- if (showSettings) {
- return <Fragment>
- <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="UI Settings"/>
- <Settings onClose={() => setShowSettings(false)}/>
- </Fragment>
- }
-
- const history = createHashHistory();
+ if (showSettings) {
return (
- <Router history={history}>
- <Route
- default
- component={DefaultMainRoute}
- />
- </Router>
+ <Fragment>
+ <NotYetReadyAppMenu
+ onShowSettings={() => setShowSettings(true)}
+ title="UI Settings"
+ />
+ <Settings onClose={() => setShowSettings(false)} />
+ </Fragment>
);
+ }
+
+ const history = createHashHistory();
+ return (
+ <Router history={history}>
+ <Route default component={DefaultMainRoute} />
+ </Router>
+ );
}
function DefaultMainRoute({
- url, //from preact-router
- }: any): VNode {
- //TODO
- url = "app/#" + url;
-
- return (
- <InstanceRoutes
- path={url}
- />
- );
+ url, //from preact-router
+}: any): VNode {
+ return <InstanceRoutes path={url} />;
}
diff --git a/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx b/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx
index 83c1c9f4d..ab3f3dde3 100644
--- a/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx
+++ b/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx
@@ -20,202 +20,275 @@
* @author Nicola Eigel
*/
-import {TranslatedString} from "@gnu-taler/taler-util";
-import {
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
-import {VNode, h} from "preact";
-import {Route, Router, route} from "preact-router";
-import {useEffect, useErrorBoundary, useMemo, useState} from "preact/hooks";
-import {Menu, NotificationCard} from "./components/menu/index.js";
-import {EntityContextProvider} from "./context/entity.js";
-import {Notification} from "./utils/types.js";
-import NotFoundPage from "./paths/notfound/index.js";
-import {Settings} from "./paths/settings/index.js";
+import { TranslatedString } from "@gnu-taler/taler-util";
+import { VNode, h } from "preact";
+import { Route, Router, route } from "preact-router";
+import { useEffect, useErrorBoundary, useMemo, useState } from "preact/hooks";
+import { Menu, NotificationCard } from "./components/menu/index.js";
+import { EntityContextProvider } from "./context/entity.js";
+import { AuditorBackend } from "./declaration.js";
import DefaultList from "./paths/default/index.js";
-import {
- AuditorBackend,
-} from "./declaration.js";
-import FinanceDashboard from "./paths/finance/index.js";
import DetailsDashboard from "./paths/details/index.js";
+import FinanceDashboard from "./paths/finance/index.js";
+import NotFoundPage from "./paths/notfound/index.js";
import OperationsDashboard from "./paths/operations/index.js";
import SecurityDashboard from "./paths/security/index.js";
+import { Settings } from "./paths/settings/index.js";
+import { Notification } from "./utils/types.js";
export enum Paths {
- error = "/error",
- settings = "/settings",
+ error = "/error",
+ settings = "/settings",
- key_figures = "/key-figures",
- critical_errors = "/critical-errors",
- operating_status = "/operating-status",
- detail_view = "/detail-view",
+ key_figures = "/key-figures",
+ critical_errors = "/critical-errors",
+ operating_status = "/operating-status",
+ detail_view = "/detail-view",
- amount_arithmethic_inconsistency_list = "/amount-arithmetic-inconsistencies",
+ amount_arithmethic_inconsistency_list = "/amount-arithmetic-inconsistencies",
- bad_sig_losses_list = "/bad-sig-losses",
+ bad_sig_losses_list = "/bad-sig-losses",
- balance_list = "/balance",
+ balance_list = "/balance",
- closure_lag_list = "/closure-lags",
+ closure_lag_list = "/closure-lags",
- coin_inconsistency_list = "/coin-inconsistencies",
+ coin_inconsistency_list = "/coin-inconsistencies",
- denomination_key_validity_withdraw_inconsistency_list = "/denomination-key-validity-withdraw-inconsistencies",
+ denomination_key_validity_withdraw_inconsistency_list = "/denomination-key-validity-withdraw-inconsistencies",
- denomination_pending_list = "/denominations-pending",
+ denomination_pending_list = "/denominations-pending",
- denomination_without_sig_list = "/denominations-without-sig",
+ denomination_without_sig_list = "/denominations-without-sig",
- deposit_confirmation_list = "/deposit-confirmations",
- deposit_confirmation_update = "/deposit-confirmation/:rowid/update",
+ deposit_confirmation_list = "/deposit-confirmations",
+ deposit_confirmation_update = "/deposit-confirmation/:rowid/update",
- emergency_list = "/emergencies",
+ emergency_list = "/emergencies",
- emergency_by_count_list = "/emergencies-by-count",
+ emergency_by_count_list = "/emergencies-by-count",
- exchange_signkey_list = "/exchange-sign-keys",
+ exchange_signkey_list = "/exchange-sign-keys",
- fee_time_inconsistency_list = "/fee-time-inconsistencies",
+ fee_time_inconsistency_list = "/fee-time-inconsistencies",
- historic_denomination_revenue_list = "/historic-denomination-revenues",
+ historic_denomination_revenue_list = "/historic-denomination-revenues",
- misattribution_in_inconsistency_list = "/misattribution-in-inconsistencies",
+ misattribution_in_inconsistency_list = "/misattribution-in-inconsistencies",
- progress_list = "/progress",
+ progress_list = "/progress",
- purse_not_closed_inconsistency_list = "/purse-not-closed-inconsistencies",
+ purse_not_closed_inconsistency_list = "/purse-not-closed-inconsistencies",
- purse_list = "/purses",
+ purse_list = "/purses",
- refresh_hanging_list = "/refreshes-hanging",
+ refresh_hanging_list = "/refreshes-hanging",
- reserve_balance_insufficient_inconsistency_list = "/reserve-balance-insufficient-inconsistencies",
+ reserve_balance_insufficient_inconsistency_list = "/reserve-balance-insufficient-inconsistencies",
- reserve_balance_summary_wrong_inconsistency_list = "/reserve-balance-summary-wrong-inconsistencies",
+ reserve_balance_summary_wrong_inconsistency_list = "/reserve-balance-summary-wrong-inconsistencies",
- reserve_in_inconsistency_list = "/reserve-in-inconsistencies",
+ reserve_in_inconsistency_list = "/reserve-in-inconsistencies",
- reserve_not_closed_inconsistency_list = "/reserve-not-closed-inconsistencies",
+ reserve_not_closed_inconsistency_list = "/reserve-not-closed-inconsistencies",
- reserves_list = "/reserves",
+ reserves_list = "/reserves",
- row_inconsistency_list = "/row-inconsistencies",
+ row_inconsistency_list = "/row-inconsistencies",
- row_minor_inconsistency_list = "/row-minor-inconsistencies",
+ row_minor_inconsistency_list = "/row-minor-inconsistencies",
- wire_format_inconsistency_list = "/wire-format-inconsistencies",
+ wire_format_inconsistency_list = "/wire-format-inconsistencies",
- wire_out_inconsistency_list = "/wire-out-inconsistencies"
+ wire_out_inconsistency_list = "/wire-out-inconsistencies",
}
interface TestProps {
- title: string;
- endpoint: string;
- entity: any;
+ title: string;
+ endpoint: string;
+ entity: any;
}
function getInstanceTitle(path: string): TestProps {
- switch (path) {
- case Paths.key_figures:
- return {title: `Key figures`, endpoint: "helper", entity: null};
- case Paths.critical_errors:
- return {title: `Critical errors`, endpoint: "helper", entity: null};
- case Paths.operating_status:
- return {title: `Operating status`, endpoint: "helper", entity: null};
- case Paths.detail_view:
- return {title: `Inconsistencies`, endpoint: "helper", entity: null};
- case Paths.amount_arithmethic_inconsistency_list:
- let amountArithmeticInconsistency: AuditorBackend.AmountArithmeticInconsistency.ClassAmountArithmeticInconsistency = {} as AuditorBackend.AmountArithmeticInconsistency.ClassAmountArithmeticInconsistency;
- return {
- title: `Amount arithmetic inconsistencies`,
- endpoint: "amount-arithmetic-inconsistency",
- entity: amountArithmeticInconsistency
- };
- case Paths.bad_sig_losses_list:
- return {title: `Bad Sig Losses`, endpoint: "bad-sig-losses", entity: null};
- case Paths.balance_list:
- return {title: "Balances", endpoint: "balances", entity: null};
- case Paths.closure_lag_list:
- return {title: `Closure Lags`, endpoint: "closure-lags", entity: null};
- case Paths.coin_inconsistency_list:
- return {title: `Coin inconsistencies`, endpoint: "coin-inconsistency", entity: null};
- case Paths.denomination_key_validity_withdraw_inconsistency_list:
- return {title: `Denomination key validity withdraw inconsistency`, endpoint: "denomination-key-validity-withdraw-inconsistency", entity: null};
- case Paths.denomination_pending_list:
- return {title: `Denominations pending`, endpoint: "denomination-pending", entity: null};
- case Paths.denomination_without_sig_list:
- return {title: `Denominations without sigs`, endpoint: "denominations-without-sigs", entity: null};
- case Paths.deposit_confirmation_list:
- return {title: "Deposit Confirmations", endpoint: "deposit-confirmation", entity: null};
- case Paths.emergency_list:
- return {title: "Emergencies", endpoint: "emergency", entity: null};
- case Paths.emergency_by_count_list:
- return {title: "Emergencies by count", endpoint: "emergency-by-count", entity: null};
- case Paths.fee_time_inconsistency_list:
- return {title: "Fee time inconsistencies", endpoint: "fee-time-inconsistency", entity: null};
- case Paths.historic_denomination_revenue_list:
- return {title: "Historic denomination revenue", endpoint: "historic-denomination-revenue", entity: null};
- case Paths.misattribution_in_inconsistency_list:
- return {title: "Misattribution in inconsistencies", endpoint: "misattribution-in-inconsistency", entity: null};
- case Paths.progress_list:
- return {title: "Progress", endpoint: "progress", entity: null};
- case Paths.purse_not_closed_inconsistency_list:
- return {title: "Purse not closed inconsistencies", endpoint: "purse-not-closed-inconsistencies", entity: null};
- case Paths.purse_list:
- return {title: "Purses", endpoint: "purses", entity: null};
- case Paths.refresh_hanging_list:
- return {title: "Refreshes hanging", endpoint: "refreshes-hanging", entity: null};
- case Paths.reserves_list:
- return {title: "Reserves", endpoint: "reserves ", entity: null};
- case Paths.reserve_balance_insufficient_inconsistency_list:
- return {title: "Reserve balance insufficient inconsistencies", endpoint: "reserve-balance-insufficient-inconsistency", entity: null};
- case Paths.reserve_balance_summary_wrong_inconsistency_list:
- return {title: "Reserve balance summary wrong inconsistencies", endpoint: "reserve-balance-summary-wrong-inconsistency", entity: null};
- case Paths.reserve_in_inconsistency_list:
- return {title: "Reserves in inconsistencies", endpoint: "reserve-in-inconsistency", entity: null};
- case Paths.reserve_not_closed_inconsistency_list:
- return {title: "Reserves not closed inconsistencies", endpoint: "reserve-not-closed-inconsistency", entity: null};
- case Paths.row_inconsistency_list:
- return {title: "Row inconsistencies", endpoint: "row-inconsistency", entity: null};
- case Paths.row_minor_inconsistency_list:
- return {title: "Row minor inconsistencies", endpoint: "row-minor-inconsistencies", entity: null};
- case Paths.wire_format_inconsistency_list:
- let wireFormatInconsistency: AuditorBackend.WireFormatInconsistency.ClassWireFormatInconsistency = {} as AuditorBackend.WireFormatInconsistency.ClassWireFormatInconsistency;
- return {title: "Wire format inconsistencies", endpoint: "wire-format-inconsistency", entity: wireFormatInconsistency};
- case Paths.wire_out_inconsistency_list:
- return {title: "Wire out inconsistencies", endpoint: "wire-out-inconsistency", entity: null};
- case Paths.settings:
- return {title: `Settings`, endpoint: "settings", entity: null};
- default:
- return {title: "", endpoint: "", entity: null};
- }
+ switch (path) {
+ case Paths.key_figures:
+ return { title: `Key figures`, endpoint: "helper", entity: null };
+ case Paths.critical_errors:
+ return { title: `Critical errors`, endpoint: "helper", entity: null };
+ case Paths.operating_status:
+ return { title: `Operating status`, endpoint: "helper", entity: null };
+ case Paths.detail_view:
+ return { title: `Inconsistencies`, endpoint: "helper", entity: null };
+ case Paths.amount_arithmethic_inconsistency_list:
+ let amountArithmeticInconsistency: AuditorBackend.AmountArithmeticInconsistency.ClassAmountArithmeticInconsistency =
+ {} as AuditorBackend.AmountArithmeticInconsistency.ClassAmountArithmeticInconsistency;
+ return {
+ title: `Amount arithmetic inconsistencies`,
+ endpoint: "amount-arithmetic-inconsistency",
+ entity: amountArithmeticInconsistency,
+ };
+ case Paths.bad_sig_losses_list:
+ return {
+ title: `Bad Sig Losses`,
+ endpoint: "bad-sig-losses",
+ entity: null,
+ };
+ case Paths.balance_list:
+ return { title: "Balances", endpoint: "balances", entity: null };
+ case Paths.closure_lag_list:
+ return { title: `Closure Lags`, endpoint: "closure-lags", entity: null };
+ case Paths.coin_inconsistency_list:
+ return {
+ title: `Coin inconsistencies`,
+ endpoint: "coin-inconsistency",
+ entity: null,
+ };
+ case Paths.denomination_key_validity_withdraw_inconsistency_list:
+ return {
+ title: `Denomination key validity withdraw inconsistency`,
+ endpoint: "denomination-key-validity-withdraw-inconsistency",
+ entity: null,
+ };
+ case Paths.denomination_pending_list:
+ return {
+ title: `Denominations pending`,
+ endpoint: "denomination-pending",
+ entity: null,
+ };
+ case Paths.denomination_without_sig_list:
+ return {
+ title: `Denominations without sigs`,
+ endpoint: "denominations-without-sigs",
+ entity: null,
+ };
+ case Paths.deposit_confirmation_list:
+ return {
+ title: "Deposit Confirmations",
+ endpoint: "deposit-confirmation",
+ entity: null,
+ };
+ case Paths.emergency_list:
+ return { title: "Emergencies", endpoint: "emergency", entity: null };
+ case Paths.emergency_by_count_list:
+ return {
+ title: "Emergencies by count",
+ endpoint: "emergency-by-count",
+ entity: null,
+ };
+ case Paths.fee_time_inconsistency_list:
+ return {
+ title: "Fee time inconsistencies",
+ endpoint: "fee-time-inconsistency",
+ entity: null,
+ };
+ case Paths.historic_denomination_revenue_list:
+ return {
+ title: "Historic denomination revenue",
+ endpoint: "historic-denomination-revenue",
+ entity: null,
+ };
+ case Paths.misattribution_in_inconsistency_list:
+ return {
+ title: "Misattribution in inconsistencies",
+ endpoint: "misattribution-in-inconsistency",
+ entity: null,
+ };
+ case Paths.progress_list:
+ return { title: "Progress", endpoint: "progress", entity: null };
+ case Paths.purse_not_closed_inconsistency_list:
+ return {
+ title: "Purse not closed inconsistencies",
+ endpoint: "purse-not-closed-inconsistencies",
+ entity: null,
+ };
+ case Paths.purse_list:
+ return { title: "Purses", endpoint: "purses", entity: null };
+ case Paths.refresh_hanging_list:
+ return {
+ title: "Refreshes hanging",
+ endpoint: "refreshes-hanging",
+ entity: null,
+ };
+ case Paths.reserves_list:
+ return { title: "Reserves", endpoint: "reserves ", entity: null };
+ case Paths.reserve_balance_insufficient_inconsistency_list:
+ return {
+ title: "Reserve balance insufficient inconsistencies",
+ endpoint: "reserve-balance-insufficient-inconsistency",
+ entity: null,
+ };
+ case Paths.reserve_balance_summary_wrong_inconsistency_list:
+ return {
+ title: "Reserve balance summary wrong inconsistencies",
+ endpoint: "reserve-balance-summary-wrong-inconsistency",
+ entity: null,
+ };
+ case Paths.reserve_in_inconsistency_list:
+ return {
+ title: "Reserves in inconsistencies",
+ endpoint: "reserve-in-inconsistency",
+ entity: null,
+ };
+ case Paths.reserve_not_closed_inconsistency_list:
+ return {
+ title: "Reserves not closed inconsistencies",
+ endpoint: "reserve-not-closed-inconsistency",
+ entity: null,
+ };
+ case Paths.row_inconsistency_list:
+ return {
+ title: "Row inconsistencies",
+ endpoint: "row-inconsistency",
+ entity: null,
+ };
+ case Paths.row_minor_inconsistency_list:
+ return {
+ title: "Row minor inconsistencies",
+ endpoint: "row-minor-inconsistencies",
+ entity: null,
+ };
+ case Paths.wire_format_inconsistency_list:
+ let wireFormatInconsistency: AuditorBackend.WireFormatInconsistency.ClassWireFormatInconsistency =
+ {} as AuditorBackend.WireFormatInconsistency.ClassWireFormatInconsistency;
+ return {
+ title: "Wire format inconsistencies",
+ endpoint: "wire-format-inconsistency",
+ entity: wireFormatInconsistency,
+ };
+ case Paths.wire_out_inconsistency_list:
+ return {
+ title: "Wire out inconsistencies",
+ endpoint: "wire-out-inconsistency",
+ entity: null,
+ };
+ case Paths.settings:
+ return { title: `Settings`, endpoint: "settings", entity: null };
+ default:
+ return { title: "", endpoint: "", entity: null };
+ }
}
export interface Props {
- path: string;
+ path: string;
}
-export function InstanceRoutes({
- // id,
- path,
- // setInstanceName
- }: Props): VNode {
- const {i18n} = useTranslationContext();
-
- type GlobalNotifState = (Notification & { to: string | undefined }) | undefined;
- const [globalNotification, setGlobalNotification] =
- useState<GlobalNotifState>(undefined);
+export function InstanceRoutes({ path }: Props): VNode {
+ type GlobalNotifState =
+ | (Notification & { to: string | undefined })
+ | undefined;
+ const [globalNotification, setGlobalNotification] =
+ useState<GlobalNotifState>(undefined);
- const [error] = useErrorBoundary();
- const {title, endpoint, entity} = getInstanceTitle(path.replace("app/#", ""));
+ const [error] = useErrorBoundary();
+ const { title, endpoint, entity } = getInstanceTitle(path);
- const value = useMemo(
- () => ({title, path, endpoint, entity}),
- [title, path, endpoint, entity],
- );
+ const value = useMemo(
+ () => ({ title, path, endpoint, entity }),
+ [title, path, endpoint, entity],
+ );
- //TODO add if needed
- /*function ServerErrorRedirectTo(to: Paths) {
+ //TODO add if needed
+ /*function ServerErrorRedirectTo(to: Paths) {
return function ServerErrorRedirectToImpl(
error: HttpError<AuditorBackend.ErrorDetail>,
) {
@@ -242,231 +315,272 @@ export function InstanceRoutes({
};
}*/
+ return (
+ <EntityContextProvider value={value}>
+ <Menu
+ // instance={id}
+ path={path}
+ title={"Settings"}
+ onShowSettings={() => {
+ route(Paths.settings);
+ }}
+ />
+ <NotificationCard notification={globalNotification} />
+ {error && (
+ <NotificationCard
+ notification={{
+ message: "Internal error, please report",
+ type: "ERROR",
+ description: (
+ <pre>
+ {
+ (error instanceof Error
+ ? error.stack
+ : String(error)) as TranslatedString
+ }
+ </pre>
+ ),
+ }}
+ />
+ )}
+ <Router
+ onChange={(e) => {
+ const movingOutFromNotification =
+ globalNotification && e.url !== globalNotification.to;
+ if (movingOutFromNotification) {
+ setGlobalNotification(undefined);
+ }
+ }}
+ >
+ <Route path="/" component={Redirect} to={Paths.key_figures} />
+
+ <Route
+ path={Paths.key_figures}
+ component={FinanceDashboard}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.critical_errors}
+ component={SecurityDashboard}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.operating_status}
+ component={OperationsDashboard}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.detail_view}
+ component={DetailsDashboard}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.amount_arithmethic_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.bad_sig_losses_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.balance_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.closure_lag_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.coin_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.denomination_key_validity_withdraw_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.denomination_pending_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.denomination_without_sig_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.deposit_confirmation_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.emergency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ <Route
+ path={Paths.emergency_by_count_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
+ />
+ {
+ <Route
+ path={Paths.exchange_signkey_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.fee_time_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.historic_denomination_revenue_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.misattribution_in_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.progress_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.purse_not_closed_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.purse_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.refresh_hanging_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.reserve_balance_insufficient_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.reserve_balance_summary_wrong_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.reserve_in_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.reserve_not_closed_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.reserves_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.row_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.row_minor_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.wire_out_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ {
+ <Route
+ path={Paths.wire_format_inconsistency_list}
+ component={DefaultList}
+ onNotFound={NotFoundPage}
+ />
+ }
+ <Route path={Paths.settings} component={Settings} />
- return (
- <EntityContextProvider value={value}>
- <Menu
- // instance={id}
- path={path}
- title={"Settings"}
- onShowSettings={() => {
- route(Paths.settings);
- }}/>
- <NotificationCard notification={globalNotification}/>
- {error &&
- <NotificationCard notification={{
- message: "Internal error, please report",
- type: "ERROR",
- description: <pre>
- {(error instanceof Error ? error.stack : String(error)) as TranslatedString}
- </pre>,
- }}/>
- }
- <Router
- onChange={(e) => {
- const movingOutFromNotification =
- globalNotification && e.url !== globalNotification.to;
- if (movingOutFromNotification) {
- setGlobalNotification(undefined);
- }
- }}
- >
- <Route path="/" component={Redirect} to={Paths.key_figures}/>
-
- <Route
- path={Paths.key_figures}
- component={FinanceDashboard}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.critical_errors}
- component={SecurityDashboard}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.operating_status}
- component={OperationsDashboard}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.detail_view}
- component={DetailsDashboard}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.amount_arithmethic_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.bad_sig_losses_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.balance_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.closure_lag_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.coin_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.denomination_key_validity_withdraw_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.denomination_pending_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.denomination_without_sig_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.deposit_confirmation_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.emergency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- <Route
- path={Paths.emergency_by_count_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- //onLoadError={ServerErrorRedirectTo(Paths.balance_list)}
- />
- {<Route
- path={Paths.exchange_signkey_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.fee_time_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.historic_denomination_revenue_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.misattribution_in_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.progress_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.purse_not_closed_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.purse_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.refresh_hanging_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.reserve_balance_insufficient_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.reserve_balance_summary_wrong_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.reserve_in_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.reserve_not_closed_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.reserves_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.row_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.row_minor_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.wire_out_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- {<Route
- path={Paths.wire_format_inconsistency_list}
- component={DefaultList}
- onNotFound={NotFoundPage}
- />}
- <Route
- path={Paths.settings}
- component={Settings}
- />
-
- {//TODO add if needed
- /**
- * Example pages
- */}
- {/* <Route path="/loading" component={Loading}/>
+ {
+ //TODO add if needed
+ /**
+ * Example pages
+ */
+ }
+ {/* <Route path="/loading" component={Loading}/>
<Route default component={NotFoundPage}/>*/}
- </Router>
- </EntityContextProvider>
- );
+ </Router>
+ </EntityContextProvider>
+ );
}
-export function Redirect({to}: { to: string }): null {
- useEffect(() => {
- route(to, true);
- });
- return null;
-} \ No newline at end of file
+export function Redirect({ to }: { to: string }): null {
+ useEffect(() => {
+ route(to, true);
+ });
+ return null;
+}
diff --git a/packages/auditor-backoffice-ui/src/components/exception/loading.tsx b/packages/auditor-backoffice-ui/src/components/exception/loading.tsx
index 11b62c124..5c249f79d 100644
--- a/packages/auditor-backoffice-ui/src/components/exception/loading.tsx
+++ b/packages/auditor-backoffice-ui/src/components/exception/loading.tsx
@@ -22,27 +22,27 @@
import { h, VNode } from "preact";
export function Loading(): VNode {
- return (
- <div
- class="columns is-centered is-vcentered"
- style={{
- height: "calc(100% - 3rem)",
- position: "absolute",
- width: "100%",
- }}
- >
- <Spinner />
- </div>
- );
+ return (
+ <div
+ class="columns is-centered is-vcentered"
+ style={{
+ height: "calc(100% - 3rem)",
+ position: "absolute",
+ width: "100%",
+ }}
+ >
+ <Spinner />
+ </div>
+ );
}
export function Spinner(): VNode {
- return (
- <div class="lds-ring">
- <div />
- <div />
- <div />
- <div />
- </div>
- );
+ return (
+ <div class="lds-ring">
+ <div />
+ <div />
+ <div />
+ <div />
+ </div>
+ );
}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/FormProvider.tsx b/packages/auditor-backoffice-ui/src/components/forms/FormProvider.tsx
index a5f3c1d2f..4abe465c7 100644
--- a/packages/auditor-backoffice-ui/src/components/forms/FormProvider.tsx
+++ b/packages/auditor-backoffice-ui/src/components/forms/FormProvider.tsx
@@ -20,7 +20,7 @@
*/
import { ComponentChildren, createContext, h, VNode } from "preact";
-import { useContext, useMemo } from "preact/hooks";
+import { useMemo } from "preact/hooks";
type Updater<S> = (value: (prevState: S) => S) => void;
@@ -82,16 +82,6 @@ export interface FormType<T> {
const FormContext = createContext<FormType<unknown>>(null!);
-/**
- * FIXME:
- * USE MEMORY EVENTS INSTEAD OF CONTEXT
- * @deprecated
- */
-
-export function useFormContext<T>() {
- return useContext<FormType<T>>(FormContext);
-}
-
export type FormErrors<T> = {
[P in keyof T]?: string | FormErrors<T[P]>;
};
@@ -103,7 +93,3 @@ export type FormtoStr<T> = {
export type FormfromStr<T> = {
[P in keyof T]?: (f: string) => T[P];
};
-
-export type FormUpdater<T> = {
- [P in keyof T]?: (f: keyof T) => (v: T[P]) => void;
-};
diff --git a/packages/auditor-backoffice-ui/src/components/forms/Input.tsx b/packages/auditor-backoffice-ui/src/components/forms/Input.tsx
deleted file mode 100644
index 899061c35..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/Input.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { ComponentChildren, h, VNode } from "preact";
-import { useField, InputProps } from "./useField.js";
-
-interface Props<T> extends InputProps<T> {
- inputType?: "text" | "number" | "multiline" | "password";
- expand?: boolean;
- toStr?: (v?: any) => string;
- fromStr?: (s: string) => any;
- inputExtra?: any;
- side?: ComponentChildren;
- children?: ComponentChildren;
-}
-
-const defaultToString = (f?: any): string => f || "";
-const defaultFromString = (v: string): any => v as any;
-
-const TextInput = ({ inputType, error, ...rest }: any) =>
- inputType === "multiline" ? (
- <textarea
- {...rest}
- class={error ? "textarea is-danger" : "textarea"}
- rows="3"
- />
- ) : (
- <input
- {...rest}
- class={error ? "input is-danger" : "input"}
- type={inputType}
- />
- );
-
-export function Input<T>({
- name,
- readonly,
- placeholder,
- tooltip,
- label,
- expand,
- help,
- children,
- inputType,
- inputExtra,
- side,
- fromStr = defaultFromString,
- toStr = defaultToString,
-}: Props<keyof T>): VNode {
- const { error, value, onChange, required } = useField<T>(name);
- return (
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label">
- {label}
- {tooltip && (
- <span class="icon has-tooltip-right" data-tooltip={tooltip}>
- <i class="mdi mdi-information" />
- </span>
- )}
- </label>
- </div>
- <div class="field-body is-flex-grow-3">
- <div class="field">
- <p
- class={
- expand
- ? "control is-expanded has-icons-right"
- : "control has-icons-right"
- }
- >
- <TextInput
- error={error}
- {...inputExtra}
- inputType={inputType}
- placeholder={placeholder}
- readonly={readonly}
- disabled={readonly}
- name={String(name)}
- value={toStr(value)}
- onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void =>
- onChange(fromStr(e.currentTarget.value))
- }
- />
- {help}
- {children}
- {required && (
- <span class="icon has-text-danger is-right">
- <i class="mdi mdi-alert" />
- </span>
- )}
- </p>
- {error && <p class="help is-danger">{error}</p>}
- </div>
- {side}
- </div>
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/InputCurrency.tsx b/packages/auditor-backoffice-ui/src/components/forms/InputCurrency.tsx
deleted file mode 100644
index c1359e641..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/InputCurrency.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { ComponentChildren, h, VNode } from "preact";
-import { useConfigContext } from "../../context/config.js";
-import { Amount } from "../../declaration.js";
-import { InputWithAddon } from "./InputWithAddon.js";
-import { InputProps } from "./useField.js";
-
-export interface Props<T> extends InputProps<T> {
- expand?: boolean;
- addonAfter?: ComponentChildren;
- children?: ComponentChildren;
- side?: ComponentChildren;
-}
-
-export function InputCurrency<T>({
- name,
- readonly,
- label,
- placeholder,
- help,
- tooltip,
- expand,
- addonAfter,
- children,
- side,
-}: Props<keyof T>): VNode {
- const config = useConfigContext();
- return (
- <InputWithAddon<T>
- name={name}
- readonly={readonly}
- addonBefore={config.currency}
- side={side}
- label={label}
- placeholder={placeholder}
- help={help}
- tooltip={tooltip}
- addonAfter={addonAfter}
- inputType="number"
- expand={expand}
- toStr={(v?: Amount) => v?.split(":")[1] || ""}
- fromStr={(v: string) => (!v ? undefined : `${config.currency}:${v}`)}
- inputExtra={{ min: 0 }}
- >
- {children}
- </InputWithAddon>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/InputNumber.tsx b/packages/auditor-backoffice-ui/src/components/forms/InputNumber.tsx
deleted file mode 100644
index 10b28cd93..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/InputNumber.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { ComponentChildren, h } from "preact";
-import { InputWithAddon } from "./InputWithAddon.js";
-import { InputProps } from "./useField.js";
-
-export interface Props<T> extends InputProps<T> {
- readonly?: boolean;
- expand?: boolean;
- side?: ComponentChildren;
- children?: ComponentChildren;
-}
-
-export function InputNumber<T>({
- name,
- readonly,
- placeholder,
- tooltip,
- label,
- help,
- expand,
- children,
- side,
-}: Props<keyof T>) {
- return (
- <InputWithAddon<T>
- name={name}
- readonly={readonly}
- fromStr={(v) => (!v ? undefined : parseInt(v, 10))}
- toStr={(v) => `${v}`}
- inputType="number"
- expand={expand}
- label={label}
- placeholder={placeholder}
- help={help}
- tooltip={tooltip}
- inputExtra={{ min: 0 }}
- children={children}
- side={side}
- />
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/InputSelector.tsx b/packages/auditor-backoffice-ui/src/components/forms/InputSelector.tsx
deleted file mode 100644
index f567f7247..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/InputSelector.tsx
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { h, VNode } from "preact";
-import { InputProps, useField } from "./useField.js";
-
-interface Props<T> extends InputProps<T> {
- readonly?: boolean;
- expand?: boolean;
- values: any[];
- toStr?: (v?: any) => string;
- fromStr?: (s: string) => any;
-}
-
-const defaultToString = (f?: any): string => f || "";
-const defaultFromString = (v: string): any => v as any;
-
-export function InputSelector<T>({
- name,
- readonly,
- expand,
- placeholder,
- tooltip,
- label,
- help,
- values,
- fromStr = defaultFromString,
- toStr = defaultToString,
-}: Props<keyof T>): VNode {
- const { error, value, onChange, required } = useField<T>(name);
- return (
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label">
- {label}
- {tooltip && (
- <span class="icon has-tooltip-right" data-tooltip={tooltip}>
- <i class="mdi mdi-information" />
- </span>
- )}
- </label>
- </div>
- <div class="field-body is-flex-grow-3">
- <div class="field has-icons-right">
- <p class={expand ? "control is-expanded select" : "control select "}>
- <select
- class={error ? "select is-danger" : "select"}
- name={String(name)}
- disabled={readonly}
- readonly={readonly}
- onChange={(e) => {
- onChange(fromStr(e.currentTarget.value));
- }}
- >
- {placeholder && <option>{placeholder}</option>}
- {values.map((v, i) => {
- return (
- <option key={i} value={v} selected={value === v}>
- {toStr(v)}
- </option>
- );
- })}
- </select>
-
- {help}
- </p>
- {required && (
- <span class="icon has-text-danger is-right" style={{height: "2.5em"}}>
- <i class="mdi mdi-alert" />
- </span>
- )}
- {error && <p class="help is-danger">{error}</p>}
- </div>
- </div>
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/InputToggle.tsx b/packages/auditor-backoffice-ui/src/components/forms/InputToggle.tsx
deleted file mode 100644
index 89b815b4b..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/InputToggle.tsx
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { h, VNode } from "preact";
-import { InputProps, useField } from "./useField.js";
-
-interface Props<T> extends InputProps<T> {
- name: T;
- readonly?: boolean;
- expand?: boolean;
- threeState?: boolean;
- toBoolean?: (v?: any) => boolean | undefined;
- fromBoolean?: (s: boolean | undefined) => any;
-}
-
-const defaultToBoolean = (f?: any): boolean | undefined => f || "";
-const defaultFromBoolean = (v: boolean | undefined): any => v as any;
-
-export function InputToggle<T>({
- name,
- readonly,
- placeholder,
- tooltip,
- label,
- help,
- threeState,
- expand,
- fromBoolean = defaultFromBoolean,
- toBoolean = defaultToBoolean,
-}: Props<keyof T>): VNode {
- const { error, value, onChange } = useField<T>(name);
-
- const onCheckboxClick = (): void => {
- const c = toBoolean(value);
- if (c === false && threeState) return onChange(undefined as any);
- return onChange(fromBoolean(!c));
- };
-
- return (
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label" >
- {label}
- {tooltip && (
- <span class="icon has-tooltip-right" data-tooltip={tooltip}>
- <i class="mdi mdi-information" />
- </span>
- )}
- </label>
- </div>
- <div class="field-body is-flex-grow-3">
- <div class="field">
- <p class={expand ? "control is-expanded" : "control"}>
- <label class="toggle" style={{ marginLeft: 4, marginTop: 0 }}>
- <input
- type="checkbox"
- class={toBoolean(value) === undefined ? "is-indeterminate" : "toggle-checkbox"}
- checked={toBoolean(value)}
- placeholder={placeholder}
- readonly={readonly}
- name={String(name)}
- disabled={readonly}
- onChange={onCheckboxClick}
- />
- <div class="toggle-switch"></div>
- </label>
- {help}
- </p>
- {error && <p class="help is-danger">{error}</p>}
- </div>
- </div>
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/InputWithAddon.tsx b/packages/auditor-backoffice-ui/src/components/forms/InputWithAddon.tsx
deleted file mode 100644
index b8cd4c2d2..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/InputWithAddon.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { ComponentChildren, h, VNode } from "preact";
-import { InputProps, useField } from "./useField.js";
-
-export interface Props<T> extends InputProps<T> {
- expand?: boolean;
- inputType?: "text" | "number" | "password";
- addonBefore?: ComponentChildren;
- addonAfter?: ComponentChildren;
- addonAfterAction?: () => void;
- toStr?: (v?: any) => string;
- fromStr?: (s: string) => any;
- inputExtra?: any;
- children?: ComponentChildren;
- side?: ComponentChildren;
-}
-
-const defaultToString = (f?: any): string => f || "";
-const defaultFromString = (v: string): any => v as any;
-
-export function InputWithAddon<T>({
- name,
- readonly,
- addonBefore,
- children,
- expand,
- label,
- placeholder,
- help,
- tooltip,
- inputType,
- inputExtra,
- side,
- addonAfter,
- addonAfterAction,
- toStr = defaultToString,
- fromStr = defaultFromString,
-}: Props<keyof T>): VNode {
- const { error, value, onChange, required } = useField<T>(name);
-
- return (
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label">
- {label}
- {tooltip && (
- <span class="icon has-tooltip-right" data-tooltip={tooltip}>
- <i class="mdi mdi-information" />
- </span>
- )}
- </label>
- </div>
- <div class="field-body is-flex-grow-3">
- <div class="field">
- <div class="field has-addons">
- {addonBefore && (
- <div class="control">
- <a class="button is-static">{addonBefore}</a>
- </div>
- )}
- <p
- class={`control${expand ? " is-expanded" : ""}${required ? " has-icons-right" : ""
- }`}
- >
- <input
- {...(inputExtra || {})}
- class={error ? "input is-danger" : "input"}
- type={inputType}
- placeholder={placeholder}
- readonly={readonly}
- disabled={readonly}
- name={String(name)}
- value={toStr(value)}
- onChange={(e): void => onChange(fromStr(e.currentTarget.value))}
- />
- {required && (
- <span class="icon has-text-danger is-right">
- <i class="mdi mdi-alert" />
- </span>
- )}
- {children}
- </p>
- {addonAfter && (
- <div class="control" onClick={addonAfterAction} style={{ cursor: addonAfterAction ? "pointer" : undefined }}>
- <a class="button is-static">{addonAfter}</a>
- </div>
- )}
- </div>
- {error && <p class="help is-danger">{error}</p>}
- <span class="has-text-grey">{help}</span>
- </div>
- {expand ? <div>{side}</div> : side}
- </div>
-
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/components/forms/useField.tsx b/packages/auditor-backoffice-ui/src/components/forms/useField.tsx
deleted file mode 100644
index 49bba4984..000000000
--- a/packages/auditor-backoffice-ui/src/components/forms/useField.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { ComponentChildren, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { useFormContext } from "./FormProvider.js";
-
-interface Use<V> {
- error?: string;
- required: boolean;
- value: any;
- initial: any;
- onChange: (v: V) => void;
- toStr: (f: V | undefined) => string;
- fromStr: (v: string) => V;
-}
-
-export function useField<T>(name: keyof T): Use<T[typeof name]> {
- const { errors, object, initialObject, toStr, fromStr, valueHandler } =
- useFormContext<T>();
- type P = typeof name;
- type V = T[P];
- const [isDirty, setDirty] = useState(false);
- const updateField =
- (field: P) =>
- (value: V): void => {
- setDirty(true);
- return valueHandler((prev) => {
- return setValueDeeper(prev, String(field).split("."), value);
- });
- };
-
- const defaultToString = (f?: V): string => String(!f ? "" : f);
- const defaultFromString = (v: string): V => v as any;
- const value = readField(object, String(name));
- const initial = readField(initialObject, String(name));
- const hasError = readField(errors, String(name));
- return {
- error: isDirty ? hasError : undefined,
- required: !isDirty && hasError,
- value,
- initial,
- onChange: updateField(name) as any,
- toStr: toStr[name] ? toStr[name]! : defaultToString,
- fromStr: fromStr[name] ? fromStr[name]! : defaultFromString,
- };
-}
-/**
- * read the field of an object an support accessing it using '.'
- *
- * @param object
- * @param name
- * @returns
- */
-const readField = (object: any, name: string) => {
- return name
- .split(".")
- .reduce((prev, current) => prev && prev[current], object);
-};
-
-const setValueDeeper = (object: any, names: string[], value: any): any => {
- if (names.length === 0) return value;
- const [head, ...rest] = names;
- return { ...object, [head]: setValueDeeper(object[head] || {}, rest, value) };
-};
-
-export interface InputProps<T> {
- name: T;
- label: ComponentChildren;
- placeholder?: string;
- tooltip?: ComponentChildren;
- readonly?: boolean;
- help?: ComponentChildren;
-}
diff --git a/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx b/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx
index d81410bdf..66469378b 100644
--- a/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx
+++ b/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx
@@ -55,7 +55,7 @@ export function NavigationBar({ onMobileMenu, title }: Props): VNode {
</a>
</div>
- <div class="navbar-menu ">
+ <div class="navbar-menu">
<a
class="navbar-start is-justify-content-center is-flex-grow-1"
href="https://taler.net"
@@ -63,8 +63,10 @@ export function NavigationBar({ onMobileMenu, title }: Props): VNode {
<img src={logo} style={{ height: 35, margin: 10 }} />
</a>
<div class="navbar-end">
- <div class="navbar-item" style={{ paddingTop: 4, paddingBottom: 4 }}>
- </div>
+ <div
+ class="navbar-item"
+ style={{ paddingTop: 4, paddingBottom: 4 }}
+ ></div>
</div>
</div>
</nav>
diff --git a/packages/auditor-backoffice-ui/src/components/menu/index.tsx b/packages/auditor-backoffice-ui/src/components/menu/index.tsx
index e411939c7..214b6bd3b 100644
--- a/packages/auditor-backoffice-ui/src/components/menu/index.tsx
+++ b/packages/auditor-backoffice-ui/src/components/menu/index.tsx
@@ -22,221 +22,219 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
* @author Nic Eigel
*/
-import {ComponentChildren, Fragment, h, VNode} from "preact";
-import {useEffect, useState} from "preact/hooks";
-import {Paths} from "../../InstanceRoutes.js";
-import {Notification} from "../../utils/types.js";
-import {NavigationBar} from "./NavigationBar.js";
-import {Sidebar} from "./SideBar.js";
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { Paths } from "../../InstanceRoutes.js";
+import { Notification } from "../../utils/types.js";
+import { NavigationBar } from "./NavigationBar.js";
+import { Sidebar } from "./SideBar.js";
function getInstanceTitle(path: string): string {
- switch (path) {
- case Paths.key_figures:
- return 'Key figures';
- case Paths.critical_errors:
- return 'Critical errors';
- case Paths.operating_status:
- return 'Operating status';
- case Paths.detail_view:
- return 'Inconsistencies';
- case Paths.amount_arithmethic_inconsistency_list:
- return `Amount arithmetic inconsistencies`;
- case Paths.bad_sig_losses_list:
- return `Bad sig losses`;
- case Paths.balance_list:
- return `Balances`;
- case Paths.closure_lag_list:
- return `Closure Lags`;
- case Paths.coin_inconsistency_list:
- return `Coin inconsistencies`;
- case Paths.denomination_key_validity_withdraw_inconsistency_list:
- return `Denomination key validity withdraw inconsistency`;
- case Paths.denomination_pending_list:
- return `Denominations pending`;
- case Paths.denomination_without_sig_list:
- return `Denominations without sigs`;
- case Paths.deposit_confirmation_list:
- return `Deposit confirmations`;
- case Paths.deposit_confirmation_update:
- return `Update deposit confirmation`;
- case Paths.emergency_list:
- return `Emergencies`;
- case Paths.emergency_by_count_list:
- return `Emergencies by count`;
- case Paths.exchange_signkey_list:
- return `Exchange signkeys`;
- case Paths.fee_time_inconsistency_list:
- return `Fee time inconsistencies`;
- case Paths.historic_denomination_revenue_list:
- return `Historic denomination revenue`;
- case Paths.misattribution_in_inconsistency_list:
- return `Misattribution in inconsistencies`;
- case Paths.progress_list:
- return `Progress`;
- case Paths.purse_not_closed_inconsistency_list:
- return `Purse not closed inconsistencies`;
- case Paths.purse_list:
- return `Purses`;
- case Paths.refresh_hanging_list:
- return `Refreshes hanging`;
- case Paths.reserve_balance_insufficient_inconsistency_list:
- return `Reserve balance insufficient inconsistencies`;
- case Paths.reserve_balance_summary_wrong_inconsistency_list:
- return `Reserve balance summary wrong inconsistencies`;
- case Paths.reserve_in_inconsistency_list:
- return `Reserves in inconsistencies`;
- case Paths.reserve_not_closed_inconsistency_list:
- return `Reserves not closed inconsistencies`;
- case Paths.row_inconsistency_list:
- return `Row inconsistencies`;
- case Paths.row_minor_inconsistency_list:
- return `Row minor inconsistencies`;
- case Paths.wire_format_inconsistency_list:
- return `Wire format inconsistencies`;
- case Paths.wire_out_inconsistency_list:
- return `Wire out inconsistencies`;
- case Paths.settings:
- return `Settings`;
- default:
- return "";
- }
+ switch (path) {
+ case Paths.key_figures:
+ return "Key figures";
+ case Paths.critical_errors:
+ return "Critical errors";
+ case Paths.operating_status:
+ return "Operating status";
+ case Paths.detail_view:
+ return "Inconsistencies";
+ case Paths.amount_arithmethic_inconsistency_list:
+ return `Amount arithmetic inconsistencies`;
+ case Paths.bad_sig_losses_list:
+ return `Bad sig losses`;
+ case Paths.balance_list:
+ return `Balances`;
+ case Paths.closure_lag_list:
+ return `Closure Lags`;
+ case Paths.coin_inconsistency_list:
+ return `Coin inconsistencies`;
+ case Paths.denomination_key_validity_withdraw_inconsistency_list:
+ return `Denomination key validity withdraw inconsistency`;
+ case Paths.denomination_pending_list:
+ return `Denominations pending`;
+ case Paths.denomination_without_sig_list:
+ return `Denominations without sigs`;
+ case Paths.deposit_confirmation_list:
+ return `Deposit confirmations`;
+ case Paths.deposit_confirmation_update:
+ return `Update deposit confirmation`;
+ case Paths.emergency_list:
+ return `Emergencies`;
+ case Paths.emergency_by_count_list:
+ return `Emergencies by count`;
+ case Paths.exchange_signkey_list:
+ return `Exchange signkeys`;
+ case Paths.fee_time_inconsistency_list:
+ return `Fee time inconsistencies`;
+ case Paths.historic_denomination_revenue_list:
+ return `Historic denomination revenue`;
+ case Paths.misattribution_in_inconsistency_list:
+ return `Misattribution in inconsistencies`;
+ case Paths.progress_list:
+ return `Progress`;
+ case Paths.purse_not_closed_inconsistency_list:
+ return `Purse not closed inconsistencies`;
+ case Paths.purse_list:
+ return `Purses`;
+ case Paths.refresh_hanging_list:
+ return `Refreshes hanging`;
+ case Paths.reserve_balance_insufficient_inconsistency_list:
+ return `Reserve balance insufficient inconsistencies`;
+ case Paths.reserve_balance_summary_wrong_inconsistency_list:
+ return `Reserve balance summary wrong inconsistencies`;
+ case Paths.reserve_in_inconsistency_list:
+ return `Reserves in inconsistencies`;
+ case Paths.reserve_not_closed_inconsistency_list:
+ return `Reserves not closed inconsistencies`;
+ case Paths.row_inconsistency_list:
+ return `Row inconsistencies`;
+ case Paths.row_minor_inconsistency_list:
+ return `Row minor inconsistencies`;
+ case Paths.wire_format_inconsistency_list:
+ return `Wire format inconsistencies`;
+ case Paths.wire_out_inconsistency_list:
+ return `Wire out inconsistencies`;
+ case Paths.settings:
+ return `Settings`;
+ default:
+ return "";
+ }
}
interface MenuProps {
- title?: string;
- path: string;
- onShowSettings: () => void;
+ title?: string;
+ path: string;
+ onShowSettings: () => void;
}
function WithTitle({
- title,
- children,
- }: {
- title: string;
- children: ComponentChildren;
+ title,
+ children,
+}: {
+ title: string;
+ children: ComponentChildren;
}): VNode {
- useEffect(() => {
- document.title = `Taler Backoffice: ${title}`;
- }, [title]);
- return <Fragment>{children}</Fragment>;
+ useEffect(() => {
+ document.title = `Taler Backoffice: ${title}`;
+ }, [title]);
+ return <Fragment>{children}</Fragment>;
}
-export function Menu({
- onShowSettings,
- title,
- path,
- }: MenuProps): VNode {
- const [mobileOpen, setMobileOpen] = useState(false);
- const titleWithSubtitle = getInstanceTitle(path.replace("app/#", ""));
- return (
- <WithTitle title={titleWithSubtitle}>
- <div
- class={mobileOpen ? "has-aside-mobile-expanded" : ""}
- onClick={() => setMobileOpen(false)}
- >
- <NavigationBar
- onMobileMenu={() => setMobileOpen(!mobileOpen)}
- title={titleWithSubtitle}
- />
-
- <Sidebar
- onShowSettings={onShowSettings}
- mobile={mobileOpen}
- />
- </div>
- </WithTitle>
- );
+export function Menu({ onShowSettings, title, path }: MenuProps): VNode {
+ const [mobileOpen, setMobileOpen] = useState(false);
+ const titleWithSubtitle = getInstanceTitle(path.replace("app/#", ""));
+ return (
+ <WithTitle title={titleWithSubtitle}>
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={titleWithSubtitle}
+ />
+
+ <Sidebar onShowSettings={onShowSettings} mobile={mobileOpen} />
+ </div>
+ </WithTitle>
+ );
}
interface NotYetReadyAppMenuProps {
- title: string;
- onShowSettings: () => void;
+ title: string;
+ onShowSettings: () => void;
}
interface NotifProps {
- notification?: Notification;
+ notification?: Notification;
}
-export function NotificationCard({notification: n}: NotifProps): VNode | null {
- if (!n) return null;
- return (
- <div class="notification">
- <div class="columns is-vcentered">
- <div class="column is-12">
- <article
- class={
- n.type === "ERROR"
- ? "message is-danger"
- : n.type === "WARN"
- ? "message is-warning"
- : "message is-info"
- }
- >
- <div class="message-header">
- <p>{n.message}</p>
- </div>
- {n.description && (
- <div class="message-body">
- <div>{n.description}</div>
- {n.details && <pre>{n.details}</pre>}
- </div>
- )}
- </article>
- </div>
+export function NotificationCard({
+ notification: n,
+}: NotifProps): VNode | null {
+ if (!n) return null;
+ return (
+ <div class="notification">
+ <div class="columns is-vcentered">
+ <div class="column is-12">
+ <article
+ class={
+ n.type === "ERROR"
+ ? "message is-danger"
+ : n.type === "WARN"
+ ? "message is-warning"
+ : "message is-info"
+ }
+ >
+ <div class="message-header">
+ <p>{n.message}</p>
</div>
+ {n.description && (
+ <div class="message-body">
+ <div>{n.description}</div>
+ {n.details && <pre>{n.details}</pre>}
+ </div>
+ )}
+ </article>
</div>
- );
+ </div>
+ </div>
+ );
}
interface NotConnectedAppMenuProps {
- title: string;
+ title: string;
}
export function NotConnectedAppMenu({
- title,
- }: NotConnectedAppMenuProps): VNode {
- const [mobileOpen, setMobileOpen] = useState(false);
-
- useEffect(() => {
- document.title = `Taler Backoffice: ${title}`;
- }, [title]);
-
- return (
- <div
- class={mobileOpen ? "has-aside-mobile-expanded" : ""}
- onClick={() => setMobileOpen(false)}
- >
- <NavigationBar
- onMobileMenu={() => setMobileOpen(!mobileOpen)}
- title={title}
- />
- </div>
- );
+ title,
+}: NotConnectedAppMenuProps): VNode {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ useEffect(() => {
+ document.title = `Taler Backoffice: ${title}`;
+ }, [title]);
+
+ return (
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={title}
+ />
+ </div>
+ );
}
-
export function NotYetReadyAppMenu({
- onShowSettings,
- title
- }: NotYetReadyAppMenuProps): VNode {
- const [mobileOpen, setMobileOpen] = useState(false);
-
- useEffect(() => {
- document.title = `Taler Backoffice: ${title}`;
- }, [title]);
-
- return (
- <div
- class={mobileOpen ? "has-aside-mobile-expanded" : ""}
- onClick={() => setMobileOpen(false)}
- >
- <NavigationBar
- onMobileMenu={() => setMobileOpen(!mobileOpen)}
- title={title}
- />
- (
- <Sidebar onShowSettings={onShowSettings} instance="" mobile={mobileOpen}/>
- )
- </div>
- );
-} \ No newline at end of file
+ onShowSettings,
+ title,
+}: NotYetReadyAppMenuProps): VNode {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ useEffect(() => {
+ document.title = `Taler Backoffice: ${title}`;
+ }, [title]);
+
+ return (
+ <div
+ class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+ onClick={() => setMobileOpen(false)}
+ >
+ <NavigationBar
+ onMobileMenu={() => setMobileOpen(!mobileOpen)}
+ title={title}
+ />
+ (
+ <Sidebar
+ onShowSettings={onShowSettings}
+ instance=""
+ mobile={mobileOpen}
+ />
+ )
+ </div>
+ );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/modal/index.tsx b/packages/auditor-backoffice-ui/src/components/modal/index.tsx
index ab2834d86..b8e3a43a3 100644
--- a/packages/auditor-backoffice-ui/src/components/modal/index.tsx
+++ b/packages/auditor-backoffice-ui/src/components/modal/index.tsx
@@ -19,14 +19,11 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+/**
+ * Imports.
+ */
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { useEntityContext } from "../../context/entity.js";
-import { DEFAULT_REQUEST_TIMEOUT } from "../../utils/constants.js";
-import { Spinner } from "../exception/loading.js";
-import { FormProvider } from "../forms/FormProvider.js";
-import { Input } from "../forms/Input.js";
interface Props {
active?: boolean;
@@ -95,402 +92,3 @@ export function ConfirmModal({
</div>
);
}
-
-export function ContinueModal({
- active,
- description,
- onCancel,
- onConfirm,
- children,
- disabled,
-}: Props): VNode {
- const { i18n } = useTranslationContext();
- return (
- <div class={active ? "modal is-active" : "modal"}>
- <div class="modal-background " onClick={onCancel} />
- <div class="modal-card">
- <header class="modal-card-head has-background-success">
- {!description ? null : <p class="modal-card-title">{description}</p>}
- <button class="delete " aria-label="close" onClick={onCancel} />
- </header>
- <section class="modal-card-body">{children}</section>
- <footer class="modal-card-foot">
- <div class="buttons is-right" style={{ width: "100%" }}>
- <button
- class="button is-success "
- disabled={disabled}
- onClick={onConfirm}
- >
- <i18n.Translate>Continue</i18n.Translate>
- </button>
- </div>
- </footer>
- </div>
- <button
- class="modal-close is-large "
- aria-label="close"
- onClick={onCancel}
- />
- </div>
- );
-}
-
-export function SimpleModal({ onCancel, children }: any): VNode {
- return (
- <div class="modal is-active">
- <div class="modal-background " onClick={onCancel} />
- <div class="modal-card">
- <section class="modal-card-body is-main-section">{children}</section>
- </div>
- <button
- class="modal-close is-large "
- aria-label="close"
- onClick={onCancel}
- />
- </div>
- );
-}
-
-export function ClearConfirmModal({
- description,
- onCancel,
- onClear,
- onConfirm,
- children,
-}: Props & { onClear?: () => void }): VNode {
- const { i18n } = useTranslationContext();
- return (
- <div class="modal is-active">
- <div class="modal-background " onClick={onCancel} />
- <div class="modal-card">
- <header class="modal-card-head">
- {!description ? null : <p class="modal-card-title">{description}</p>}
- <button class="delete " aria-label="close" onClick={onCancel} />
- </header>
- <section class="modal-card-body is-main-section">{children}</section>
- <footer class="modal-card-foot">
- {onClear && (
- <button
- class="button is-danger"
- onClick={onClear}
- disabled={onClear === undefined}
- >
- <i18n.Translate>Clear</i18n.Translate>
- </button>
- )}
- <div class="buttons is-right" style={{ width: "100%" }}>
- <button class="button " onClick={onCancel}>
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- <button
- class="button is-info"
- onClick={onConfirm}
- disabled={onConfirm === undefined}
- >
- <i18n.Translate>Confirm</i18n.Translate>
- </button>
- </div>
- </footer>
- </div>
- <button
- class="modal-close is-large "
- aria-label="close"
- onClick={onCancel}
- />
- </div>
- );
-}
-
-interface DeleteModalProps {
- element: { id: string; name: string };
- onCancel: () => void;
- onConfirm: (id: string) => void;
-}
-
-export function DeleteModal({
- element,
- onCancel,
- onConfirm,
-}: DeleteModalProps): VNode {
- return (
- <ConfirmModal
- label={`Delete instance`}
- description={`Delete the instance "${element.name}"`}
- danger
- active
- onCancel={onCancel}
- onConfirm={() => onConfirm(element.id)}
- >
- <p>
- If you delete the instance named <b>&quot;{element.name}&quot;</b> (ID:{" "}
- <b>{element.id}</b>), the merchant will no longer be able to process
- orders or refunds
- </p>
- <p>
- This action deletes the instance private key, but preserves all
- transaction data. You can still access that data after deleting the
- instance.
- </p>
- <p class="warning">
- Deleting an instance <b>cannot be undone</b>.
- </p>
- </ConfirmModal>
- );
-}
-
-export function PurgeModal({
- element,
- onCancel,
- onConfirm,
-}: DeleteModalProps): VNode {
- return (
- <ConfirmModal
- label={`Purge the instance`}
- description={`Purge the instance "${element.name}"`}
- danger
- active
- onCancel={onCancel}
- onConfirm={() => onConfirm(element.id)}
- >
- <p>
- If you purge the instance named <b>&quot;{element.name}&quot;</b> (ID:{" "}
- <b>{element.id}</b>), you will also delete all it&apos;s transaction
- data.
- </p>
- <p>
- The instance will disappear from your list, and you will no longer be
- able to access it&apos;s data.
- </p>
- <p class="warning">
- Purging an instance <b>cannot be undone</b>.
- </p>
- </ConfirmModal>
- );
-}
-
-interface UpdateTokenModalProps {
- oldToken?: string;
- onCancel: () => void;
- onConfirm: (value: string) => void;
- onClear: () => void;
-}
-
-//FIXME: merge UpdateTokenModal with SetTokenNewInstanceModal
-export function UpdateTokenModal({
- onCancel,
- onClear,
- onConfirm,
- oldToken,
-}: UpdateTokenModalProps): VNode {
- type State = { old_token: string; new_token: string; repeat_token: string };
- const [form, setValue] = useState<Partial<State>>({
- old_token: "",
- new_token: "",
- repeat_token: "",
- });
- const { i18n } = useTranslationContext();
-
- const hasInputTheCorrectOldToken = oldToken && oldToken !== form.old_token;
- const errors = {
- old_token: hasInputTheCorrectOldToken
- ? i18n.str`is not the same as the current access token`
- : undefined,
- new_token: !form.new_token
- ? i18n.str`cannot be empty`
- : form.new_token === form.old_token
- ? i18n.str`cannot be the same as the old token`
- : undefined,
- repeat_token:
- form.new_token !== form.repeat_token
- ? i18n.str`is not the same`
- : undefined,
- };
-
- const hasErrors = Object.keys(errors).some(
- (k) => (errors as any)[k] !== undefined,
- );
-
- const instance = useEntityContext();
-
- const text = i18n.str`You are updating the access token from instance with id `;
-
- return (
- <ClearConfirmModal
- description={text}
- onCancel={onCancel}
- onConfirm={!hasErrors ? () => onConfirm(form.new_token!) : undefined}
- onClear={!hasInputTheCorrectOldToken && oldToken ? onClear : undefined}
- >
- <div class="columns">
- <div class="column" />
- <div class="column is-four-fifths">
- <FormProvider errors={errors} object={form} valueHandler={setValue}>
- {oldToken && (
- <Input<State>
- name="old_token"
- label={i18n.str`Old access token`}
- tooltip={i18n.str`access token currently in use`}
- inputType="password"
- />
- )}
- <Input<State>
- name="new_token"
- label={i18n.str`New access token`}
- tooltip={i18n.str`next access token to be used`}
- inputType="password"
- />
- <Input<State>
- name="repeat_token"
- label={i18n.str`Repeat access token`}
- tooltip={i18n.str`confirm the same access token`}
- inputType="password"
- />
- </FormProvider>
- <p>
- <i18n.Translate>
- Clearing the access token will mean public access to the instance
- </i18n.Translate>
- </p>
- </div>
- <div class="column" />
- </div>
- </ClearConfirmModal>
- );
-}
-
-export function SetTokenNewInstanceModal({
- onCancel,
- onClear,
- onConfirm,
-}: UpdateTokenModalProps): VNode {
- type State = { old_token: string; new_token: string; repeat_token: string };
- const [form, setValue] = useState<Partial<State>>({
- new_token: "",
- repeat_token: "",
- });
- const { i18n } = useTranslationContext();
-
- const errors = {
- new_token: !form.new_token
- ? i18n.str`cannot be empty`
- : form.new_token === form.old_token
- ? i18n.str`cannot be the same as the old access token`
- : undefined,
- repeat_token:
- form.new_token !== form.repeat_token
- ? i18n.str`is not the same`
- : undefined,
- };
-
- const hasErrors = Object.keys(errors).some(
- (k) => (errors as any)[k] !== undefined,
- );
-
- return (
- <div class="modal is-active">
- <div class="modal-background " onClick={onCancel} />
- <div class="modal-card">
- <header class="modal-card-head">
- <p class="modal-card-title">{i18n.str`You are setting the access token for the new instance`}</p>
- <button class="delete " aria-label="close" onClick={onCancel} />
- </header>
- <section class="modal-card-body is-main-section">
- <div class="columns">
- <div class="column" />
- <div class="column is-four-fifths">
- <FormProvider
- errors={errors}
- object={form}
- valueHandler={setValue}
- >
- <Input<State>
- name="new_token"
- label={i18n.str`New access token`}
- tooltip={i18n.str`next access token to be used`}
- inputType="password"
- />
- <Input<State>
- name="repeat_token"
- label={i18n.str`Repeat access token`}
- tooltip={i18n.str`confirm the same access token`}
- inputType="password"
- />
- </FormProvider>
- <p>
- <i18n.Translate>
- With external authorization method no check will be done by
- the merchant backend
- </i18n.Translate>
- </p>
- </div>
- <div class="column" />
- </div>
- </section>
- <footer class="modal-card-foot">
- {onClear && (
- <button
- class="button is-danger"
- onClick={onClear}
- disabled={onClear === undefined}
- >
- <i18n.Translate>Set external authorization</i18n.Translate>
- </button>
- )}
- <div class="buttons is-right" style={{ width: "100%" }}>
- <button class="button " onClick={onCancel}>
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- <button
- class="button is-info"
- onClick={() => onConfirm(form.new_token!)}
- disabled={hasErrors}
- >
- <i18n.Translate>Set access token</i18n.Translate>
- </button>
- </div>
- </footer>
- </div>
- <button
- class="modal-close is-large "
- aria-label="close"
- onClick={onCancel}
- />
- </div>
- );
-}
-
-export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
- const { i18n } = useTranslationContext();
- return (
- <div class="modal is-active">
- <div class="modal-background " onClick={onCancel} />
- <div class="modal-card">
- <header class="modal-card-head">
- <p class="modal-card-title">
- <i18n.Translate>Operation in progress...</i18n.Translate>
- </p>
- </header>
- <section class="modal-card-body">
- <div class="columns">
- <div class="column" />
- <Spinner />
- <div class="column" />
- </div>
- <p>{i18n.str`The operation will be automatically canceled after ${DEFAULT_REQUEST_TIMEOUT} seconds`}</p>
- </section>
- <footer class="modal-card-foot">
- <div class="buttons is-right" style={{ width: "100%" }}>
- <button class="button " onClick={onCancel}>
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- </div>
- </footer>
- </div>
- <button
- class="modal-close is-large "
- aria-label="close"
- onClick={onCancel}
- />
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/context/backend.ts b/packages/auditor-backoffice-ui/src/context/backend.ts
index ce321c3e6..0d041f069 100644
--- a/packages/auditor-backoffice-ui/src/context/backend.ts
+++ b/packages/auditor-backoffice-ui/src/context/backend.ts
@@ -25,39 +25,32 @@ import { useContext } from "preact/hooks";
import { useBackendURL } from "../hooks/index.js";
interface BackendContextType {
- url: string,
+ url: string;
}
const BackendContext = createContext<BackendContextType>({
- url: "",
+ url: "",
});
-function useBackendContextState(
- defaultUrl?: string,
-): BackendContextType {
- const [url] = useBackendURL(defaultUrl);
-
- return {
- url,
- };
-}
-
export const BackendContextProvider = ({
- children,
- defaultUrl,
- }: {
- children: any;
- defaultUrl?: string;
+ children,
+ defaultUrl,
+}: {
+ children: any;
+ defaultUrl?: string;
}): VNode => {
- const value = useBackendContextState(defaultUrl);
-
- return h(BackendContext.Provider, { value, children });
+ const [url] = useBackendURL(defaultUrl);
+
+ return h(BackendContext.Provider, {
+ value: {
+ url,
+ },
+ children,
+ });
};
-
-
export const useBackendContext = (): BackendContextType =>
- useContext(BackendContext);
+ useContext(BackendContext);
interface BackendTokenType {
token: string;
@@ -67,4 +60,5 @@ const BackendTokenContext = createContext<BackendTokenType>({} as any);
export const BackendTokenContextProvider = BackendTokenContext.Provider;
-export const useBackendTokenContext = (): BackendTokenType => useContext(BackendTokenContext); \ No newline at end of file
+export const useBackendTokenContext = (): BackendTokenType =>
+ useContext(BackendTokenContext);
diff --git a/packages/auditor-backoffice-ui/src/declaration.d.ts b/packages/auditor-backoffice-ui/src/declaration.d.ts
index a8cdee53c..69839ef05 100644
--- a/packages/auditor-backoffice-ui/src/declaration.d.ts
+++ b/packages/auditor-backoffice-ui/src/declaration.d.ts
@@ -20,87 +20,11 @@
* @author Nic Eigel
*/
-type HashCode = string;
-type EddsaPublicKey = string;
-type EddsaSignature = string;
-type WireTransferIdentifierRawP = string;
-type RelativeTime = TalerProtocolDuration;
-type ImageDataUrl = string;
-type AuditorUserType = "business" | "individual";
-
-
export interface WithId {
id: string;
}
-interface Timestamp {
- // Milliseconds since epoch, or the special
- // value "forever" to represent an event that will
- // never happen.
- t_s: number | "never";
-}
-
-interface TalerProtocolDuration {
- d_us: number | "forever";
-}
-
-interface Duration {
- d_ms: number | "forever";
-}
-
-interface WithId {
- id: string;
-}
-
-type Amount = string;
-type UUID = string;
-type Integer = number;
-
export namespace AuditorBackend {
- interface DepositConfirmation {
- // identifier
- deposit_confirmation_serial_id: number;
-
- h_contract_terms: string;
-
- h_policy: string;
-
- h_wire: string;
-
- exchange_timestamp: string;
-
- refund_deadline: string;
-
- wire_deadline: string;
-
- total_without_fee: string;
-
- coin_pubs: string;
-
- coin_sigs: string;
-
- merchant_pub: string;
-
- merchant_sig: string;
-
- exchange_pub: string;
-
- exchange_sig: string;
-
- suppressed: string;
-
- ancient: string;
- }
-
- interface Config {
- name: string;
- version: string;
- implementation: string;
- currency: string;
- auditor_public_key: string;
- exchange_master_public_key: string;
- }
-
interface ErrorDetail {
// Numeric error code unique to the condition.
// The other arguments are specific to the error value reported here.
@@ -175,18 +99,7 @@ export namespace AuditorBackend {
// exchanges: ExchangeConfigInfo[];
}
- export interface TokenResponse {
- null;
- }
-
- namespace Default {
- interface ObjectResponse {
- object: AnyEntry[];
- }
- }
-
- namespace AmountArithmeticInconsistency {
-
+ namespace AmountArithmeticInconsistency {
class ClassAmountArithmeticInconsistency {
data: AmountArithmeticInconsistencyDetail[];
}
@@ -205,517 +118,7 @@ export namespace AuditorBackend {
}
}
- namespace BadSigLoss {
- class ClassBadSigLoss {
- data: BadSigLossDetail[];
- }
-
- interface SummaryResponse {
- amount_arithmetic_inconsistency: BadSigLossDetail[];
- }
-
- interface BadSigLossDetail
- {
- row_id: number;
- operation: string;
- loss: string;
- operation_specific_pub: string;
- suppressed: boolean;
- }
- }
-
- namespace Balance {
-
- class ClassBalance {
- // List of products that are present in the inventory
- data: BalanceDetail[];
- }
-
- interface SummaryResponse {
- // List of products that are present in the inventory
- balances: BalanceDetail[];
- }
-
- interface BalanceDetail {
- // identifier
- row_id: number;
-
- balance_key: string;
-
- balance_value: string;
-
- suppressed: boolean;
- }
- }
-
- namespace ClosureLag {
- class ClassClosureLag {
- // List of products that are present in the inventory
- data: ClosureLagDetail[];
- }
-
- interface SummaryResponse {
- // List of products that are present in the inventory
- closure_lags: ClosureLagDetail[];
- }
-
- interface ClosureLagDetail {
- row_id: number;
- amount: string;
- deadline: number;
- wtid: number;
- account: string;
- suppressed: boolean;
- }
- }
-
- namespace CoinInconsistency {
- class ClassCoinInconsistency {
- data: CoinInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- amount_arithmetic_inconsistency: CoinInconsistencyDetail[];
- }
-
- interface CoinInconsistencyDetail
- {
- row_id: number;
- operation: string;
- exchange_amount: string;
- auditor_amount: string;
- coin_pub: string;
- profitable: boolean;
- suppressed: boolean;
- }
- }
-
- namespace DenominationKeyValidityWithdrawInconsistency {
- class ClassDenominationKeyValidityWithdrawInconsistency {
- data: DenominationKeyValidityWithdrawInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: DenominationKeyValidityWithdrawInconsistencyDetail[];
- }
-
- interface DenominationKeyValidityWithdrawInconsistencyDetail
- {
- row_id: number;
- operation: string;
- loss: string;
- operation_specific_pub: string;
- suppressed: boolean;
- }
- }
-
- namespace DenominationPending {
- class ClassDenominationPending {
- data: DenominationPendingDetail[];
- }
-
- interface SummaryResponse {
- responseData: DenominationPendingDetail[];
- }
-
- interface DenominationPendingDetail
- {
- denom_pub_hash: string;
- denom_balance: string;
- denom_loss: string;
- num_issued: number;
- denom_risk: string;
- recoup_loss: string;
- suppressed: boolean;
- }
- }
-
- namespace DenominationsWithoutSigs {
- class ClassDenominationsWithoutSigs {
- data: DenominationsWithoutSigsDetail[];
- }
-
- interface SummaryResponse {
- responseData: DenominationsWithoutSigsDetail[];
- }
-
- interface DenominationsWithoutSigsDetail
- {
- row_id: number;
- denompub_h: string;
- value: string;
- start_time: number;
- end_time: number;
- suppressed: boolean;
- }
- }
-
- namespace DepositConfirmation {
- class ClassDepositConfirmation{
- data: DepositConfirmationDetail[];
- }
-
- interface SummaryResponse {
- responseData: DepositConfirmationDetail[];
- }
-
- interface DepositConfirmationDetail {
- deposit_confirmation_serial_id: number;
- h_contract_terms: string;
- h_policy: string;
- h_wire: string;
- exchange_timestamp: string;
- refund_deadline: string;
- wire_deadline: string;
- total_without_fee: string;
- coin_pubs: string;
- coin_sigs: string;
- merchant_pub: string;
- merchant_sig: string;
- exchange_pub: string;
- exchange_sig: string;
- suppressed: string;
- ancient: string;
- }
- }
-
- namespace Emergency {
- class ClassEmergency{
- data: EmergencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: EmergencyDetail[];
- }
-
- interface EmergencyDetail
- {
- row_id: number;
- denompub_h: string;
- denom_risk: string;
- denom_loss: string;
- deposit_start: number;
- deposit_end: number;
- value: string;
- }
- }
-
- namespace EmergencyByCount {
- class ClassEmergencyByCount{
- data: EmergencyByCountDetail[];
- }
-
- interface SummaryResponse {
- responseData: EmergencyByCountDetail[];
- }
-
- interface EmergencyByCountDetail
- {
- row_id: number;
- denompub_h: string;
- num_issued: number;
- num_known: number;
- risk: string;
- start: number;
- deposit_end: number;
- value: string;
- suppressed: boolean;
- }
- }
-
- namespace FeeTimeInconsistency {
- class ClassFeeTimeInconsistency{
- data: FeeTimeInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: FeeTimeInconsistencyDetail[];
- }
-
- interface FeeTimeInconsistencyDetail
- {
- row_id: number;
- type: string;
- time: string;
- diagnostic: string;
- suppressed: boolean;
- }
- }
-
- namespace HistoricDenominationRevenue {
- class ClassHistoricDenominationRevenue {
- data: HistoricDenominationRevenueDetail[];
- }
-
- interface SummaryResponse {
- responseData: HistoricDenominationRevenueDetail[];
- }
-
- interface HistoricDenominationRevenueDetail
- {
- denom_pub_hash: string;
- revenue_timestamp: number;
- revenue_balance: string;
- loss_balance: string;
- suppressed: boolean;
- }
- }
-
- namespace HistoricReserveSummary {
- class ClassHistoricReserveSummary {
- data: HistoricReserveSummaryDetail[];
- }
-
- interface SummaryResponse {
- responseData: HistoricReserveSummaryDetail[];
- }
-
- interface HistoricReserveSummaryDetail
- {
- denom_pub_hash: string;
- revenue_timestamp: number;
- revenue_balance: string;
- loss_balance: string;
- suppressed: boolean;
- }
- }
-
- namespace MisattributionInInconsistency {
- class ClassMisattributionInInconsistency {
- data: MisattributionInInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: MisattributionInInconsistencyDetail[];
- }
-
- interface MisattributionInInconsistencyDetail
- {
- row_id: number;
- amount: string;
- bank_row: number;
- reserve_pub: string;
- suppressed: boolean;
- }
- }
-
- namespace Progress {
- class ClassProgress {
- data: ProgressDetail[];
- }
-
- interface SummaryResponse {
- responseData: ProgressDetail[];
- }
-
- interface ProgressDetail
- {
- progress_key: string;
- progress_offset: number;
- suppressed: boolean;
- }
- }
-
- namespace PurseNotClosedInconsistency {
- class ClassPurseNotClosedInconsistency {
- data: PurseNotClosedInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: PurseNotClosedInconsistencyDetail[];
- }
-
- interface PurseNotClosedInconsistencyDetail
- {
- row_id: number;
- purse_pub: string,
- amount: string;
- expiration_date: number;
- suppressed: boolean;
- }
- }
-
- namespace Purses {
- class ClassPurses {
- data: PursesDetail[];
- }
-
- interface SummaryResponse {
- responseData: PursesDetail[];
- }
-
- interface PursesDetail
- {
- auditor_purses_rowid: number;
- purse_pub: string;
- balance: string;
- target: string,
- expiration_date: number;
- suppressed: boolean;
- }
- }
-
- namespace RefreshesHanging {
- class ClassRefreshesHanging {
- data: RefreshesHangingDetail[];
- }
-
- interface SummaryResponse {
- responseData: RefreshesHangingDetail[];
- }
-
- interface RefreshesHangingDetail
- {
- row_id: number;
- amount: string;
- coin_pub: string;
- suppressed: boolean;
- }
- }
-
- namespace ReserveBalanceInsufficientInconsistency {
- class ClassReserveBalanceInsufficientInconsistency {
- data: ReserveBalanceInsufficientInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: ReserveBalanceInsufficientInconsistencyDetail[];
- }
-
- interface ReserveBalanceInsufficientInconsistencyDetail
- {
- row_id: number;
- reserve_pub: string;
- inconsistency_gain: boolean;
- inconsistency_amount: string;
- suppressed: boolean;
- }
- }
-
- namespace ReserveBalanceSummaryWrongInconsistency {
- class ClassReserveBalanceSummaryWrongInconsistency {
- data: ReserveBalanceSummaryWrongInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: ReserveBalanceSummaryWrongInconsistencyDetail[];
- }
-
- interface ReserveBalanceSummaryWrongInconsistencyDetail
- {
- row_id: number;
- reserve_pub: string;
- exchange_amount: string;
- auditor_amount: string;
- suppressed: boolean;
- }
- }
-
- namespace ReserveInInconsistency {
- class ClassReserveInInconsistency {
- data: ReserveInInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: ReserveInInconsistencyDetail[];
- }
-
- interface ReserveInInconsistencyDetail
- {
- row_id: number;
- amount_exchange_expected: string;
- amount_wired: string;
- reserve_pub: string;
- timestamp: number;
- account: string;
- diagnostic: string;
- suppressed: boolean;
- }
- }
-
- namespace ReserveNotClosedInconsistency {
- class ClassReserveNotClosedInconsistency {
- data: ReserveNotClosedInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: ReserveNotClosedInconsistencyDetail[];
- }
-
- interface ReserveNotClosedInconsistencyDetail
- {
- row_id: number;
- reserve_pub: string;
- balance: string;
- expiration_time: number;
- diagnostic: string;
- suppressed: boolean;
- }
- }
-
- namespace Reserves {
- class ClassReserves{
- data: ReservesDetail[];
- }
-
- interface SummaryResponse {
- responseData: ReservesDetail[];
- }
-
- interface ReservesDetail
- {
- auditor_reserves_rowid: number;
- reserve_pub: string;
- reserve_balance: string;
- reserve_loss: string;
- withdraw_fee_balance: string;
- close_fee_balance: string;
- purse_fee_balance: string;
- open_fee_balance: string;
- history_fee_balance: string;
- expiration_date: number;
- origin_account: string;
- suppressed: boolean;
- }
- }
-
- namespace RowInconsistency {
- class ClassRowInconsistency {
- data: RowInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: RowInconsistencyDetail[];
- }
-
- interface RowInconsistencyDetail
- {
- row_id: number;
- row_table: string;
- diagnostic: string;
- suppressed: boolean;
- }
- }
-
- namespace RowMinorInconsistency {
- class ClassRowMinorInconsistency {
- data: RowMinorInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: RowMinorInconsistencyDetail[];
- }
-
- interface RowMinorInconsistencyDetail
- {
- row_id: number;
- row_table: string;
- diagnostic: string;
- suppressed: boolean;
- }
- }
-
- namespace WireFormatInconsistency {
+ namespace WireFormatInconsistency {
class ClassWireFormatInconsistency {
data: WireFormatInconsistencyDetail[];
}
@@ -724,8 +127,7 @@ export namespace AuditorBackend {
responseData: WireFormatInconsistencyDetail[];
}
- interface WireFormatInconsistencyDetail
- {
+ interface WireFormatInconsistencyDetail {
row_id: number;
amount: string;
wire_offset: string;
@@ -733,23 +135,4 @@ export namespace AuditorBackend {
suppressed: boolean;
}
}
-
- namespace WireOutInconsistency {
- class ClassWireOutInconsistency{
- data: WireOutInconsistencyDetail[];
- }
-
- interface SummaryResponse {
- responseData: WireOutInconsistencyDetail[];
- }
-
- interface WireOutInconsistencyDetail
- {
- row_id: number;
- destination_account: string;
- expected: string;
- claimed: string;
- suppressed: boolean;
- }
- }
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/backend.ts b/packages/auditor-backoffice-ui/src/hooks/backend.ts
index 4b0a5a828..69b63e02b 100644
--- a/packages/auditor-backoffice-ui/src/hooks/backend.ts
+++ b/packages/auditor-backoffice-ui/src/hooks/backend.ts
@@ -20,150 +20,160 @@
* @author Nic Eigel
*/
+/**
+ * Imports.
+ */
import {
- HttpResponse,
- HttpResponseOk,
- RequestError,
- RequestOptions,
- useApiContext,
+ HttpResponse,
+ HttpResponseOk,
+ RequestError,
+ RequestOptions,
+ useApiContext,
} from "@gnu-taler/web-util/browser";
-import {useCallback, useEffect, useState} from "preact/hooks";
-import {useSWRConfig} from "swr";
+import { useCallback, useEffect, useState } from "preact/hooks";
+import { useSWRConfig } from "swr";
import { useBackendContext } from "../context/backend.js";
import { AuditorBackend } from "../declaration.js";
export function useMatchMutate(): (
- re?: RegExp,
- value?: unknown,
+ re?: RegExp,
+ value?: unknown,
) => Promise<any> {
- const {cache, mutate} = useSWRConfig();
-
- if (!(cache instanceof Map)) {
- throw new Error(
- "matchMutate requires the cache provider to be a Map instance",
- );
- }
+ const { cache, mutate } = useSWRConfig();
- return function matchRegexMutate(re?: RegExp) {
- return mutate((key) => {
- // evict if no key or regex === all
- if (!key || !re) return true
- // match string
- if (typeof key === 'string' && re.test(key)) return true
- // record or object have the path at [0]
- if (typeof key === 'object' && re.test(key[0])) return true
- //key didn't match regex
- return false
- }, undefined, {
- revalidate: true,
- });
- };
+ if (!(cache instanceof Map)) {
+ throw new Error(
+ "matchMutate requires the cache provider to be a Map instance",
+ );
+ }
+
+ return function matchRegexMutate(re?: RegExp) {
+ return mutate(
+ (key) => {
+ // evict if no key or regex === all
+ if (!key || !re) return true;
+ // match string
+ if (typeof key === "string" && re.test(key)) return true;
+ // record or object have the path at [0]
+ if (typeof key === "object" && re.test(key[0])) return true;
+ //key didn't match regex
+ return false;
+ },
+ undefined,
+ {
+ revalidate: true,
+ },
+ );
+ };
}
const CHECK_CONFIG_INTERVAL_OK = 5 * 60 * 1000;
const CHECK_CONFIG_INTERVAL_FAIL = 2 * 1000;
export function useBackendConfig(): HttpResponse<
- AuditorBackend.VersionResponse | undefined,
- RequestError<AuditorBackend.ErrorDetail>
+ AuditorBackend.VersionResponse | undefined,
+ RequestError<AuditorBackend.ErrorDetail>
> {
- const {request} = useBackendBaseRequest();
-
- type Type = AuditorBackend.VersionResponse;
- type State = { data: HttpResponse<Type, RequestError<AuditorBackend.ErrorDetail>>, timer: number }
- const [result, setResult] = useState<State>({data: {loading: true}, timer: 0});
-
- useEffect(() => {
- if (result.timer) {
- clearTimeout(result.timer);
- }
+ const { request } = useBackendBaseRequest();
+
+ type Type = AuditorBackend.VersionResponse;
+ type State = {
+ data: HttpResponse<Type, RequestError<AuditorBackend.ErrorDetail>>;
+ timer: number;
+ };
+ const [result, setResult] = useState<State>({
+ data: { loading: true },
+ timer: 0,
+ });
+
+ useEffect(() => {
+ if (result.timer) {
+ clearTimeout(result.timer);
+ }
- function tryConfig(): void {
- request<Type>(`/config`)
- .then((data) => {
- const timer: any = setTimeout(() => {
- tryConfig();
- }, CHECK_CONFIG_INTERVAL_OK);
- setResult({data, timer});
- })
- .catch((error) => {
- const timer: any = setTimeout(() => {
- tryConfig();
- }, CHECK_CONFIG_INTERVAL_FAIL);
- const data = error.cause;
- setResult({data, timer});
- });
- }
+ function tryConfig(): void {
+ request<Type>("config")
+ .then((data) => {
+ const timer: any = setTimeout(() => {
+ tryConfig();
+ }, CHECK_CONFIG_INTERVAL_OK);
+ setResult({ data, timer });
+ })
+ .catch((error) => {
+ const timer: any = setTimeout(() => {
+ tryConfig();
+ }, CHECK_CONFIG_INTERVAL_FAIL);
+ const data = error.cause;
+ setResult({ data, timer });
+ });
+ }
- tryConfig();
- }, [request]);
+ tryConfig();
+ }, [request]);
- return result.data;
+ return result.data;
}
export function useBackendToken(): HttpResponse<
AuditorBackend.VersionResponse,
RequestError<AuditorBackend.ErrorDetail>
> {
- const {request} = useBackendBaseRequest();
-
- type Type = AuditorBackend.VersionResponse;
- type State = { data: HttpResponse<Type, RequestError<AuditorBackend.ErrorDetail>>, timer: number }
- const [result, setResult] = useState<State>({data: {loading: true}, timer: 0});
-
- useEffect(() => {
- if (result.timer) {
- clearTimeout(result.timer);
- }
+ const { request } = useBackendBaseRequest();
+
+ type Type = AuditorBackend.VersionResponse;
+ type State = {
+ data: HttpResponse<Type, RequestError<AuditorBackend.ErrorDetail>>;
+ timer: number;
+ };
+ const [result, setResult] = useState<State>({
+ data: { loading: true },
+ timer: 0,
+ });
+
+ useEffect(() => {
+ if (result.timer) {
+ clearTimeout(result.timer);
+ }
- function tryToken(): void {
- request<Type>(`/monitoring/balances`)
- .then((data) => {
- const timer: any = setTimeout(() => {
- tryToken();
- }, CHECK_CONFIG_INTERVAL_OK);
- setResult({data, timer});
- })
- .catch((error) => {
- const timer: any = setTimeout(() => {
- tryToken();
- }, CHECK_CONFIG_INTERVAL_FAIL);
- const data = error.cause;
- setResult({data, timer});
- });
- }
+ function tryToken(): void {
+ request<Type>(`/monitoring/balances`)
+ .then((data) => {
+ const timer: any = setTimeout(() => {
+ tryToken();
+ }, CHECK_CONFIG_INTERVAL_OK);
+ setResult({ data, timer });
+ })
+ .catch((error) => {
+ const timer: any = setTimeout(() => {
+ tryToken();
+ }, CHECK_CONFIG_INTERVAL_FAIL);
+ const data = error.cause;
+ setResult({ data, timer });
+ });
+ }
- tryToken();
- }, [request]);
+ tryToken();
+ }, [request]);
- return result.data;
+ return result.data;
}
interface useBackendInstanceRequestType {
-
- request: <T>(
- endpoint: string,
- options?: RequestOptions,
- ) => Promise<HttpResponseOk<T>>;
- fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
- multiFetcher: <T>(params: string[]) => Promise<HttpResponseOk<T>[]>;
- depositConfirmationFetcher: <T>(
- params: [
- endpoint: string,
- ],
- ) => Promise<HttpResponseOk<T>>;
+ request: <T>(
+ endpoint: string,
+ options?: RequestOptions,
+ ) => Promise<HttpResponseOk<T>>;
+ fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
+ multiFetcher: <T>(params: string[]) => Promise<HttpResponseOk<T>[]>;
}
interface useBackendBaseRequestType {
-
- request: <T>(
- endpoint: string,
- options?: RequestOptions
- ) => Promise<HttpResponseOk<T>>;
+ request: <T>(
+ endpoint: string,
+ options?: RequestOptions,
+ ) => Promise<HttpResponseOk<T>>;
}
-type YesOrNo = "yes" | "no";
-
/**
*
* @param root the request is intended to the base URL and no the instance URL
@@ -171,91 +181,67 @@ type YesOrNo = "yes" | "no";
*/
//TODO: Add token
export function useBackendBaseRequest(): useBackendBaseRequestType {
- const {url: backend} = useBackendContext();
- const {request: requestHandler} = useApiContext();
- //const { token } = useBackendTokenContext();
- const token = "D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0";
-
-
- const request = useCallback(
- function requestImpl<T>(
- endpoint: string,
- //todo: remove
- options: RequestOptions = {},
- ): Promise<HttpResponseOk<T>> {
- return requestHandler<T>(backend, endpoint, {...options, token}).then(res => {
- return res;
- }).catch(err => {
- throw err;
- });
- },
- [backend],
- );
+ const { url: backend } = useBackendContext();
+ const { request: requestHandler } = useApiContext();
+
+ const request = useCallback(
+ function requestImpl<T>(
+ endpoint: string,
+ //todo: remove
+ options: RequestOptions = {},
+ ): Promise<HttpResponseOk<T>> {
+ return requestHandler<T>(backend, endpoint, { ...options })
+ .then((res) => {
+ return res;
+ })
+ .catch((err) => {
+ throw err;
+ });
+ },
+ [backend],
+ );
- return {request};
+ return { request };
}
-
export function useBackendRequest(): useBackendInstanceRequestType {
- const {url: rootBackendUrl} = useBackendContext();
- // const {id} = useInstanceContext();
- const {request: requestHandler} = useApiContext();
-
- //TODO: check
- const baseUrl = "http://localhost:8083/";
- const token = "D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0";
-
-
-
-
- const request = useCallback(
- function requestImpl<T>(
- endpoint: string,
- options: RequestOptions = {},
- ): Promise<HttpResponseOk<T>> {
- return requestHandler<T>(baseUrl, endpoint, {...options, token});
- },
- [baseUrl],
- );
-
- const multiFetcher = useCallback(
- function multiFetcherImpl<T>(
- params: string[],
- options: RequestOptions = {},
- ): Promise<HttpResponseOk<T>[]> {
- return Promise.all(
- params.map((endpoint) =>
- requestHandler<T>(baseUrl, endpoint, {...options, token}),
- ),
- );
- },
- [baseUrl],
- );
-
- const fetcher = useCallback(
- function fetcherImpl<T>(endpoint: string): Promise<HttpResponseOk<T>> {
- return requestHandler<T>(baseUrl, endpoint, {token});
- },
- [baseUrl],
- );
-
- const depositConfirmationFetcher = useCallback(
- function orderFetcherImpl<T>(
- args: [endpoint: string,
- ],
- ): Promise<HttpResponseOk<T>> {
- const [endpoint] = args;
- const params: any = {"token": "D4CST1Z6AHN3RT03M0T9NSTF2QGHTB5ZD2D3RYZB4HAWG8SX0JEFWBXCKXZHMB7Y3Z7KVFW0B3XPXD5BHCFP8EB0R6CNH2KAWDWVET0"};
- return requestHandler<T>(baseUrl, endpoint, {params, token});
- },
- [baseUrl],
- );
-
-
- return {
- request,
- fetcher,
- depositConfirmationFetcher,
- multiFetcher
- };
-} \ No newline at end of file
+ const { url: baseUrl } = useBackendContext();
+ const { request: requestHandler } = useApiContext();
+
+ const request = useCallback(
+ function requestImpl<T>(
+ endpoint: string,
+ options: RequestOptions = {},
+ ): Promise<HttpResponseOk<T>> {
+ return requestHandler<T>(baseUrl, endpoint, { ...options });
+ },
+ [baseUrl],
+ );
+
+ const multiFetcher = useCallback(
+ function multiFetcherImpl<T>(
+ params: string[],
+ options: RequestOptions = {},
+ ): Promise<HttpResponseOk<T>[]> {
+ return Promise.all(
+ params.map((endpoint) =>
+ requestHandler<T>(baseUrl, endpoint, { ...options }),
+ ),
+ );
+ },
+ [baseUrl],
+ );
+
+ const fetcher = useCallback(
+ function fetcherImpl<T>(endpoint: string): Promise<HttpResponseOk<T>> {
+ return requestHandler<T>(baseUrl, endpoint, {});
+ },
+ [baseUrl],
+ );
+
+ return {
+ request,
+ fetcher,
+ multiFetcher,
+ };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/critical.ts b/packages/auditor-backoffice-ui/src/hooks/critical.ts
index 6a25d3037..8283fefbb 100644
--- a/packages/auditor-backoffice-ui/src/hooks/critical.ts
+++ b/packages/auditor-backoffice-ui/src/hooks/critical.ts
@@ -16,16 +16,13 @@
import {
HttpResponse,
HttpResponseOk,
- HttpResponsePaginated,
RequestError,
} from "@gnu-taler/web-util/browser";
-import { useEffect, useState } from "preact/hooks";
-import { AuditorBackend, WithId } from "../declaration.js";
-import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
-import { useBackendRequest, useMatchMutate } from "./backend.js";
+import { AuditorBackend } from "../declaration.js";
+import { useBackendRequest } from "./backend.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import _useSWR, { SWRHook, useSWRConfig } from "swr";
+import _useSWR, { SWRHook } from "swr";
const useSWR = _useSWR as unknown as SWRHook;
@@ -50,9 +47,9 @@ export function getCriticalData(
"monitoring/reserve-balance-insufficient-inconsistency",
];
-
const { data: list, error: listError } = useSWR<
- HttpResponseOk<any>[], RequestError<AuditorBackend.ErrorDetail>
+ HttpResponseOk<any>[],
+ RequestError<AuditorBackend.ErrorDetail>
>(endpoints, multiFetcher, {
refreshInterval: 60,
refreshWhenHidden: false,
@@ -67,4 +64,4 @@ export function getCriticalData(
return { ok: true, data: [list] };
}
return { loading: true };
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/entity.ts b/packages/auditor-backoffice-ui/src/hooks/entity.ts
index ae62da35e..3cfdd8616 100644
--- a/packages/auditor-backoffice-ui/src/hooks/entity.ts
+++ b/packages/auditor-backoffice-ui/src/hooks/entity.ts
@@ -13,28 +13,33 @@
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/>
*/
+
+/**
+ * Imports.
+ */
import {
HttpResponse,
HttpResponseOk,
RequestError,
} from "@gnu-taler/web-util/browser";
-import { AuditorBackend, WithId } from "../declaration.js";
+import { AuditorBackend } from "../declaration.js";
import { useBackendRequest, useMatchMutate } from "./backend.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import _useSWR, { SWRHook, useSWRConfig } from "swr";
+import _useSWR, { SWRHook } from "swr";
import { useEntityContext } from "../context/entity.js";
const useSWR = _useSWR as unknown as SWRHook;
-type YesOrNo = "yes" | "no";
-
interface Props {
endpoint: string;
entity: any;
}
-export function getEntityList({ endpoint, entity }: Props): HttpResponse<any, AuditorBackend.ErrorDetail> {
+export function getEntityList({
+ endpoint,
+ entity,
+}: Props): HttpResponse<any, AuditorBackend.ErrorDetail> {
const { fetcher } = useBackendRequest();
const { data: list, error: listError } = useSWR<
@@ -56,20 +61,16 @@ export function getEntityList({ endpoint, entity }: Props): HttpResponse<any, Au
return { loading: true };
}
export interface EntityAPI {
- updateEntity: (
- id: string
- ) => Promise<void>;
+ updateEntity: (id: string) => Promise<void>;
}
export function useEntityAPI(): EntityAPI {
const mutateAll = useMatchMutate();
const { request } = useBackendRequest();
- const { endpoint } = useEntityContext();
- const data = {"suppressed": true};
+ const { endpoint } = useEntityContext();
+ const data = { suppressed: true };
- const updateEntity = async (
- id: string,
- ): Promise<void> => {
+ const updateEntity = async (id: string): Promise<void> => {
const r = await request(`monitoring/${endpoint}/${id}`, {
method: "PATCH",
data,
@@ -79,4 +80,4 @@ export function useEntityAPI(): EntityAPI {
};
return { updateEntity };
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/finance.ts b/packages/auditor-backoffice-ui/src/hooks/finance.ts
index 97bf2577f..a0d035735 100644
--- a/packages/auditor-backoffice-ui/src/hooks/finance.ts
+++ b/packages/auditor-backoffice-ui/src/hooks/finance.ts
@@ -13,21 +13,27 @@
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/>
*/
+
+/**
+ * Imports.
+ */
import {
HttpResponse,
HttpResponseOk,
RequestError,
} from "@gnu-taler/web-util/browser";
-import { AuditorBackend, WithId } from "../declaration.js";
-import { useBackendRequest, useMatchMutate } from "./backend.js";
+import { AuditorBackend } from "../declaration.js";
+import { useBackendRequest } from "./backend.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import _useSWR, { SWRHook, useSWRConfig } from "swr";
+import _useSWR, { SWRHook } from "swr";
const useSWR = _useSWR as unknown as SWRHook;
-
-export function getKeyFiguresData(): HttpResponse<any, AuditorBackend.ErrorDetail> {
+export function getKeyFiguresData(): HttpResponse<
+ any,
+ AuditorBackend.ErrorDetail
+> {
const { multiFetcher } = useBackendRequest();
const endpoints = [
"monitoring/misattribution-in-inconsistency",
@@ -39,11 +45,11 @@ export function getKeyFiguresData(): HttpResponse<any, AuditorBackend.ErrorDetai
"monitoring/wire-format-inconsistency",
"monitoring/wire-out-inconsistency",
"monitoring/reserve-balance-summary-wrong-inconsistency",
-
];
const { data: list, error: listError } = useSWR<
- HttpResponseOk<any>[], RequestError<AuditorBackend.ErrorDetail>
+ HttpResponseOk<any>[],
+ RequestError<AuditorBackend.ErrorDetail>
>(endpoints, multiFetcher, {
refreshInterval: 60,
refreshWhenHidden: false,
diff --git a/packages/auditor-backoffice-ui/src/hooks/index.ts b/packages/auditor-backoffice-ui/src/hooks/index.ts
index cf1c57771..b844c49cf 100644
--- a/packages/auditor-backoffice-ui/src/hooks/index.ts
+++ b/packages/auditor-backoffice-ui/src/hooks/index.ts
@@ -14,66 +14,67 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import {StateUpdater, useState} from "preact/hooks";
+import { canonicalizeBaseUrl } from "@gnu-taler/taler-util";
+import { StateUpdater, useState } from "preact/hooks";
import { ValueOrFunction } from "../utils/types.js";
-export function useBackendURL(
- url?: string,
-): [string, StateUpdater<string>] {
- const [value, setter] = useSimpleLocalStorage(
- "auditor-base-url",
- url || calculateRootPath(),
- );
+export function useBackendURL(url?: string): [string, StateUpdater<string>] {
+ const canonUrl = canonicalizeBaseUrl(url ?? calculateRootPath());
+
+ const [value, setter] = useSimpleLocalStorage("auditor-base-url", canonUrl);
- const checkedSetter = (v: ValueOrFunction<string>) => {
- return setter((p) => (v instanceof Function ? v(p ?? "") : v).replace(/\/$/, ""));
- };
+ const checkedSetter = (v: ValueOrFunction<string>) => {
+ // FIXME: Explain?!
+ return setter((p) =>
+ (v instanceof Function ? v(p ?? "") : v).replace(/\/$/, ""),
+ );
+ };
- return [value!, checkedSetter];
+ return [value!, checkedSetter];
}
-const calculateRootPath = () => {
- const rootPath =
- typeof window !== undefined
- ? window.location.origin + window.location.pathname
- : "/";
+function calculateRootPath() {
+ const rootPath =
+ typeof window !== undefined
+ ? window.location.origin + window.location.pathname
+ : "/";
- /**
- * By default, auditor backend serves the html content
- * from the /webui root. This should cover most of the
- * cases and the rootPath will be the auditor backend
- * URL where the instances are
- */
- return rootPath.replace("/webui/", "");
-};
+ /*
+ * By default, auditor backend serves the html content
+ * from the /webui root. This should cover most of the
+ * cases and the rootPath will be the auditor backend
+ * URL where the instances are
+ */
+ return rootPath.replace("/spa/", "");
+}
-export function useSimpleLocalStorage(
- key: string,
- initialValue?: string,
+function useSimpleLocalStorage(
+ key: string,
+ initialValue?: string,
): [string | undefined, StateUpdater<string | undefined>] {
- const [storedValue, setStoredValue] = useState<string | undefined>(
- (): string | undefined => {
- return typeof window !== "undefined"
- ? window.localStorage.getItem(key) || initialValue
- : initialValue;
- },
- );
+ const [storedValue, setStoredValue] = useState<string | undefined>(
+ (): string | undefined => {
+ return typeof window !== "undefined"
+ ? window.localStorage.getItem(key) || initialValue
+ : initialValue;
+ },
+ );
- const setValue = (
- value?: string | ((val?: string) => string | undefined),
- ) => {
- setStoredValue((p) => {
- const toStore = value instanceof Function ? value(p) : value;
- if (typeof window !== "undefined") {
- if (!toStore) {
- window.localStorage.removeItem(key);
- } else {
- window.localStorage.setItem(key, toStore);
- }
- }
- return toStore;
- });
- };
+ const setValue = (
+ value?: string | ((val?: string) => string | undefined),
+ ) => {
+ setStoredValue((p) => {
+ const toStore = value instanceof Function ? value(p) : value;
+ if (typeof window !== "undefined") {
+ if (!toStore) {
+ window.localStorage.removeItem(key);
+ } else {
+ window.localStorage.setItem(key, toStore);
+ }
+ }
+ return toStore;
+ });
+ };
- return [storedValue, setValue];
-} \ No newline at end of file
+ return [storedValue, setValue];
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/operational.ts b/packages/auditor-backoffice-ui/src/hooks/operational.ts
index 89524f24e..c40a1423c 100644
--- a/packages/auditor-backoffice-ui/src/hooks/operational.ts
+++ b/packages/auditor-backoffice-ui/src/hooks/operational.ts
@@ -18,11 +18,11 @@ import {
HttpResponseOk,
RequestError,
} from "@gnu-taler/web-util/browser";
-import { AuditorBackend, WithId } from "../declaration.js";
-import { useBackendRequest, useMatchMutate } from "./backend.js";
+import { AuditorBackend } from "../declaration.js";
+import { useBackendRequest } from "./backend.js";
// FIX default import https://github.com/microsoft/TypeScript/issues/49189
-import _useSWR, { SWRHook, useSWRConfig } from "swr";
+import _useSWR, { SWRHook } from "swr";
const useSWR = _useSWR as unknown as SWRHook;
@@ -49,17 +49,16 @@ export function getOperationData(
"monitoring/denomination-key-validity-withdraw-inconsistency",
"monitoring/refreshes-hanging",
//TODO fix endpoint
- // "monitoring/closure-lags",
- // "monitoring/row-minor-inconsistencies",
- // "monitoring/historic-denomination-revenue",
- // "monitoring/denomination-pending",
+ // "monitoring/closure-lags",
+ // "monitoring/row-minor-inconsistencies",
+ // "monitoring/historic-denomination-revenue",
+ // "monitoring/denomination-pending",
"monitoring/historic-reserve-summary",
-
];
-
const { data: list, error: listError } = useSWR<
- HttpResponseOk<any>[], RequestError<AuditorBackend.ErrorDetail>
+ HttpResponseOk<any>[],
+ RequestError<AuditorBackend.ErrorDetail>
>(endpoints, multiFetcher, {
refreshInterval: 60,
refreshWhenHidden: false,
@@ -77,7 +76,5 @@ export function getOperationData(
}
export interface EntityAPI {
- updateEntity: (
- id: string,
- ) => Promise<void>;
-} \ No newline at end of file
+ updateEntity: (id: string) => Promise<void>;
+}
diff --git a/packages/auditor-backoffice-ui/src/index.tsx b/packages/auditor-backoffice-ui/src/index.tsx
index fc956e8aa..7fdf7c1c3 100644
--- a/packages/auditor-backoffice-ui/src/index.tsx
+++ b/packages/auditor-backoffice-ui/src/index.tsx
@@ -21,4 +21,4 @@ import "./scss/main.scss";
const app = document.getElementById("app");
-render(<Application />, app as any); \ No newline at end of file
+render(<Application />, app as any);
diff --git a/packages/auditor-backoffice-ui/src/paths/default/Table.tsx b/packages/auditor-backoffice-ui/src/paths/default/Table.tsx
index 9bb75907d..05db3fc43 100644
--- a/packages/auditor-backoffice-ui/src/paths/default/Table.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/default/Table.tsx
@@ -20,16 +20,18 @@
*/
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { StateUpdater, useState } from "preact/hooks";
-import { useEntityContext, useEntityDataContext } from "../../context/entity.js";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import {
+ useEntityContext,
+ useEntityDataContext,
+} from "../../context/entity.js";
interface Props {
onSuppress: (id: any) => void;
}
-export function CardTable({onSuppress}: Props): any {
-
+export function CardTable({ onSuppress }: Props): any {
const data = useEntityDataContext();
const [rowSelection, rowSelectionHandler] = useState<string | undefined>(
undefined,
@@ -46,17 +48,14 @@ export function CardTable({onSuppress}: Props): any {
</span>
<i18n.Translate>{title}</i18n.Translate>
</p>
- <div class="card-header-icon" aria-label="more options">
- </div>
+ <div class="card-header-icon" aria-label="more options"></div>
</header>
<div class="card-content">
<div class="b-table has-pagination">
<div class="table-wrapper has-mobile-cards">
- {(data.data[0][endpoint] !== undefined && data.data[0][endpoint].length != 0) ? (
- <Table
- data={data.data[0][endpoint]}
- onSuppress={onSuppress}
- />
+ {data.data[0][endpoint] !== undefined &&
+ data.data[0][endpoint].length != 0 ? (
+ <Table data={data.data[0][endpoint]} onSuppress={onSuppress} />
) : (
<EmptyTable />
)}
@@ -72,10 +71,7 @@ interface TableProps {
onSuppress: (id: any) => void;
}
-function Table({
- data,
- onSuppress,
- }: TableProps): VNode {
+function Table({ data, onSuppress }: TableProps): VNode {
const { i18n } = useTranslationContext();
const { entity } = useEntityContext();
type Entity = typeof entity;
@@ -85,51 +81,50 @@ function Table({
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
<thead>
- <tr>
- {Object.keys(data[0]).map((i: Entity) => {
- const paramName = i[0].toUpperCase() + i.replace("_", " ").slice(1, i.count);
- return (
- <Fragment key={count.toString() + i}>
- <th>
- <i18n.Translate>{paramName}</i18n.Translate>
- </th>
- </Fragment>);
- })}
- </tr>
+ <tr>
+ {Object.keys(data[0]).map((i: Entity) => {
+ const paramName =
+ i[0].toUpperCase() + i.replace("_", " ").slice(1, i.count);
+ return (
+ <Fragment key={count.toString() + i}>
+ <th>
+ <i18n.Translate>{paramName}</i18n.Translate>
+ </th>
+ </Fragment>
+ );
+ })}
+ </tr>
</thead>
<tbody>
- {data.map((key: Entity, value: string) => {
- return (
- <tr>
- {Object.keys(data[0]).map((i: Entity) => {
- return (
- <Fragment>
- <td>
- {(key[i] == false) ? "false" : key[i]}
- </td>
- </Fragment>
- );
- })}
- <td class="is-actions-cell right-sticky">
- <div class="buttons is-right">
- <span
- class="has-tooltip-bottom"
- data-tooltip={i18n.str`suppress`}
+ {data.map((key: Entity, value: string) => {
+ return (
+ <tr>
+ {Object.keys(data[0]).map((i: Entity) => {
+ return (
+ <Fragment>
+ <td>{key[i] == false ? "false" : key[i]}</td>
+ </Fragment>
+ );
+ })}
+ <td class="is-actions-cell right-sticky">
+ <div class="buttons is-right">
+ <span
+ class="has-tooltip-bottom"
+ data-tooltip={i18n.str`suppress`}
+ >
+ <button
+ class="button is-small is-success "
+ type="button"
+ onClick={(): void => onSuppress(key["row_id"])}
>
- <button
- class="button is-small is-success "
- type="button"
- onClick={(): void => onSuppress(key["row_id"])}
- >
- {<i18n.Translate>Suppress</i18n.Translate>}
- </button>
- </span>
- </div>
- </td>
- </tr>
- );
- })
- }
+ {<i18n.Translate>Suppress</i18n.Translate>}
+ </button>
+ </span>
+ </div>
+ </td>
+ </tr>
+ );
+ })}
</tbody>
</table>
</div>
@@ -142,14 +137,12 @@ function EmptyTable(): VNode {
<div class="content has-text-grey has-text-centered">
<p>
<span class="icon is-large">
- <i class="mdi mdi-emoticon-happy mdi-48px" />
+ <i class="mdi mdi-emoticon-happy mdi-48px" />
</span>
</p>
<p>
- <i18n.Translate>
- There are no entries yet
- </i18n.Translate>
+ <i18n.Translate>There are no entries yet</i18n.Translate>
</p>
</div>
);
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/default/index.tsx b/packages/auditor-backoffice-ui/src/paths/default/index.tsx
index 1b7758190..1bcd17b1c 100644
--- a/packages/auditor-backoffice-ui/src/paths/default/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/default/index.tsx
@@ -19,41 +19,40 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
+import { HttpStatusCode } from "@gnu-taler/taler-util";
import {
ErrorType,
HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
+import { route } from "preact-router";
+import { useMemo, useState } from "preact/hooks";
import { Loading } from "../../components/exception/loading.js";
import { NotificationCard } from "../../components/menu/index.js";
+import { ConfirmModal } from "../../components/modal/index.js";
+import {
+ EntityDataContextProvider,
+ useEntityContext,
+} from "../../context/entity.js";
import { AuditorBackend, WithId } from "../../declaration.js";
-import { Notification } from "../../utils/types.js";
-import { CardTable } from "./Table.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
-import { EntityDataContextProvider, useEntityContext } from "../../context/entity.js";
import { getEntityList, useEntityAPI } from "../../hooks/entity.js";
-import { useMemo } from "preact/hooks";
-import { ConfirmModal, DeleteModal } from "../../components/modal/index.js";
-import { route } from "preact-router";
import { Paths } from "../../InstanceRoutes.js";
-
+import { Notification } from "../../utils/types.js";
+import { CardTable } from "./Table.js";
interface Props {
onNotFound: () => VNode;
onLoadError: (e: HttpError<AuditorBackend.ErrorDetail>) => VNode;
}
-export default function DefaultList({
- onLoadError,
- onNotFound,
- }: Props): VNode {
+export default function DefaultList({ onLoadError, onNotFound }: Props): VNode {
const { endpoint, entity } = useEntityContext();
const result = getEntityList({ endpoint, entity });
const { updateEntity } = useEntityAPI();
- const [suppressing, setSuppressing] =
- useState<typeof entity & WithId | null>(null);
+ const [suppressing, setSuppressing] = useState<
+ (typeof entity & WithId) | null
+ >(null);
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
@@ -68,31 +67,24 @@ export default function DefaultList({
}
let data = result.data;
- const value = useMemo(
- () => ({ data }),
- [data],
- );
+ const value = useMemo(() => ({ data }), [data]);
function onReturn(): void {
route(Paths.detail_view);
}
return (
-
<section class="section is-main-section">
- <button
- class="button is-fullwidth"
- onClick={onReturn}
- >Back
- </button><br />
+ <button class="button is-fullwidth" onClick={onReturn}>
+ Back
+ </button>
+ <br />
<NotificationCard notification={notif} />
<EntityDataContextProvider value={value}>
<CardTable
- onSuppress={(e: typeof entity & WithId) =>
- setSuppressing(e)
- }
+ onSuppress={(e: typeof entity & WithId) => setSuppressing(e)}
/>
</EntityDataContextProvider>
diff --git a/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx b/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx
index 60ae7b578..602ce5ef0 100644
--- a/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx
@@ -20,10 +20,9 @@
*/
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode, Fragment } from "preact";
-import { route, Route } from "preact-router";
-import { Paths, Redirect } from "../../InstanceRoutes.js";
-import { AuditorBackend } from "../../declaration.js";
+import { Fragment, h, VNode } from "preact";
+import { route } from "preact-router";
+import { Paths } from "../../InstanceRoutes.js";
export interface ListPageProps {
onShowAll: () => void;
@@ -56,16 +55,18 @@ export function ListPage(): VNode {
return (
<Fragment>
-
<div class="columns">
<div class="column">
<div class="card">
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.amount_arithmethic_inconsistency_list) }
+ onClick={(e) =>
+ route(Paths.amount_arithmethic_inconsistency_list)
+ }
value={"Amount arithmetic inconsistencies"}
- >Amount arithmetic inconsistencies
+ >
+ Amount arithmetic inconsistencies
</button>
</div>
</div>
@@ -75,9 +76,10 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.bad_sig_losses_list) }
+ onClick={(e) => route(Paths.bad_sig_losses_list)}
value={"Bad signature losses"}
- >Bad signature losses
+ >
+ Bad signature losses
</button>
</div>
</div>
@@ -87,8 +89,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.closure_lag_list) }
- >Closure Lags
+ onClick={(e) => route(Paths.closure_lag_list)}
+ >
+ Closure Lags
</button>
</div>
</div>
@@ -98,8 +101,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.coin_inconsistency_list) }
- >Coin inconsistencies
+ onClick={(e) => route(Paths.coin_inconsistency_list)}
+ >
+ Coin inconsistencies
</button>
</div>
</div>
@@ -112,8 +116,13 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.denomination_key_validity_withdraw_inconsistency_list) }
- >Denominations key validity
+ onClick={(e) =>
+ route(
+ Paths.denomination_key_validity_withdraw_inconsistency_list,
+ )
+ }
+ >
+ Denominations key validity
</button>
</div>
</div>
@@ -123,8 +132,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.denomination_without_sig_list) }
- >Denominations without signature
+ onClick={(e) => route(Paths.denomination_without_sig_list)}
+ >
+ Denominations without signature
</button>
</div>
</div>
@@ -134,8 +144,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.denomination_pending_list) }
- >Denominations pending
+ onClick={(e) => route(Paths.denomination_pending_list)}
+ >
+ Denominations pending
</button>
</div>
</div>
@@ -145,8 +156,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.deposit_confirmation_list) }
- >Deposit confirmations
+ onClick={(e) => route(Paths.deposit_confirmation_list)}
+ >
+ Deposit confirmations
</button>
</div>
</div>
@@ -159,8 +171,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.emergency_list) }
- >Emergencies
+ onClick={(e) => route(Paths.emergency_list)}
+ >
+ Emergencies
</button>
</div>
</div>
@@ -170,8 +183,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.emergency_by_count_list) }
- >Emergencies by count
+ onClick={(e) => route(Paths.emergency_by_count_list)}
+ >
+ Emergencies by count
</button>
</div>
</div>
@@ -181,8 +195,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.fee_time_inconsistency_list) }
- >Fee time inconsistencies
+ onClick={(e) => route(Paths.fee_time_inconsistency_list)}
+ >
+ Fee time inconsistencies
</button>
</div>
</div>
@@ -192,8 +207,11 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.misattribution_in_inconsistency_list) }
- >Misattribution in inconsistencies
+ onClick={(e) =>
+ route(Paths.misattribution_in_inconsistency_list)
+ }
+ >
+ Misattribution in inconsistencies
</button>
</div>
</div>
@@ -206,8 +224,11 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.purse_not_closed_inconsistency_list) }
- >Purses not closed
+ onClick={(e) =>
+ route(Paths.purse_not_closed_inconsistency_list)
+ }
+ >
+ Purses not closed
</button>
</div>
</div>
@@ -217,8 +238,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.purse_list) }
- >Purses
+ onClick={(e) => route(Paths.purse_list)}
+ >
+ Purses
</button>
</div>
</div>
@@ -228,8 +250,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.refresh_hanging_list) }
- >Refreshes hanging
+ onClick={(e) => route(Paths.refresh_hanging_list)}
+ >
+ Refreshes hanging
</button>
</div>
</div>
@@ -239,8 +262,11 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.reserve_balance_insufficient_inconsistency_list) }
- >Reserve balances insufficient
+ onClick={(e) =>
+ route(Paths.reserve_balance_insufficient_inconsistency_list)
+ }
+ >
+ Reserve balances insufficient
</button>
</div>
</div>
@@ -253,8 +279,11 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.reserve_balance_summary_wrong_inconsistency_list) }
- >Reserve balances summary wrong
+ onClick={(e) =>
+ route(Paths.reserve_balance_summary_wrong_inconsistency_list)
+ }
+ >
+ Reserve balances summary wrong
</button>
</div>
</div>
@@ -264,8 +293,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.reserve_in_inconsistency_list) }
- >Reserves in
+ onClick={(e) => route(Paths.reserve_in_inconsistency_list)}
+ >
+ Reserves in
</button>
</div>
</div>
@@ -275,8 +305,11 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.reserve_not_closed_inconsistency_list) }
- >Reserves not closed
+ onClick={(e) =>
+ route(Paths.reserve_not_closed_inconsistency_list)
+ }
+ >
+ Reserves not closed
</button>
</div>
</div>
@@ -286,8 +319,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.reserves_list) }
- >Reserves
+ onClick={(e) => route(Paths.reserves_list)}
+ >
+ Reserves
</button>
</div>
</div>
@@ -300,8 +334,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.row_inconsistency_list) }
- >Row inconsistencies
+ onClick={(e) => route(Paths.row_inconsistency_list)}
+ >
+ Row inconsistencies
</button>
</div>
</div>
@@ -311,8 +346,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.row_minor_inconsistency_list) }
- >Row minor inconsistencies
+ onClick={(e) => route(Paths.row_minor_inconsistency_list)}
+ >
+ Row minor inconsistencies
</button>
</div>
</div>
@@ -322,8 +358,9 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.wire_format_inconsistency_list) }
- >Wire format inconsistencies
+ onClick={(e) => route(Paths.wire_format_inconsistency_list)}
+ >
+ Wire format inconsistencies
</button>
</div>
</div>
@@ -333,14 +370,14 @@ export function ListPage(): VNode {
<div class="card-body">
<button
class="button is-fullwidth"
- onClick={(e) => route(Paths.wire_out_inconsistency_list) }
- >Wire out inconsistencies
+ onClick={(e) => route(Paths.wire_out_inconsistency_list)}
+ >
+ Wire out inconsistencies
</button>
</div>
</div>
</div>
</div>
-
</Fragment>
);
}
diff --git a/packages/auditor-backoffice-ui/src/paths/details/index.tsx b/packages/auditor-backoffice-ui/src/paths/details/index.tsx
index f99dae7e5..163ccd3c9 100644
--- a/packages/auditor-backoffice-ui/src/paths/details/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/details/index.tsx
@@ -27,7 +27,6 @@ import { Notification } from "../../utils/types.js";
import { ListPage } from "./ListPage.js";
export default function DetailsDashboard(): VNode {
-
const [notif, setNotif] = useState<Notification | undefined>(undefined);
return (
@@ -36,4 +35,4 @@ export default function DetailsDashboard(): VNode {
<ListPage />
</section>
);
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx b/packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx
index 88ca6bcfd..4a05ae851 100644
--- a/packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx
@@ -20,12 +20,12 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode, Fragment } from "preact";
+/**
+ * Imports.
+ */
+import { Fragment, h, VNode } from "preact";
export function ListPage(data: any): VNode {
- const { i18n } = useTranslationContext();
-
let balances = data.data.data[0][4].data.balances;
let coinBalances = [
"Total recoup loss",
@@ -62,45 +62,77 @@ export function ListPage(data: any): VNode {
<div class="card-content">
<table class="table is-striped is-fullwidth is-dark">
<tbody>
- <tr>
- <th>Finding</th>
- <td class="has-text-right"><b>Count</b></td>
- <td class="has-text-right"><b>Gain/Loss</b></td>
- </tr>
- {
- data["data"]["data"][0].map((x: any) => {
+ <tr>
+ <th>Finding</th>
+ <td class="has-text-right">
+ <b>Count</b>
+ </td>
+ <td class="has-text-right">
+ <b>Gain/Loss</b>
+ </td>
+ </tr>
+ {data["data"]["data"][0].map((x: any) => {
const key = Object.keys(x.data)[0];
let value = Object.values(x.data)[0];
- const paramName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+ const paramName =
+ key[0].toUpperCase() +
+ key
+ .split("_")
+ .join(" ")
+ .split("-")
+ .join(" ")
+ .slice(1, key.length);
if (key == "balances") {
//TODO fix
let gains = 0;
- if (value == null)
- value = 0;
- else
- value = Object.keys(value).length;
+ if (value == null) value = 0;
+ else value = Object.keys(value).length;
return (
<tr class="is-link">
<td>{paramName}</td>
- <td class="has-text-right"><p
- class={value == 0 ? "text-success" : "text-danger"}>{String(value)}</p></td>
- <td class="has-text-right"><p
- class={gains == 0 ? "text-success" : "text-danger"}>{String(gains)}</p></td>
+ <td class="has-text-right">
+ <p
+ class={
+ value == 0 ? "text-success" : "text-danger"
+ }
+ >
+ {String(value)}
+ </p>
+ </td>
+ <td class="has-text-right">
+ <p
+ class={
+ gains == 0 ? "text-success" : "text-danger"
+ }
+ >
+ {String(gains)}
+ </p>
+ </td>
</tr>
);
} else {
<tr class="is-link">
<td>{paramName}</td>
- <td class="has-text-right"><p
- class={value == 0 ? "text-success" : "text-danger"}>{String(value)}</p></td>
- <td class="has-text-right"><p>{
- //TODO
- }</p></td>
+ <td class="has-text-right">
+ <p
+ class={
+ value == 0 ? "text-success" : "text-danger"
+ }
+ >
+ {String(value)}
+ </p>
+ </td>
+ <td class="has-text-right">
+ <p>
+ {
+ //TODO
+ }
+ </p>
+ </td>
</tr>;
}
- })
- }
+ })}
</tbody>
</table>
</div>
@@ -109,34 +141,44 @@ export function ListPage(data: any): VNode {
<div class="card-content">
<table class="table is-striped is-fullwidth is-dark">
<tbody>
- <tr>
- <th>Summary</th>
- <td class="has-text-right"><b>Value</b></td>
- </tr>
- <tr>
- <td>Total gain/loss</td>
- <td class="has-text-right">{
- //TODO fix
- }</td>
- </tr>
- <tr>
- <td>Pending gain/loss</td>
- <td class="has-text-right">{
- //TODO fix
- }</td>
- </tr>
- <tr>
- <td>Transaction count</td>
- <td class="has-text-right">{
- //TODO fix
- }</td>
- </tr>
- <tr>
- <td>Transactions pending</td>
- <td class="has-text-right">{
- //TODO fix
- }</td>
- </tr>
+ <tr>
+ <th>Summary</th>
+ <td class="has-text-right">
+ <b>Value</b>
+ </td>
+ </tr>
+ <tr>
+ <td>Total gain/loss</td>
+ <td class="has-text-right">
+ {
+ //TODO fix
+ }
+ </td>
+ </tr>
+ <tr>
+ <td>Pending gain/loss</td>
+ <td class="has-text-right">
+ {
+ //TODO fix
+ }
+ </td>
+ </tr>
+ <tr>
+ <td>Transaction count</td>
+ <td class="has-text-right">
+ {
+ //TODO fix
+ }
+ </td>
+ </tr>
+ <tr>
+ <td>Transactions pending</td>
+ <td class="has-text-right">
+ {
+ //TODO fix
+ }
+ </td>
+ </tr>
</tbody>
</table>
</div>
@@ -150,59 +192,75 @@ export function ListPage(data: any): VNode {
<p class="has-text-weight-bold">Helper coin</p>
<table class="table is-striped is-fullwidth is-dark">
<tbody>
- <tr>
- <th>Balance</th>
- <td><b>Value</b></td>
- </tr>
- {
- balances.map((x: any) => {
+ <tr>
+ <th>Balance</th>
+ <td>
+ <b>Value</b>
+ </td>
+ </tr>
+ {balances.map((x: any) => {
let key = x.balance_key;
- let balanceName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+ let balanceName =
+ key[0].toUpperCase() +
+ key
+ .split("_")
+ .join(" ")
+ .split("-")
+ .join(" ")
+ .slice(1, key.length);
- if(coinBalances.includes(balanceName))
- {
+ if (coinBalances.includes(balanceName)) {
let value = balances[i].balance_value.replace(":", " ");
- i=i+1;
+ i = i + 1;
return (
<tr class="is-link">
<td>{balanceName}</td>
- <td><p>{value}</p></td>
+ <td>
+ <p>{value}</p>
+ </td>
</tr>
);
} else {
return null;
}
- })
- }
+ })}
</tbody>
</table>
<p class="has-text-weight-bold">Helper reserve</p>
<table class="table is-striped is-fullwidth is-dark">
<tbody>
- <tr>
- <th>Balance</th>
- <td><b>Value</b></td>
- </tr>
- {
- balances.map((x: any) => {
+ <tr>
+ <th>Balance</th>
+ <td>
+ <b>Value</b>
+ </td>
+ </tr>
+ {balances.map((x: any) => {
let key = x.balance_key;
- let balanceName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+ let balanceName =
+ key[0].toUpperCase() +
+ key
+ .split("_")
+ .join(" ")
+ .split("-")
+ .join(" ")
+ .slice(1, key.length);
- if(reserveBalances.includes(balanceName))
- {
+ if (reserveBalances.includes(balanceName)) {
let value = balances[i].balance_value.replace(":", " ");
- i = i+1;
+ i = i + 1;
return (
<tr class="is-link">
<td>{balanceName}</td>
- <td><p>{value}</p></td>
+ <td>
+ <p>{value}</p>
+ </td>
</tr>
);
} else {
return null;
}
- })
- }
+ })}
</tbody>
</table>
</div>
diff --git a/packages/auditor-backoffice-ui/src/paths/finance/index.tsx b/packages/auditor-backoffice-ui/src/paths/finance/index.tsx
index b0d07aa0f..13c718886 100644
--- a/packages/auditor-backoffice-ui/src/paths/finance/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/finance/index.tsx
@@ -20,19 +20,15 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import {
- ErrorType,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ErrorType, useTranslationContext } from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../components/exception/loading.js";
import { NotificationCard } from "../../components/menu/index.js";
+import { getKeyFiguresData } from "../../hooks/finance.js";
import { Notification } from "../../utils/types.js";
import { ListPage } from "./ListPage.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
-import { getKeyFiguresData } from "../../hooks/finance.js";
-
interface Props {
onUnauthorized: () => VNode;
@@ -42,13 +38,12 @@ interface Props {
}
export default function FinanceDashboard({
- onUnauthorized,
- // onLoadError,
- onCreate,
- onSelect,
- onNotFound,
- }: Props): VNode {
-
+ onUnauthorized,
+ // onLoadError,
+ onCreate,
+ onSelect,
+ onNotFound,
+}: Props): VNode {
const result = getKeyFiguresData();
const [notif, setNotif] = useState<Notification | undefined>(undefined);
@@ -67,14 +62,13 @@ export default function FinanceDashboard({
result.status === HttpStatusCode.NotFound
)
return onNotFound();
- else
- return onNotFound();
+ else return onNotFound();
}
return (
<section class="section is-main-section">
<NotificationCard notification={notif} />
- <ListPage data={result} />
+ <ListPage data={result} />
</section>
);
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/login/index.tsx b/packages/auditor-backoffice-ui/src/paths/login/index.tsx
index c99dc6050..16fb18fdf 100644
--- a/packages/auditor-backoffice-ui/src/paths/login/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/login/index.tsx
@@ -22,106 +22,102 @@
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { useCallback, useState } from "preact/hooks";
-import { useBackendContext, useBackendTokenContext } from "../../context/backend.js";
+import { Route } from "preact-router";
+import { useCallback, useState } from "preact/hooks";
import { NotificationCard } from "../../components/menu/index.js";
-import { Notification } from "../../utils/types.js";
+import { useBackendTokenContext } from "../../context/backend.js";
import { useBackendToken } from "../../hooks/backend.js";
-import { Route } from "preact-router";
import { Paths, Redirect } from "../../InstanceRoutes.js";
+import { Notification } from "../../utils/types.js";
export function LoginPage(): VNode {
const [token, setToken] = useState("");
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
- const doLogin = useCallback(async function doLoginImpl() {
-
- const result = useBackendToken();
- if (!result.ok) {
- }
- if (result.ok) {
- //TODO fixme
- const { token } = useBackendTokenContext();
- /* return (
+ const doLogin = useCallback(
+ async function doLoginImpl() {
+ const result = useBackendToken();
+ if (!result.ok) {
+ }
+ if (result.ok) {
+ //TODO fixme
+ const { token } = useBackendTokenContext();
+ /* return (
<Route path="/" component={Redirect} to={Paths.key_figures}/>
);*/
- } else {
- setNotif({
- message: "Your password is incorrect",
- type: "ERROR",
- });
- }
- }, [token]);
-
- return (
- <Route path="/" component={Redirect} to={Paths.key_figures}/>
+ } else {
+ setNotif({
+ message: "Your password is incorrect",
+ type: "ERROR",
+ });
+ }
+ },
+ [token],
);
+ return <Route path="/" component={Redirect} to={Paths.key_figures} />;
+
return (
<div class="columns is-centered" style={{ margin: "auto" }}>
- <div class="column is-two-thirds ">
- <div class="modal-card" style={{ width: "100%", margin: 0 }}>
- <header
- class="modal-card-head"
- style={{ border: "1px solid", borderBottom: 0 }}
- >
- <p class="modal-card-title">{i18n.str`Token required`}</p>
- </header>
- <section
- class="modal-card-body"
- style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
- >
-
- <p>
- <i18n.Translate>Need the access token for the API.</i18n.Translate>
- </p>
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label">
- <i18n.Translate>Access Token</i18n.Translate>
- </label>
- </div>
- <div class="field-body">
- <div class="field">
- <p class="control is-expanded">
- <input
- class="input"
- type="password"
- placeholder={"current access token"}
- name="token"
- onKeyPress={(e) =>
- e.keyCode === 13
- ? doLogin()
- : null
- }
- value={token}
- onInput={(e): void => setToken(e?.currentTarget.value)}
- />
- </p>
+ <div class="column is-two-thirds ">
+ <div class="modal-card" style={{ width: "100%", margin: 0 }}>
+ <header
+ class="modal-card-head"
+ style={{ border: "1px solid", borderBottom: 0 }}
+ >
+ <p class="modal-card-title">{i18n.str`Token required`}</p>
+ </header>
+ <section
+ class="modal-card-body"
+ style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
+ >
+ <p>
+ <i18n.Translate>
+ Need the access token for the API.
+ </i18n.Translate>
+ </p>
+ <div class="field is-horizontal">
+ <div class="field-label is-normal">
+ <label class="label">
+ <i18n.Translate>Access Token</i18n.Translate>
+ </label>
+ </div>
+ <div class="field-body">
+ <div class="field">
+ <p class="control is-expanded">
+ <input
+ class="input"
+ type="password"
+ placeholder={"current access token"}
+ name="token"
+ onKeyPress={(e) => (e.keyCode === 13 ? doLogin() : null)}
+ value={token}
+ onInput={(e): void => setToken(e?.currentTarget.value)}
+ />
+ </p>
+ </div>
</div>
</div>
- </div>
- </section>
- <footer
- class="modal-card-foot "
- style={{
- justifyContent: "flex-end",
- border: "1px solid",
- borderTop: 0,
- }}
- >
- <AsyncButton
- onClick={() => doLogin()}
+ </section>
+ <footer
+ class="modal-card-foot "
+ style={{
+ justifyContent: "flex-end",
+ border: "1px solid",
+ borderTop: 0,
+ }}
>
- <i18n.Translate>Confirm</i18n.Translate>
- </AsyncButton>
- </footer>
+ <AsyncButton onClick={() => doLogin()}>
+ <i18n.Translate>Confirm</i18n.Translate>
+ </AsyncButton>
+ </footer>
+ </div>
</div>
</div>
- </div>);
-
+ );
- return (<Fragment>
+ return (
+ <Fragment>
<NotificationCard notification={notif} />
<div class="columns is-centered" style={{ margin: "auto" }}>
<div class="column is-two-thirds ">
@@ -145,7 +141,6 @@ export function LoginPage(): VNode {
</label>
</div>
<div class="field-body">
-
<div class="field">
<p class="control is-expanded">
<input
@@ -154,9 +149,7 @@ export function LoginPage(): VNode {
placeholder={"current access token"}
name="token"
onKeyPress={(e) =>
- e.keyCode === 13
- ? doLogin()
- : null
+ e.keyCode === 13 ? doLogin() : null
}
value={token}
onInput={(e): void => setToken(e?.currentTarget.value)}
@@ -175,39 +168,45 @@ export function LoginPage(): VNode {
}}
>
<div />
- <AsyncButton
- type="is-info"
- onClick={doLogin}
- >
+ <AsyncButton type="is-info" onClick={doLogin}>
<i18n.Translate>Confirm</i18n.Translate>
</AsyncButton>
-
</footer>
</div>
</div>
</div>
</Fragment>
-
);
}
-function AsyncButton({ onClick, disabled, type = "", children }: {
- type?: string,
- disabled?: boolean,
- onClick: () => Promise<void>,
- children: ComponentChildren
+function AsyncButton({
+ onClick,
+ disabled,
+ type = "",
+ children,
+}: {
+ type?: string;
+ disabled?: boolean;
+ onClick: () => Promise<void>;
+ children: ComponentChildren;
}): VNode {
const [running, setRunning] = useState(false);
- return <button class={"button " + type} disabled={disabled || running} onClick={() => {
- setRunning(true);
- onClick().then(() => {
- setRunning(false);
- }).catch(() => {
- setRunning(false);
- });
- }}>
- {children}
- </button>;
+ return (
+ <button
+ class={"button " + type}
+ disabled={disabled || running}
+ onClick={() => {
+ setRunning(true);
+ onClick()
+ .then(() => {
+ setRunning(false);
+ })
+ .catch(() => {
+ setRunning(false);
+ });
+ }}
+ >
+ {children}
+ </button>
+ );
}
-
-
diff --git a/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx b/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx
index 114b95219..68adb79bf 100644
--- a/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx
@@ -23,12 +23,12 @@ import { h, VNode } from "preact";
import { Link } from "preact-router";
export default function NotFoundPage(): VNode {
- return (
- <div>
- <p>That page doesn&apos;t exist.</p>
- <Link href="/">
- <h4>Back to Home</h4>
- </Link>
- </div>
- );
+ return (
+ <div>
+ <p>That page doesn&apos;t exist.</p>
+ <Link href="/">
+ <h4>Back to Home</h4>
+ </Link>
+ </div>
+ );
}
diff --git a/packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx b/packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx
index 7f0579b2b..3b26ff071 100644
--- a/packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx
@@ -20,12 +20,12 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode, Fragment } from "preact";
+/**
+ * Imports.
+ */
+import { Fragment, h, VNode } from "preact";
export function ListPage(data: any): VNode {
- const { i18n } = useTranslationContext();
-
return (
<Fragment>
<div class="columns is-fullwidth">
@@ -34,33 +34,54 @@ export function ListPage(data: any): VNode {
<div class="card-content">
<table class="table is-striped is-fullwidth">
<tbody>
- <tr>
- <th>Finding</th>
- <td class="has-text-right"><b>Count</b></td>
- <td class="has-text-right"><b>Time difference (s)</b></td>
- <td class="has-text-right"><b>Diagnostic</b></td>
- </tr>
- {
- data["data"]["data"][0].map((x: any) => {
+ <tr>
+ <th>Finding</th>
+ <td class="has-text-right">
+ <b>Count</b>
+ </td>
+ <td class="has-text-right">
+ <b>Time difference (s)</b>
+ </td>
+ <td class="has-text-right">
+ <b>Diagnostic</b>
+ </td>
+ </tr>
+ {data["data"]["data"][0].map((x: any) => {
const key = Object.keys(x.data)[0];
let value = Object.values(x.data)[0];
console.log(value);
- if (!!value)
- value = 0;
- const paramName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+ if (!!value) value = 0;
+ const paramName =
+ key[0].toUpperCase() +
+ key
+ .split("_")
+ .join(" ")
+ .split("-")
+ .join(" ")
+ .slice(1, key.length);
return (
<tr class="is-link">
<td>{paramName}</td>
- <td className="has-text-right"><p
- class={value == 0 ? "text-success" : "text-danger"}>{String(value)}</p></td>
- <td className="has-text-right">{//TODO
- }</td>
- <td>{//TODO
- }</td>
+ <td className="has-text-right">
+ <p
+ class={value == 0 ? "text-success" : "text-danger"}
+ >
+ {String(value)}
+ </p>
+ </td>
+ <td className="has-text-right">
+ {
+ //TODO
+ }
+ </td>
+ <td>
+ {
+ //TODO
+ }
+ </td>
</tr>
);
- })
- }
+ })}
</tbody>
</table>
</div>
@@ -69,4 +90,4 @@ export function ListPage(data: any): VNode {
</div>
</Fragment>
);
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/operations/index.tsx b/packages/auditor-backoffice-ui/src/paths/operations/index.tsx
index c05b271fe..da8374b20 100644
--- a/packages/auditor-backoffice-ui/src/paths/operations/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/operations/index.tsx
@@ -20,19 +20,15 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import {
- ErrorType,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ErrorType, useTranslationContext } from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../components/exception/loading.js";
import { NotificationCard } from "../../components/menu/index.js";
+import { getOperationData } from "../../hooks/operational.js";
import { Notification } from "../../utils/types.js";
import { ListPage } from "./ListPage.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
-import { getOperationData } from "../../hooks/operational.js";
-
interface Props {
onUnauthorized: () => VNode;
@@ -42,13 +38,12 @@ interface Props {
}
export default function OperationsDashboard({
- onUnauthorized,
- // onLoadError,
- onCreate,
- onSelect,
- onNotFound,
- }: Props): VNode {
-
+ onUnauthorized,
+ // onLoadError,
+ onCreate,
+ onSelect,
+ onNotFound,
+}: Props): VNode {
const result = getOperationData();
const [notif, setNotif] = useState<Notification | undefined>(undefined);
@@ -67,14 +62,13 @@ export default function OperationsDashboard({
result.status === HttpStatusCode.NotFound
)
return onNotFound();
- else
- return onNotFound();
+ else return onNotFound();
}
return (
<section class="section is-main-section">
<NotificationCard notification={notif} />
- <ListPage data={result} />
+ <ListPage data={result} />
</section>
);
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx b/packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx
index 74f83bd4a..4408dd7f6 100644
--- a/packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx
@@ -21,7 +21,7 @@
*/
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode, Fragment } from "preact";
+import { Fragment, h, VNode } from "preact";
export function ListPage(data: any): VNode {
const { i18n } = useTranslationContext();
@@ -34,31 +34,46 @@ export function ListPage(data: any): VNode {
<div class="card-content">
<table class="table is-striped is-fullwidth">
<tbody>
- <tr>
- <th>Finding</th>
- <td class="has-text-right"><b>Count</b></td>
- <td class="has-text-right"><b>Expiration dates</b></td>
- </tr>
- {
- data["data"]["data"][0].map((x: any) => {
+ <tr>
+ <th>Finding</th>
+ <td class="has-text-right">
+ <b>Count</b>
+ </td>
+ <td class="has-text-right">
+ <b>Expiration dates</b>
+ </td>
+ </tr>
+ {data["data"]["data"][0].map((x: any) => {
const key = Object.keys(x.data)[0];
let value = Object.values(x.data)[0];
console.log(value);
- if (!!value)
- value = 0;
- const paramName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+ if (!!value) value = 0;
+ const paramName =
+ key[0].toUpperCase() +
+ key
+ .split("_")
+ .join(" ")
+ .split("-")
+ .join(" ")
+ .slice(1, key.length);
return (
<tr class="is-link">
<td>{paramName}</td>
- <td class="has-text-right"><p
- class={value == 0 ? "text-success" : "text-danger"}>{String(value)}</p></td>
- <td class="has-text-right">{
- //TODO
- }</td>
+ <td class="has-text-right">
+ <p
+ class={value == 0 ? "text-success" : "text-danger"}
+ >
+ {String(value)}
+ </p>
+ </td>
+ <td class="has-text-right">
+ {
+ //TODO
+ }
+ </td>
</tr>
);
- })
- }
+ })}
</tbody>
</table>
</div>
diff --git a/packages/auditor-backoffice-ui/src/paths/security/index.tsx b/packages/auditor-backoffice-ui/src/paths/security/index.tsx
index 99c98a5e7..873494352 100644
--- a/packages/auditor-backoffice-ui/src/paths/security/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/security/index.tsx
@@ -20,18 +20,19 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import {
- ErrorType,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
+/**
+ * Imports.
+ */
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ErrorType, useTranslationContext } from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import { useState } from "preact/hooks";
import { Loading } from "../../components/exception/loading.js";
import { NotificationCard } from "../../components/menu/index.js";
+import { getCriticalData } from "../../hooks/critical.js";
import { Notification } from "../../utils/types.js";
import { ListPage } from "./ListPage.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
-import { getCriticalData } from "../../hooks/critical.js";
+
interface Props {
onUnauthorized: () => VNode;
onNotFound: () => VNode;
@@ -40,13 +41,12 @@ interface Props {
}
export default function SecurityDashboard({
- onUnauthorized,
- // onLoadError,
- onCreate,
- onSelect,
- onNotFound,
- }: Props): VNode {
-
+ onUnauthorized,
+ // onLoadError,
+ onCreate,
+ onSelect,
+ onNotFound,
+}: Props): VNode {
const result = getCriticalData();
const [notif, setNotif] = useState<Notification | undefined>(undefined);
@@ -65,14 +65,13 @@ export default function SecurityDashboard({
result.status === HttpStatusCode.NotFound
)
return onNotFound();
- else
- return onNotFound();
+ else return onNotFound();
}
return (
<section class="section is-main-section">
<NotificationCard notification={notif} />
- <ListPage data={result} />
+ <ListPage data={result} />
</section>
);
-} \ No newline at end of file
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/settings/index.tsx b/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
index 77a56a794..3d07f4cf8 100644
--- a/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
@@ -20,9 +20,15 @@
* @author Nic Eigel
*/
+/**
+ * Imports.
+ */
import { useLang, useTranslationContext } from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
-import { FormErrors, FormProvider } from "../../components/forms/FormProvider.js";
+import {
+ FormErrors,
+ FormProvider,
+} from "../../components/forms/FormProvider.js";
import { LangSelector } from "../../components/menu/LangSelector.js";
import { Settings, useSettings } from "../../hooks/useSettings.js";
@@ -34,74 +40,78 @@ function getBrowserLang(): string | undefined {
}
export function Settings({ onClose }: { onClose?: () => void }): VNode {
- const { i18n } = useTranslationContext()
- const borwserLang = getBrowserLang()
- const { update } = useLang(undefined, {})
+ const { i18n } = useTranslationContext();
+ const borwserLang = getBrowserLang();
+ const { update } = useLang(undefined, {});
- const [value, updateValue] = useSettings()
- const errors: FormErrors<Settings> = {
- }
+ const [value, updateValue] = useSettings();
+ const errors: FormErrors<Settings> = {};
function valueHandler(s: (d: Partial<Settings>) => Partial<Settings>): void {
- const next = s(value)
+ const next = s(value);
const v: Settings = {
advanceOrderMode: next.advanceOrderMode ?? false,
- dateFormat: next.dateFormat ?? "ymd"
- }
- updateValue(v)
+ dateFormat: next.dateFormat ?? "ymd",
+ };
+ updateValue(v);
}
- return <div>
- <section class="section is-main-section">
- <div class="columns">
- <div class="column" />
- <div class="column is-four-fifths">
- <div>
-
- <FormProvider<Settings>
- name="settings"
- errors={errors}
- object={value}
- valueHandler={valueHandler}
- >
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label">
- <i18n.Translate>Language</i18n.Translate>
- <span class="icon has-tooltip-right" data-tooltip={"Force language setting instance of taking the browser"}>
- <i class="mdi mdi-information" />
- </span>
- </label>
- </div>
- <div class="field field-body has-addons is-flex-grow-3">
- <LangSelector />
- &nbsp;
- {borwserLang !== undefined && <button
- data-tooltip={i18n.str`generate random secret key`}
- class="button is-info mr-2"
- onClick={(e) => {
- update(borwserLang.substring(0, 2))
- }}
- >
- <i18n.Translate>Set default</i18n.Translate>
- </button>}
+ return (
+ <div>
+ <section class="section is-main-section">
+ <div class="columns">
+ <div class="column" />
+ <div class="column is-four-fifths">
+ <div>
+ <FormProvider<Settings>
+ name="settings"
+ errors={errors}
+ object={value}
+ valueHandler={valueHandler}
+ >
+ <div class="field is-horizontal">
+ <div class="field-label is-normal">
+ <label class="label">
+ <i18n.Translate>Language</i18n.Translate>
+ <span
+ class="icon has-tooltip-right"
+ data-tooltip={
+ "Force language setting instance of taking the browser"
+ }
+ >
+ <i class="mdi mdi-information" />
+ </span>
+ </label>
+ </div>
+ <div class="field field-body has-addons is-flex-grow-3">
+ <LangSelector />
+ &nbsp;
+ {borwserLang !== undefined && (
+ <button
+ data-tooltip={i18n.str`generate random secret key`}
+ class="button is-info mr-2"
+ onClick={(e) => {
+ update(borwserLang.substring(0, 2));
+ }}
+ >
+ <i18n.Translate>Set default</i18n.Translate>
+ </button>
+ )}
+ </div>
</div>
- </div>
- </FormProvider>
+ </FormProvider>
+ </div>
</div>
+ <div class="column" />
</div>
- <div class="column" />
- </div>
- </section >
- {onClose &&
- <section class="section is-main-section">
- <button
- class="button"
- onClick={onClose}
- >
- <i18n.Translate>Close</i18n.Translate>
- </button>
</section>
- }
- </div >
-} \ No newline at end of file
+ {onClose && (
+ <section class="section is-main-section">
+ <button class="button" onClick={onClose}>
+ <i18n.Translate>Close</i18n.Translate>
+ </button>
+ </section>
+ )}
+ </div>
+ );
+}
diff --git a/packages/auditor-backoffice-ui/src/schemas/index.ts b/packages/auditor-backoffice-ui/src/schemas/index.ts
deleted file mode 100644
index 380466e13..000000000
--- a/packages/auditor-backoffice-ui/src/schemas/index.ts
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { isAfter, isFuture } from "date-fns";
-import * as yup from "yup";
-import { AMOUNT_REGEX, PAYTO_REGEX } from "../utils/constants.js";
-import { Amounts } from "@gnu-taler/taler-util";
-
-yup.setLocale({
- mixed: {
- default: "field_invalid",
- },
- number: {
- min: ({ min }: any) => ({ key: "field_too_short", values: { min } }),
- max: ({ max }: any) => ({ key: "field_too_big", values: { max } }),
- },
-});
-
-function listOfPayToUrisAreValid(values?: (string | undefined)[]): boolean {
- return !!values && values.every((v) => v && PAYTO_REGEX.test(v));
-}
-
-function currencyWithAmountIsValid(value?: string): boolean {
- return !!value && Amounts.parse(value) !== undefined;
-}
-function currencyGreaterThan0(value?: string) {
- if (value) {
- try {
- const [, amount] = value.split(":");
- const intAmount = parseInt(amount, 10);
- return intAmount > 0;
- } catch {
- return false;
- }
- }
- return true;
-}
-
-export const InstanceSchema = yup.object().shape({
- id: yup.string().required().meta({ type: "url" }),
- name: yup.string().required(),
- auth: yup.object().shape({
- method: yup.string().matches(/^(external|token)$/),
- token: yup.string().optional().nullable(),
- }),
- payto_uris: yup
- .array()
- .of(yup.string())
- .min(1)
- .meta({ type: "array" })
- .test("payto", "{path} is not valid", listOfPayToUrisAreValid),
- default_max_deposit_fee: yup
- .string()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid)
- .meta({ type: "amount" }),
- default_max_wire_fee: yup
- .string()
- .required()
- .test("amount", "{path} is not valid", currencyWithAmountIsValid)
- .meta({ type: "amount" }),
- default_wire_fee_amortization: yup.number().required(),
- address: yup
- .object()
- .shape({
- country: yup.string().optional(),
- address_lines: yup.array().of(yup.string()).max(7).optional(),
- building_number: yup.string().optional(),
- building_name: yup.string().optional(),
- street: yup.string().optional(),
- post_code: yup.string().optional(),
- town_location: yup.string().optional(),
- town: yup.string(),
- district: yup.string().optional(),
- country_subdivision: yup.string().optional(),
- })
- .meta({ type: "group" }),
- jurisdiction: yup
- .object()
- .shape({
- country: yup.string().optional(),
- address_lines: yup.array().of(yup.string()).max(7).optional(),
- building_number: yup.string().optional(),
- building_name: yup.string().optional(),
- street: yup.string().optional(),
- post_code: yup.string().optional(),
- town_location: yup.string().optional(),
- town: yup.string(),
- district: yup.string().optional(),
- country_subdivision: yup.string().optional(),
- })
- .meta({ type: "group" }),
- // default_pay_delay: yup.object()
- // .shape({ d_us: yup.number() })
- // .required()
- // .meta({ type: 'duration' }),
- // .transform(numberToDuration),
- default_wire_transfer_delay: yup
- .object()
- .shape({ d_us: yup.number() })
- .required()
- .meta({ type: "duration" }),
- // .transform(numberToDuration),
-});
-
-export const InstanceUpdateSchema = InstanceSchema.clone().omit(["id"]);
-export const InstanceCreateSchema = InstanceSchema.clone();
-
-export const AuthorizeRewardSchema = yup.object().shape({
- justification: yup.string().required(),
- amount: yup
- .string()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid)
- .test("amount_positive", "the amount is not valid", currencyGreaterThan0),
- next_url: yup.string().required(),
-});
-
-const stringIsValidJSON = (value?: string) => {
- const p = value?.trim();
- if (!p) return true;
- try {
- JSON.parse(p);
- return true;
- } catch {
- return false;
- }
-};
-
-export const OrderCreateSchema = yup.object().shape({
- pricing: yup
- .object()
- .required()
- .shape({
- summary: yup.string().ensure().required(),
- order_price: yup
- .string()
- .ensure()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid)
- .test(
- "amount_positive",
- "the amount should be greater than 0",
- currencyGreaterThan0,
- ),
- }),
- // extra: yup.object().test("extra", "is not a JSON format", stringIsValidJSON),
- payments: yup
- .object()
- .required()
- .shape({
- refund_deadline: yup
- .date()
- .test("future", "should be in the future", (d) =>
- d ? isFuture(d) : true,
- ),
- pay_deadline: yup
- .date()
- .test("future", "should be in the future", (d) =>
- d ? isFuture(d) : true,
- ),
- auto_refund_deadline: yup
- .date()
- .test("future", "should be in the future", (d) =>
- d ? isFuture(d) : true,
- ),
- delivery_date: yup
- .date()
- .test("future", "should be in the future", (d) =>
- d ? isFuture(d) : true,
- ),
- })
- .test("payment", "dates", (d) => {
- if (
- d.pay_deadline &&
- d.refund_deadline &&
- isAfter(d.refund_deadline, d.pay_deadline)
- ) {
- return new yup.ValidationError(
- "pay deadline should be greater than refund",
- "asd",
- "payments.pay_deadline",
- );
- }
- return true;
- }),
-});
-
-export const ProductCreateSchema = yup.object().shape({
- product_id: yup.string().ensure().required(),
- description: yup.string().required(),
- unit: yup.string().ensure().required(),
- price: yup
- .string()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid),
- stock: yup.object({}).optional(),
- minimum_age: yup.number().optional().min(0),
-});
-
-export const ProductUpdateSchema = yup.object().shape({
- description: yup.string().required(),
- price: yup
- .string()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid),
- stock: yup.object({}).optional(),
- minimum_age: yup.number().optional().min(0),
-});
-
-export const TaxSchema = yup.object().shape({
- name: yup.string().required().ensure(),
- tax: yup
- .string()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid),
-});
-
-export const NonInventoryProductSchema = yup.object().shape({
- quantity: yup.number().required().positive(),
- description: yup.string().required(),
- unit: yup.string().ensure().required(),
- price: yup
- .string()
- .required()
- .test("amount", "the amount is not valid", currencyWithAmountIsValid),
-});
diff --git a/packages/auditor-backoffice-ui/src/scss/_aside.scss b/packages/auditor-backoffice-ui/src/scss/_aside.scss
index b7b59516b..719da7d2c 100644
--- a/packages/auditor-backoffice-ui/src/scss/_aside.scss
+++ b/packages/auditor-backoffice-ui/src/scss/_aside.scss
@@ -130,7 +130,11 @@ aside.aside {
@include touch {
nav.navbar {
- @include transition(margin-left);
+ // @include transition(margin-left);
+ // TODO: adapt above transition mixin to work with multiple transitions
+ transition:
+ margin-left 250ms ease-in-out 50ms,
+ width 250ms ease-in-out 50ms;
}
aside.aside {
@include transition(left);
@@ -173,6 +177,7 @@ aside.aside {
div.has-aside-mobile-expanded {
nav.navbar {
margin-left: $aside-mobile-width;
+ width: calc(100vw - $aside-mobile-width);
}
aside.aside {
left: 0;
diff --git a/packages/auditor-backoffice-ui/src/utils/amount.ts b/packages/auditor-backoffice-ui/src/utils/amount.ts
deleted file mode 100644
index 0796087ac..000000000
--- a/packages/auditor-backoffice-ui/src/utils/amount.ts
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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/>
- *//*
-import {
- amountFractionalBase,
- AmountJson,
- Amounts,
-} from "@gnu-taler/taler-util";
-import { AuditorBackend } from "../declaration.js";
-
-/**
- * merge refund with the same description and a difference less than one minute
- * @param prev list of refunds that will hold the merged refunds
- * @param cur new refund to add to the list
- * @returns list with the new refund, may be merged with the last
- */
-/*export function mergeRefunds(
- prev: MerchantBackend.Orders.RefundDetails[],
- cur: MerchantBackend.Orders.RefundDetails,
-): MerchantBackend.Orders.RefundDetails[] {
- let tail;
-
- if (
- prev.length === 0 || //empty list
- cur.timestamp.t_s === "never" || //current does not have timestamp
- (tail = prev[prev.length - 1]).timestamp.t_s === "never" || // last does not have timestamp
- cur.reason !== tail.reason || //different reason
- cur.pending !== tail.pending || //different pending state
- Math.abs(cur.timestamp.t_s - tail.timestamp.t_s) > 1000 * 60
- ) {
- //more than 1 minute difference
-
- //can't merge refunds, they are different or to distant in time
- prev.push(cur);
- return prev;
- }
-
- const a = Amounts.parseOrThrow(tail.amount);
- const b = Amounts.parseOrThrow(cur.amount);
- const r = Amounts.add(a, b).amount;
-
- prev[prev.length - 1] = {
- ...tail,
- amount: Amounts.stringify(r),
- };
-
- return prev;
-}
-
-export function rate(a: AmountJson, b: AmountJson): number {
- const af = toFloat(a);
- const bf = toFloat(b);
- if (bf === 0) return 0;
- return af / bf;
-}
-
-function toFloat(amount: AmountJson): number {
- return amount.value + amount.fraction / amountFractionalBase;
-}
-*/ \ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/utils/constants.ts b/packages/auditor-backoffice-ui/src/utils/constants.ts
deleted file mode 100644
index e8db927c4..000000000
--- a/packages/auditor-backoffice-ui/src/utils/constants.ts
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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)
- */
-
-//https://tools.ietf.org/html/rfc8905
-export const PAYTO_REGEX =
- /^payto:\/\/[a-zA-Z][a-zA-Z0-9-.]+(\/[a-zA-Z0-9\-\.\~\(\)@_%:!$&'*+,;=]*)*\??((amount|receiver-name|sender-name|instruction|message)=[a-zA-Z0-9\-\.\~\(\)@_%:!$'*+,;=]*&?)*$/;
-export const PAYTO_WIRE_METHOD_LOOKUP =
- /payto:\/\/([a-zA-Z][a-zA-Z0-9-.]+)\/.*/;
-
-export const AMOUNT_REGEX = /^[a-zA-Z][a-zA-Z]{1,11}:[0-9][0-9,]*\.?[0-9,]*$/;
-
-export const INSTANCE_ID_LOOKUP = /\/instances\/([^/]*)\/?$/;
-
-export const AMOUNT_ZERO_REGEX = /^[a-zA-Z][a-zA-Z]*:0$/;
-
-export const CROCKFORD_BASE32_REGEX =
- /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]+[*~$=U]*$/;
-
-export const URL_REGEX =
- /^((https?:)(\/\/\/?)([\w]*(?::[\w]*)?@)?([\d\w\.-]+)(?::(\d+))?)\/$/;
-
-// how much rows we add every time user hit load more
-export const PAGE_SIZE = 20;
-// how bigger can be the result set
-// after this threshold, load more with move the cursor
-export const MAX_RESULT_SIZE = PAGE_SIZE * 2 - 1;
-
-// how much we will wait for all request, in seconds
-export const DEFAULT_REQUEST_TIMEOUT = 10;
-
-export const MAX_IMAGE_SIZE = 1024 * 1024;
-
-export const INSTANCE_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_.@-]+$/;
-
-export const COUNTRY_TABLE = {
- AE: "U.A.E.",
- AF: "Afghanistan",
- AL: "Albania",
- AM: "Armenia",
- AN: "Netherlands Antilles",
- AR: "Argentina",
- AT: "Austria",
- AU: "Australia",
- AZ: "Azerbaijan",
- BA: "Bosnia and Herzegovina",
- BD: "Bangladesh",
- BE: "Belgium",
- BG: "Bulgaria",
- BH: "Bahrain",
- BN: "Brunei Darussalam",
- BO: "Bolivia",
- BR: "Brazil",
- BT: "Bhutan",
- BY: "Belarus",
- BZ: "Belize",
- CA: "Canada",
- CG: "Congo",
- CH: "Switzerland",
- CI: "Cote d'Ivoire",
- CL: "Chile",
- CM: "Cameroon",
- CN: "People's Republic of China",
- CO: "Colombia",
- CR: "Costa Rica",
- CS: "Serbia and Montenegro",
- CZ: "Czech Republic",
- DE: "Germany",
- DK: "Denmark",
- DO: "Dominican Republic",
- DZ: "Algeria",
- EC: "Ecuador",
- EE: "Estonia",
- EG: "Egypt",
- ER: "Eritrea",
- ES: "Spain",
- ET: "Ethiopia",
- FI: "Finland",
- FO: "Faroe Islands",
- FR: "France",
- GB: "United Kingdom",
- GD: "Caribbean",
- GE: "Georgia",
- GL: "Greenland",
- GR: "Greece",
- GT: "Guatemala",
- HK: "Hong Kong",
- // HK: "Hong Kong S.A.R.",
- HN: "Honduras",
- HR: "Croatia",
- HT: "Haiti",
- HU: "Hungary",
- ID: "Indonesia",
- IE: "Ireland",
- IL: "Israel",
- IN: "India",
- IQ: "Iraq",
- IR: "Iran",
- IS: "Iceland",
- IT: "Italy",
- JM: "Jamaica",
- JO: "Jordan",
- JP: "Japan",
- KE: "Kenya",
- KG: "Kyrgyzstan",
- KH: "Cambodia",
- KR: "South Korea",
- KW: "Kuwait",
- KZ: "Kazakhstan",
- LA: "Laos",
- LB: "Lebanon",
- LI: "Liechtenstein",
- LK: "Sri Lanka",
- LT: "Lithuania",
- LU: "Luxembourg",
- LV: "Latvia",
- LY: "Libya",
- MA: "Morocco",
- MC: "Principality of Monaco",
- MD: "Moldava",
- // MD: "Moldova",
- ME: "Montenegro",
- MK: "Former Yugoslav Republic of Macedonia",
- ML: "Mali",
- MM: "Myanmar",
- MN: "Mongolia",
- MO: "Macau S.A.R.",
- MT: "Malta",
- MV: "Maldives",
- MX: "Mexico",
- MY: "Malaysia",
- NG: "Nigeria",
- NI: "Nicaragua",
- NL: "Netherlands",
- NO: "Norway",
- NP: "Nepal",
- NZ: "New Zealand",
- OM: "Oman",
- PA: "Panama",
- PE: "Peru",
- PH: "Philippines",
- PK: "Islamic Republic of Pakistan",
- PL: "Poland",
- PR: "Puerto Rico",
- PT: "Portugal",
- PY: "Paraguay",
- QA: "Qatar",
- RE: "Reunion",
- RO: "Romania",
- RS: "Serbia",
- RU: "Russia",
- RW: "Rwanda",
- SA: "Saudi Arabia",
- SE: "Sweden",
- SG: "Singapore",
- SI: "Slovenia",
- SK: "Slovak",
- SN: "Senegal",
- SO: "Somalia",
- SR: "Suriname",
- SV: "El Salvador",
- SY: "Syria",
- TH: "Thailand",
- TJ: "Tajikistan",
- TM: "Turkmenistan",
- TN: "Tunisia",
- TR: "Turkey",
- TT: "Trinidad and Tobago",
- TW: "Taiwan",
- TZ: "Tanzania",
- UA: "Ukraine",
- US: "United States",
- UY: "Uruguay",
- VA: "Vatican",
- VE: "Venezuela",
- VN: "Viet Nam",
- YE: "Yemen",
- ZA: "South Africa",
- ZW: "Zimbabwe",
-};
diff --git a/packages/auditor-backoffice-ui/src/utils/regex.test.ts b/packages/auditor-backoffice-ui/src/utils/regex.test.ts
deleted file mode 100644
index 78f2ef5ae..000000000
--- a/packages/auditor-backoffice-ui/src/utils/regex.test.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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 { expect } from "chai";
-import { AMOUNT_REGEX, PAYTO_REGEX } from "./constants.js";
-
-describe("payto uri format", () => {
- const valids = [
- "payto://iban/DE75512108001245126199?amount=EUR:200.0&message=hello",
- "payto://ach/122000661/1234",
- "payto://upi/alice@example.com?receiver-name=Alice&amount=INR:200",
- "payto://void/?amount=EUR:10.5",
- "payto://ilp/g.acme.bob",
- ];
-
- it("should be valid", () => {
- valids.forEach((v) => expect(v).match(PAYTO_REGEX));
- });
-
- const invalids = [
- // has two question marks
- "payto://iban/DE75?512108001245126199?amount=EUR:200.0&message=hello",
- // has a space
- "payto://ach /122000661/1234",
- // has a space
- "payto://upi/alice@ example.com?receiver-name=Alice&amount=INR:200",
- // invalid field name (mount instead of amount)
- "payto://void/?mount=EUR:10.5",
- // payto:// is incomplete
- "payto: //ilp/g.acme.bob",
- ];
-
- it("should not be valid", () => {
- invalids.forEach((v) => expect(v).not.match(PAYTO_REGEX));
- });
-});
-
-describe("amount format", () => {
- const valids = [
- "ARS:10",
- "COL:10.2",
- "UY:1,000.2",
- "ARS:10.123,123",
- "ARS:1,000,000",
- "ARSCOL:10",
- "LONGESTCURR:1,000,000.123,123",
- ];
-
-
- it("should be valid", () => {
- valids.forEach((v) => expect(v).match(AMOUNT_REGEX));
- });
-
- const invalids = [
- //no currency name
- ":10",
- //use . instead of ,
- "ARS:1.000.000",
- //currency name with numbers
- "1ARS:10",
- //currency name with numbers
- "AR5:10",
- //missing value
- "USD:",
- ];
-
- it("should not be valid", () => {
- invalids.forEach((v) => expect(v).not.match(AMOUNT_REGEX));
- });
-});
diff --git a/packages/auditor-backoffice-ui/src/utils/table.ts b/packages/auditor-backoffice-ui/src/utils/table.ts
deleted file mode 100644
index 1322ad804..000000000
--- a/packages/auditor-backoffice-ui/src/utils/table.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021-2024 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/>
- */
-/*
-import { WithId } from "../declaration.js";
-*/
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
-/*
-export interface Actions<T extends WithId> {
- element: T;
- type: "DELETE" | "UPDATE";
-}
-
-function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
- return value !== null && value !== undefined;
-}
-
-export function buildActions<T extends WithId>(
- instances: T[],
- selected: string[],
- action: "DELETE",
-): Actions<T>[] {
- return selected
- .map((id) => instances.find((i) => i.id === id))
- .filter(notEmpty)
- .map((id) => ({ element: id, type: action }));
-}
-*/
-/**
- * For any object or array, return the same object if is not empty.
- * not empty:
- * - for arrays: at least one element not undefined
- * - for objects: at least one property not undefined
- * @param obj
- * @returns
- *//*
-export function undefinedIfEmpty<
- T extends Record<string, unknown> | Array<unknown>,
->(obj: T | undefined): T | undefined {
- if (obj === undefined) return undefined;
- return Object.values(obj).some((v) => v !== undefined) ? obj : undefined;
-}*/
diff --git a/packages/auditor-backoffice-ui/src/utils/types.ts b/packages/auditor-backoffice-ui/src/utils/types.ts
index f96606a16..de26cd82e 100644
--- a/packages/auditor-backoffice-ui/src/utils/types.ts
+++ b/packages/auditor-backoffice-ui/src/utils/types.ts
@@ -14,12 +14,11 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
+/**
+ * Imports.
+ */
import { VNode } from "preact";
-export interface KeyValue {
- [key: string]: string;
-}
-
export interface Notification {
message: string;
description?: string | VNode;