aboutsummaryrefslogtreecommitdiff
path: root/packages/auditor-backoffice-ui/src/paths
diff options
context:
space:
mode:
Diffstat (limited to 'packages/auditor-backoffice-ui/src/paths')
-rw-r--r--packages/auditor-backoffice-ui/src/paths/default/Table.tsx155
-rw-r--r--packages/auditor-backoffice-ui/src/paths/default/index.tsx130
-rw-r--r--packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx346
-rw-r--r--packages/auditor-backoffice-ui/src/paths/details/index.tsx (renamed from packages/auditor-backoffice-ui/src/paths/instance/transfers/update/index.tsx)19
-rw-r--r--packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx214
-rw-r--r--packages/auditor-backoffice-ui/src/paths/finance/index.tsx (renamed from packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/index.tsx)69
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx126
-rw-r--r--packages/auditor-backoffice-ui/src/paths/login/index.tsx317
-rw-r--r--packages/auditor-backoffice-ui/src/paths/notfound/index.tsx16
-rw-r--r--packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx72
-rw-r--r--packages/auditor-backoffice-ui/src/paths/operations/index.tsx (renamed from packages/auditor-backoffice-ui/src/paths/instance/products/update/index.tsx)69
-rw-r--r--packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx70
-rw-r--r--packages/auditor-backoffice-ui/src/paths/security/index.tsx (renamed from packages/auditor-backoffice-ui/src/paths/instance/templates/qr/index.tsx)56
-rw-r--r--packages/auditor-backoffice-ui/src/paths/settings/index.tsx55
14 files changed, 1281 insertions, 433 deletions
diff --git a/packages/auditor-backoffice-ui/src/paths/default/Table.tsx b/packages/auditor-backoffice-ui/src/paths/default/Table.tsx
new file mode 100644
index 000000000..9bb75907d
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/default/Table.tsx
@@ -0,0 +1,155 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 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 { 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";
+
+interface Props {
+ onSuppress: (id: any) => void;
+}
+
+export function CardTable({onSuppress}: Props): any {
+
+ const data = useEntityDataContext();
+ const [rowSelection, rowSelectionHandler] = useState<string | undefined>(
+ undefined,
+ );
+ const { i18n } = useTranslationContext();
+ const { title, endpoint, entity } = useEntityContext();
+
+ return (
+ <div class="card has-table">
+ <header class="card-header">
+ <p class="card-header-title">
+ <span class="icon">
+ <i class="mdi mdi-shopping" />
+ </span>
+ <i18n.Translate>{title}</i18n.Translate>
+ </p>
+ <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}
+ />
+ ) : (
+ <EmptyTable />
+ )}
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+}
+
+interface TableProps {
+ data: any;
+ onSuppress: (id: any) => void;
+}
+
+function Table({
+ data,
+ onSuppress,
+ }: TableProps): VNode {
+ const { i18n } = useTranslationContext();
+ const { entity } = useEntityContext();
+ type Entity = typeof entity;
+ let count = 0;
+
+ return (
+ <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>
+ </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`}
+ >
+ <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>
+ );
+ })
+ }
+ </tbody>
+ </table>
+ </div>
+ );
+}
+
+function EmptyTable(): VNode {
+ const { i18n } = useTranslationContext();
+ return (
+ <div class="content has-text-grey has-text-centered">
+ <p>
+ <span class="icon is-large">
+ <i class="mdi mdi-emoticon-happy mdi-48px" />
+ </span>
+ </p>
+ <p>
+ <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
new file mode 100644
index 000000000..1b7758190
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/default/index.tsx
@@ -0,0 +1,130 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 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 Nic Eigel
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+ ErrorType,
+ HttpError,
+ 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 { 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";
+
+
+interface Props {
+ onNotFound: () => VNode;
+ onLoadError: (e: HttpError<AuditorBackend.ErrorDetail>) => 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 [notif, setNotif] = useState<Notification | undefined>(undefined);
+ const { i18n } = useTranslationContext();
+
+ if (result.loading) return <Loading />;
+ if (!result.ok) {
+ if (
+ result.type === ErrorType.CLIENT &&
+ result.status === HttpStatusCode.Unauthorized
+ )
+ return onNotFound();
+ return onLoadError(result);
+ }
+
+ let data = result.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 />
+
+ <NotificationCard notification={notif} />
+
+ <EntityDataContextProvider value={value}>
+ <CardTable
+ onSuppress={(e: typeof entity & WithId) =>
+ setSuppressing(e)
+ }
+ />
+ </EntityDataContextProvider>
+
+ {suppressing && (
+ <ConfirmModal
+ label={`Suppress row`}
+ description={`Suppress the row`}
+ danger
+ active
+ onCancel={() => setSuppressing(null)}
+ onConfirm={async (): Promise<void> => {
+ try {
+ await updateEntity(suppressing);
+ setNotif({
+ message: i18n.str`Entity row with id: ${suppressing} has been suppressed`,
+ type: "SUCCESS",
+ });
+ } catch (error) {
+ setNotif({
+ message: i18n.str`Failed to suppress row`,
+ type: "ERROR",
+ description: error instanceof Error ? error.message : undefined,
+ });
+ }
+ setSuppressing(null);
+ }}
+ >
+ <p class="warning">
+ Suppressing a row <b>cannot be undone</b> in this GUI.
+ </p>
+ </ConfirmModal>
+ )}
+ </section>
+ );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx b/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx
new file mode 100644
index 000000000..60ae7b578
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/details/ListPage.tsx
@@ -0,0 +1,346 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 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 { 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";
+
+export interface ListPageProps {
+ onShowAll: () => void;
+ onShowNotPaid: () => void;
+ onShowPaid: () => void;
+ onShowRefunded: () => void;
+ onShowNotWired: () => void;
+ onShowWired: () => void;
+ onCopyURL: (id: string) => void;
+ isAllActive: string;
+ isPaidActive: string;
+ isNotPaidActive: string;
+ isRefundedActive: string;
+ isNotWiredActive: string;
+ isWiredActive: string;
+
+ jumpToDate?: Date;
+ onSelectDate: (date?: Date) => void;
+
+ onLoadMoreBefore?: () => void;
+ hasMoreBefore?: boolean;
+ hasMoreAfter?: boolean;
+ onLoadMoreAfter?: () => void;
+
+ onCreate: () => void;
+}
+
+export function ListPage(): VNode {
+ const { i18n } = useTranslationContext();
+
+ 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) }
+ value={"Amount arithmetic inconsistencies"}
+ >Amount arithmetic inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.bad_sig_losses_list) }
+ value={"Bad signature losses"}
+ >Bad signature losses
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.closure_lag_list) }
+ >Closure Lags
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.coin_inconsistency_list) }
+ >Coin inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="columns">
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.denomination_key_validity_withdraw_inconsistency_list) }
+ >Denominations key validity
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.denomination_without_sig_list) }
+ >Denominations without signature
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.denomination_pending_list) }
+ >Denominations pending
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.deposit_confirmation_list) }
+ >Deposit confirmations
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="columns">
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.emergency_list) }
+ >Emergencies
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.emergency_by_count_list) }
+ >Emergencies by count
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.fee_time_inconsistency_list) }
+ >Fee time inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.misattribution_in_inconsistency_list) }
+ >Misattribution in inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="columns">
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.purse_not_closed_inconsistency_list) }
+ >Purses not closed
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.purse_list) }
+ >Purses
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.refresh_hanging_list) }
+ >Refreshes hanging
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.reserve_balance_insufficient_inconsistency_list) }
+ >Reserve balances insufficient
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="columns">
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.reserve_balance_summary_wrong_inconsistency_list) }
+ >Reserve balances summary wrong
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.reserve_in_inconsistency_list) }
+ >Reserves in
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.reserve_not_closed_inconsistency_list) }
+ >Reserves not closed
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.reserves_list) }
+ >Reserves
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="columns">
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.row_inconsistency_list) }
+ >Row inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.row_minor_inconsistency_list) }
+ >Row minor inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ onClick={(e) => route(Paths.wire_format_inconsistency_list) }
+ >Wire format inconsistencies
+ </button>
+ </div>
+ </div>
+ </div>
+ <div class="column">
+ <div class="card">
+ <div class="card-body">
+ <button
+ class="button is-fullwidth"
+ 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/instance/transfers/update/index.tsx b/packages/auditor-backoffice-ui/src/paths/details/index.tsx
index 719f99209..f99dae7e5 100644
--- a/packages/auditor-backoffice-ui/src/paths/instance/transfers/update/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/details/index.tsx
@@ -16,11 +16,24 @@
/**
*
+ * @author Nic Eigel
* @author Sebastian Javier Marchano (sebasjm)
*/
import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../components/menu/index.js";
+import { Notification } from "../../utils/types.js";
+import { ListPage } from "./ListPage.js";
-export default function UpdateTransfer(): VNode {
- return <div>order transfer page</div>;
-}
+export default function DetailsDashboard(): VNode {
+
+ const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+ return (
+ <section class="section is-main-section">
+ <NotificationCard notification={notif} />
+ <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
new file mode 100644
index 000000000..88ca6bcfd
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/finance/ListPage.tsx
@@ -0,0 +1,214 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 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 Nic Eigel
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode, Fragment } 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",
+ "Coin refund fee revenue",
+ "Coin deposit fee revenue",
+ "Coin melt fee revenue",
+ "Coin irregular loss",
+ "Coins reported emergency risk by amount",
+ "Coins emergencies loss by count",
+ "Coins emergencies loss",
+ "Coins total arithmetic delta minus",
+ "Coins total arithmetic delta plus",
+ "Total escrowed",
+ "Total refresh hanging",
+ ];
+ let reserveBalances = [
+ "Total balance summary delta minus",
+ "Total balance reserve not closed",
+ "Reserves total arithmetic delta minus",
+ "Reserves total arithmetic delta plus",
+ "Reserves total bad signature loss",
+ "Reserves history fee revenue",
+ "Reserves open fee revenue",
+ ];
+ let i = 0;
+
+ return (
+ <Fragment>
+ <div class="columns">
+ <div class="column is-half">
+ <div class="columns">
+ <div class="column">
+ <div class="card">
+ <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) => {
+ 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);
+ if (key == "balances") {
+ //TODO fix
+ let gains = 0;
+ 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>
+ </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>
+ </tr>;
+ }
+ })
+ }
+ </tbody>
+ </table>
+ </div>
+ </div>
+ <div class="card">
+ <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>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="column is-half">
+ <div class="card">
+ <div class="card-content">
+ <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) => {
+ let key = x.balance_key;
+ let balanceName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+
+ if(coinBalances.includes(balanceName))
+ {
+ let value = balances[i].balance_value.replace(":", " ");
+ i=i+1;
+ return (
+ <tr class="is-link">
+ <td>{balanceName}</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) => {
+ let key = x.balance_key;
+ let balanceName = key[0].toUpperCase() + key.split("_").join(" ").split("-").join(" ").slice(1, key.length);
+
+ if(reserveBalances.includes(balanceName))
+ {
+ let value = balances[i].balance_value.replace(":", " ");
+ i = i+1;
+ return (
+ <tr class="is-link">
+ <td>{balanceName}</td>
+ <td><p>{value}</p></td>
+ </tr>
+ );
+ } else {
+ return null;
+ }
+ })
+ }
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </Fragment>
+ );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/index.tsx b/packages/auditor-backoffice-ui/src/paths/finance/index.tsx
index 2d3e7bd6b..b0d07aa0f 100644
--- a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/finance/index.tsx
@@ -16,43 +16,41 @@
/**
*
+ * @author Nic Eigel
* @author Sebastian Javier Marchano (sebasjm)
*/
import {
ErrorType,
- HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
-import { Fragment, h, VNode } from "preact";
+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 { MerchantBackend } from "../../../../declaration.js";
-import { useProductAPI, useProductDetails } from "../../../../hooks/product.js";
-import { Notification } from "../../../../utils/types.js";
-import { UpdatePage } from "./UpdatePage.js";
+import { Loading } from "../../components/exception/loading.js";
+import { NotificationCard } from "../../components/menu/index.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";
+
-export type Entity = MerchantBackend.Products.ProductAddDetail;
interface Props {
- onBack?: () => void;
- onConfirm: () => void;
onUnauthorized: () => VNode;
onNotFound: () => VNode;
- onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
- pid: string;
+ onSelect: (id: string) => void;
+ onCreate: () => void;
}
-export default function UpdateProduct({
- pid,
- onConfirm,
- onBack,
- onUnauthorized,
- onNotFound,
- onLoadError,
-}: Props): VNode {
- const { updateProduct } = useProductAPI();
- const result = useProductDetails(pid);
+
+export default function FinanceDashboard({
+ onUnauthorized,
+ // onLoadError,
+ onCreate,
+ onSelect,
+ onNotFound,
+ }: Props): VNode {
+
+ const result = getKeyFiguresData();
+
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
@@ -69,27 +67,14 @@ export default function UpdateProduct({
result.status === HttpStatusCode.NotFound
)
return onNotFound();
- return onLoadError(result);
+ else
+ return onNotFound();
}
return (
- <Fragment>
+ <section class="section is-main-section">
<NotificationCard notification={notif} />
- <UpdatePage
- product={{ ...result.data, product_id: pid }}
- onBack={onBack}
- onUpdate={(data) => {
- return updateProduct(pid, data)
- .then(onConfirm)
- .catch((error) => {
- setNotif({
- message: i18n.str`could not create product`,
- type: "ERROR",
- description: error.message,
- });
- });
- }}
- />
- </Fragment>
+ <ListPage data={result} />
+ </section>
);
-}
+} \ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx
deleted file mode 100644
index a99cfd2ef..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx
+++ /dev/null
@@ -1,126 +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)
- * @author Nic Eigel
- */
-
-import {
- ErrorType,
- HttpError,
- 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 { AuditorBackend, WithId } from "../../../../declaration.js";
-import {
- useDepositConfirmation,
- useDepositConfirmationAPI,
-} from "../../../../hooks/deposit_confirmations.js";
-import { Notification } from "../../../../utils/types.js";
-import { CardTable } from "./Table.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
-import { ConfirmModal, DeleteModal } from "../../../../components/modal/index.js";
-import { JumpToElementById } from "../../../../components/form/JumpToElementById.js";
-
-interface Props {
- onUnauthorized: () => VNode;
- onNotFound: () => VNode;
- onCreate: () => void;
- onSelect: (id: string) => void;
- onLoadError: (e: HttpError<AuditorBackend.ErrorDetail>) => VNode;
-}
-export default function DepositConfirmationList({
- onUnauthorized,
- onLoadError,
- onCreate,
- onSelect,
- onNotFound,
-}: Props): VNode {
- const result = useDepositConfirmation();
- const { deleteDepositConfirmation, updateDepositConfirmation, getDepositConfirmation } = useDepositConfirmationAPI();
- const [deleting, setDeleting] =
- useState<AuditorBackend.DepositConfirmation.DepositConfirmationDetail & WithId | null>(null);
- const [notif, setNotif] = useState<Notification | undefined>(undefined);
-
- const { i18n } = useTranslationContext();
-
- if (result.loading) return <Loading />;
- if (!result.ok) {
- if (
- result.type === ErrorType.CLIENT &&
- result.status === HttpStatusCode.Unauthorized
- )
- return onUnauthorized();
- if (
- result.type === ErrorType.CLIENT &&
- result.status === HttpStatusCode.NotFound
- )
- return onNotFound();
- return onLoadError(result);
- }
-
- return (
- <section class="section is-main-section">
- <NotificationCard notification={notif} />
-
- <JumpToElementById
- testIfExist={getDepositConfirmation}
- onSelect={onSelect}
- description={i18n.str`jump to deposit_confirmation with the given serial ID`}
- placeholder={i18n.str`serial id`}
- />
-
- {deleting && (
- <ConfirmModal
- label={`Delete deposit-confirmation`}
- description={`Delete the deposit-cofirmation "${deleting.serial_id}"`}
- danger
- active
- onCancel={() => setDeleting(null)}
- onConfirm={async (): Promise<void> => {
- try {
- await deleteDepositConfirmation(deleting.serial_id);
- setNotif({
- message: i18n.str`Deposit-confirmation "${deleting.serial_id}" (ID: ${deleting.serial_id}) has been deleted`,
- type: "SUCCESS",
- });
- } catch (error) {
- setNotif({
- message: i18n.str`Failed to delete deposit-confirmation`,
- type: "ERROR",
- description: error instanceof Error ? error.message : undefined,
- });
- }
- setDeleting(null);
- }}
- >
- <p>
- If you delete the deposit-confirmation (ID:{" "}
- <b>{deleting.serial_id}</b>), the stock and related information will be lost
- </p>
- <p class="warning">
- Deleting a deposit-confirmation <b>cannot be undone</b>.
- </p>
- </ConfirmModal>
- )}
- </section>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/login/index.tsx b/packages/auditor-backoffice-ui/src/paths/login/index.tsx
index f8990d377..c99dc6050 100644
--- a/packages/auditor-backoffice-ui/src/paths/login/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/login/index.tsx
@@ -16,187 +16,198 @@
/**
*
+ * @author Nic Eigel
* @author Sebastian Javier Marchano (sebasjm)
*/
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { ComponentChildren, h, VNode } from "preact";
-import { useCallback, useEffect, useState } from "preact/hooks";
-import { useBackendContext } from "../../context/backend.js";
-import { useInstanceContext } from "../../context/instance.js";
-import { AccessToken, LoginToken } from "../../declaration.js";
-import { useCredentialsChecker } from "../../hooks/backend.js";
-
-interface Props {
- onConfirm: (token: LoginToken | undefined) => void;
-}
-
-function normalizeToken(r: string): AccessToken {
- return `secret-token:${r}` as AccessToken;
-}
-
-export function LoginPage({ onConfirm }: Props): VNode {
- const { url: backendURL } = useBackendContext();
- const { admin, id } = useInstanceContext();
- const { requestNewLoginToken } = useCredentialsChecker();
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { useCallback, useState } from "preact/hooks";
+import { useBackendContext, useBackendTokenContext } from "../../context/backend.js";
+import { NotificationCard } from "../../components/menu/index.js";
+import { Notification } from "../../utils/types.js";
+import { useBackendToken } from "../../hooks/backend.js";
+import { Route } from "preact-router";
+import { Paths, Redirect } from "../../InstanceRoutes.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 secretToken = normalizeToken(token);
- const baseUrl = id === undefined ? backendURL : `${backendURL}/instances/${id}`
- const result = await requestNewLoginToken(baseUrl, secretToken);
- if (result.valid) {
- const { token, expiration } = result
- onConfirm({ token, expiration });
+
+ const result = useBackendToken();
+ if (!result.ok) {
+ }
+ if (result.ok) {
+ //TODO fixme
+ const { token } = useBackendTokenContext();
+ /* return (
+ <Route path="/" component={Redirect} to={Paths.key_figures}/>
+ );*/
} else {
- onConfirm(undefined);
+ setNotif({
+ message: "Your password is incorrect",
+ type: "ERROR",
+ });
}
- }, [id, token])
-
- if (admin && id !== "default") {
- //admin trying to access another instance
- 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`Login 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 instance.</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>
+ }, [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>
</div>
- </section>
- <footer
- class="modal-card-foot "
- style={{
- justifyContent: "flex-end",
- border: "1px solid",
- borderTop: 0,
- }}
+ </div>
+ </section>
+ <footer
+ class="modal-card-foot "
+ style={{
+ justifyContent: "flex-end",
+ border: "1px solid",
+ borderTop: 0,
+ }}
+ >
+ <AsyncButton
+ onClick={() => doLogin()}
>
- <AsyncButton
- onClick={doLogin}
- >
- <i18n.Translate>Confirm</i18n.Translate>
- </AsyncButton>
- </footer>
- </div>
+ <i18n.Translate>Confirm</i18n.Translate>
+ </AsyncButton>
+ </footer>
</div>
- </div>)
- }
+ </div>
+ </div>);
- 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`Login required`}</p>
- </header>
- <section
- class="modal-card-body"
- style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
- >
- <i18n.Translate>Please enter your access token.</i18n.Translate>
- <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>
+ return (<Fragment>
+ <NotificationCard notification={notif} />
+ <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`Login required`}</p>
+ </header>
+ <section
+ class="modal-card-body"
+ style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
+ >
+ <i18n.Translate>Please enter your access token.</i18n.Translate>
+
+ <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: "space-between",
- border: "1px solid",
- borderTop: 0,
- }}
- >
- <div />
- <AsyncButton
- type="is-info"
- onClick={doLogin}
+ </section>
+ <footer
+ class="modal-card-foot "
+ style={{
+ justifyContent: "space-between",
+ border: "1px solid",
+ borderTop: 0,
+ }}
>
- <i18n.Translate>Confirm</i18n.Translate>
- </AsyncButton>
- </footer>
+ <div />
+ <AsyncButton
+ type="is-info"
+ onClick={doLogin}
+ >
+ <i18n.Translate>Confirm</i18n.Translate>
+ </AsyncButton>
+
+ </footer>
+ </div>
</div>
</div>
- </div>
+ </Fragment>
+
);
}
-function AsyncButton({ onClick, disabled, type = "", children }: { type?: string, disabled?: boolean, onClick: () => Promise<void>, children: ComponentChildren }): VNode {
- const [running, setRunning] = useState(false)
+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)
+ setRunning(true);
onClick().then(() => {
- setRunning(false)
+ setRunning(false);
}).catch(() => {
- setRunning(false)
- })
+ setRunning(false);
+ });
}}>
{children}
- </button>
+ </button>;
}
diff --git a/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx b/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx
index 68adb79bf..114b95219 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
new file mode 100644
index 000000000..7f0579b2b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx
@@ -0,0 +1,72 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 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 Nic Eigel
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode, Fragment } from "preact";
+
+export function ListPage(data: any): VNode {
+ const { i18n } = useTranslationContext();
+
+ return (
+ <Fragment>
+ <div class="columns is-fullwidth">
+ <div class="column is-fullwidth">
+ <div class="card">
+ <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) => {
+ 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);
+ 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>
+ </tr>
+ );
+ })
+ }
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </Fragment>
+ );
+} \ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/products/update/index.tsx b/packages/auditor-backoffice-ui/src/paths/operations/index.tsx
index 2d3e7bd6b..c05b271fe 100644
--- a/packages/auditor-backoffice-ui/src/paths/instance/products/update/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/operations/index.tsx
@@ -16,43 +16,41 @@
/**
*
+ * @author Nic Eigel
* @author Sebastian Javier Marchano (sebasjm)
*/
import {
ErrorType,
- HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
-import { Fragment, h, VNode } from "preact";
+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 { MerchantBackend } from "../../../../declaration.js";
-import { useProductAPI, useProductDetails } from "../../../../hooks/product.js";
-import { Notification } from "../../../../utils/types.js";
-import { UpdatePage } from "./UpdatePage.js";
+import { Loading } from "../../components/exception/loading.js";
+import { NotificationCard } from "../../components/menu/index.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";
+
-export type Entity = MerchantBackend.Products.ProductAddDetail;
interface Props {
- onBack?: () => void;
- onConfirm: () => void;
onUnauthorized: () => VNode;
onNotFound: () => VNode;
- onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
- pid: string;
+ onSelect: (id: string) => void;
+ onCreate: () => void;
}
-export default function UpdateProduct({
- pid,
- onConfirm,
- onBack,
- onUnauthorized,
- onNotFound,
- onLoadError,
-}: Props): VNode {
- const { updateProduct } = useProductAPI();
- const result = useProductDetails(pid);
+
+export default function OperationsDashboard({
+ onUnauthorized,
+ // onLoadError,
+ onCreate,
+ onSelect,
+ onNotFound,
+ }: Props): VNode {
+
+ const result = getOperationData();
+
const [notif, setNotif] = useState<Notification | undefined>(undefined);
const { i18n } = useTranslationContext();
@@ -69,27 +67,14 @@ export default function UpdateProduct({
result.status === HttpStatusCode.NotFound
)
return onNotFound();
- return onLoadError(result);
+ else
+ return onNotFound();
}
return (
- <Fragment>
+ <section class="section is-main-section">
<NotificationCard notification={notif} />
- <UpdatePage
- product={{ ...result.data, product_id: pid }}
- onBack={onBack}
- onUpdate={(data) => {
- return updateProduct(pid, data)
- .then(onConfirm)
- .catch((error) => {
- setNotif({
- message: i18n.str`could not create product`,
- type: "ERROR",
- description: error.message,
- });
- });
- }}
- />
- </Fragment>
+ <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
new file mode 100644
index 000000000..74f83bd4a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/security/ListPage.tsx
@@ -0,0 +1,70 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 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 Nic Eigel
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode, Fragment } from "preact";
+
+export function ListPage(data: any): VNode {
+ const { i18n } = useTranslationContext();
+
+ return (
+ <Fragment>
+ <div class="columns is-fullwidth">
+ <div class="column is-fullwidth">
+ <div class="card">
+ <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) => {
+ 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);
+ 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>
+ </tr>
+ );
+ })
+ }
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </div>
+ </div>
+ </Fragment>
+ );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/index.tsx b/packages/auditor-backoffice-ui/src/paths/security/index.tsx
index 65ccc2dcc..99c98a5e7 100644
--- a/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/security/index.tsx
@@ -16,46 +16,43 @@
/**
*
+ * @author Nic Eigel
* @author Sebastian Javier Marchano (sebasjm)
*/
import {
ErrorType,
- HttpError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
-import { Fragment, h, VNode } from "preact";
+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 { MerchantBackend } from "../../../../declaration.js";
-import {
- useTemplateAPI,
- useTemplateDetails,
-} from "../../../../hooks/templates.js";
-import { Notification } from "../../../../utils/types.js";
-import { QrPage } from "./QrPage.js";
+import { Loading } from "../../components/exception/loading.js";
+import { NotificationCard } from "../../components/menu/index.js";
+import { Notification } from "../../utils/types.js";
+import { ListPage } from "./ListPage.js";
import { HttpStatusCode } from "@gnu-taler/taler-util";
-
-export type Entity = MerchantBackend.Transfers.TransferInformation;
+import { getCriticalData } from "../../hooks/critical.js";
interface Props {
- onBack?: () => void;
onUnauthorized: () => VNode;
onNotFound: () => VNode;
- onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
- tid: string;
+ onSelect: (id: string) => void;
+ onCreate: () => void;
}
-export default function TemplateQrPage({
- tid,
- onBack,
- onLoadError,
- onNotFound,
- onUnauthorized,
-}: Props): VNode {
- const result = useTemplateDetails(tid);
+export default function SecurityDashboard({
+ onUnauthorized,
+ // onLoadError,
+ onCreate,
+ onSelect,
+ onNotFound,
+ }: Props): VNode {
+
+ const result = getCriticalData();
+
const [notif, setNotif] = useState<Notification | undefined>(undefined);
+ const { i18n } = useTranslationContext();
+
if (result.loading) return <Loading />;
if (!result.ok) {
if (
@@ -68,13 +65,14 @@ export default function TemplateQrPage({
result.status === HttpStatusCode.NotFound
)
return onNotFound();
- return onLoadError(result);
+ else
+ return onNotFound();
}
return (
- <>
+ <section class="section is-main-section">
<NotificationCard notification={notif} />
- <QrPage contract={result.data.template_contract} id={tid} onBack={onBack} />
- </>
+ <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 093c3d09d..77a56a794 100644
--- a/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
+++ b/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
@@ -1,8 +1,28 @@
+/*
+ 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)
+ * @author Nic Eigel
+ */
+
import { useLang, useTranslationContext } from "@gnu-taler/web-util/browser";
import { VNode, h } from "preact";
-import { FormErrors, FormProvider } from "../../components/form/FormProvider.js";
-import { InputSelector } from "../../components/form/InputSelector.js";
-import { InputToggle } from "../../components/form/InputToggle.js";
+import { FormErrors, FormProvider } from "../../components/forms/FormProvider.js";
import { LangSelector } from "../../components/menu/LangSelector.js";
import { Settings, useSettings } from "../../hooks/useSettings.js";
@@ -16,7 +36,7 @@ function getBrowserLang(): string | undefined {
export function Settings({ onClose }: { onClose?: () => void }): VNode {
const { i18n } = useTranslationContext()
const borwserLang = getBrowserLang()
- //const { update } = useLang()
+ const { update } = useLang(undefined, {})
const [value, updateValue] = useSettings()
const errors: FormErrors<Settings> = {
@@ -60,38 +80,13 @@ export function Settings({ onClose }: { onClose?: () => void }): VNode {
data-tooltip={i18n.str`generate random secret key`}
class="button is-info mr-2"
onClick={(e) => {
- //update(borwserLang.substring(0, 2))
+ update(borwserLang.substring(0, 2))
}}
>
<i18n.Translate>Set default</i18n.Translate>
</button>}
</div>
</div>
- <InputToggle<Settings>
- label={i18n.str`Advance order creation`}
- tooltip={i18n.str`Shows more options in the order creation form`}
- name="advanceOrderMode"
- />
- <InputSelector<Settings>
- name="dateFormat"
- label={i18n.str`Date format`}
- expand={true}
- help={
- value.dateFormat === "dmy" ? "31/12/2001" : value.dateFormat === "mdy" ? "12/31/2001" : value.dateFormat === "ymd" ? "2001/12/31" : ""
- }
- toStr={(e) => {
- if (e === "ymd") return "year month day"
- if (e === "mdy") return "month day year"
- if (e === "dmy") return "day month year"
- return "choose one"
- }}
- values={[
- "ymd",
- "mdy",
- "dmy",
- ]}
- tooltip={i18n.str`how the date is going to be displayed`}
- />
</FormProvider>
</div>
</div>