aboutsummaryrefslogtreecommitdiff
path: root/packages/auditor-backoffice-ui/src/paths/instance/otp_devices
diff options
context:
space:
mode:
authorNic Eigel <nic@eigel.ch>2024-06-24 09:16:33 +0200
committerNic Eigel <nic@eigel.ch>2024-06-24 09:16:33 +0200
commit75ff04672c011cf4c47b8f07d327adbf59323396 (patch)
tree24577e0429f641e3c19005b5a9180af8186232d0 /packages/auditor-backoffice-ui/src/paths/instance/otp_devices
parent0b90a34e7c7c5d9bcca9a2ebe74df9fdfafc6577 (diff)
downloadwallet-core-75ff04672c011cf4c47b8f07d327adbf59323396.tar.xz
fixing merge-error
Diffstat (limited to 'packages/auditor-backoffice-ui/src/paths/instance/otp_devices')
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx28
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx179
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx104
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx70
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx28
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx64
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx211
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx106
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx32
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx186
-rw-r--r--packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx102
11 files changed, 0 insertions, 1110 deletions
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx
deleted file mode 100644
index 36b31ebe8..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx
+++ /dev/null
@@ -1,28 +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, FunctionalComponent } from "preact";
-import { CreatePage as TestedComponent } from "./CreatePage.js";
-
-export default {
- title: "Pages/OtpDevices/Create",
- component: TestedComponent,
-};
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx
deleted file mode 100644
index e3ecb3243..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx
+++ /dev/null
@@ -1,179 +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 { isRfc3548Base32Charset, randomRfc3548Base32Key } from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Fragment, h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
-import {
- FormErrors,
- FormProvider,
-} from "../../../../components/form/FormProvider.js";
-import { Input } from "../../../../components/form/Input.js";
-import { InputSelector } from "../../../../components/form/InputSelector.js";
-import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
-import { useBackendContext } from "../../../../context/backend.js";
-import { MerchantBackend } from "../../../../declaration.js";
-
-type Entity = MerchantBackend.OTP.OtpDeviceAddDetails;
-
-interface Props {
- onCreate: (d: Entity) => Promise<void>;
- onBack?: () => void;
-}
-
-const algorithms = [0, 1, 2];
-const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d eTOTP-SHA1"];
-
-export function CreatePage({ onCreate, onBack }: Props): VNode {
- const { i18n } = useTranslationContext();
- const backend = useBackendContext();
-
- const [state, setState] = useState<Partial<Entity>>({});
-
- const [showKey, setShowKey] = useState(false);
-
- const errors: FormErrors<Entity> = {
- otp_device_id: !state.otp_device_id
- ? i18n.str`required`
- : !/[a-zA-Z0-9]*/.test(state.otp_device_id)
- ? i18n.str`no valid. only characters and numbers`
- : undefined,
- otp_algorithm: !state.otp_algorithm ? i18n.str`required` : undefined,
- otp_key: !state.otp_key
- ? i18n.str`required`
- : !isRfc3548Base32Charset(state.otp_key)
- ? i18n.str`just letters and numbers from 2 to 7`
- : state.otp_key.length !== 32
- ? i18n.str`size of the key should be 32`
- : undefined,
- otp_device_description: !state.otp_device_description
- ? i18n.str`required`
- : !/[a-zA-Z0-9]*/.test(state.otp_device_description)
- ? i18n.str`no valid. only characters and numbers`
- : undefined,
- };
-
- const hasErrors = Object.keys(errors).some(
- (k) => (errors as any)[k] !== undefined,
- );
-
- const submitForm = () => {
- if (hasErrors) return Promise.reject();
- return onCreate(state as any);
- };
-
- return (
- <div>
- <section class="section is-main-section">
- <div class="columns">
- <div class="column" />
- <div class="column is-four-fifths">
- <FormProvider
- object={state}
- valueHandler={setState}
- errors={errors}
- >
- <Input<Entity>
- name="otp_device_id"
- label={i18n.str`ID`}
- tooltip={i18n.str`Internal id on the system`}
- />
- <Input<Entity>
- name="otp_device_description"
- label={i18n.str`Descripiton`}
- tooltip={i18n.str`Useful to identify the device physically`}
- />
- <InputSelector<Entity>
- name="otp_algorithm"
- label={i18n.str`Verification algorithm`}
- tooltip={i18n.str`Algorithm to use to verify transaction in offline mode`}
- values={algorithms}
- toStr={(v) => algorithmsNames[v]}
- fromStr={(v) => Number(v)}
- />
- {state.otp_algorithm && state.otp_algorithm > 0 ? (
- <Fragment>
- <InputWithAddon<Entity>
- expand
- name="otp_key"
- label={i18n.str`Device key`}
- inputType={showKey ? "text" : "password"}
- help="Be sure to be very hard to guess or use the random generator"
- tooltip={i18n.str`Your device need to have exactly the same value`}
- fromStr={(v) => v.toUpperCase()}
- addonAfterAction={() => {
- setShowKey(!showKey);
- }}
- addonAfter={
- <span class="icon">
- {showKey ? (
- <i class="mdi mdi-eye" />
- ) : (
- <i class="mdi mdi-eye-off" />
- )}
- </span>
- }
- side={
- <button
- data-tooltip={i18n.str`generate random secret key`}
- class="button is-info mr-3"
- onClick={(e) => {
- setState((s) => ({
- ...s,
- otp_key: randomRfc3548Base32Key(),
- }));
- }}
- >
- <i18n.Translate>random</i18n.Translate>
- </button>
- }
- />
- </Fragment>
- ) : undefined}
- </FormProvider>
-
- <div class="buttons is-right mt-5">
- {onBack && (
- <button class="button" onClick={onBack}>
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- )}
- <AsyncButton
- disabled={hasErrors}
- data-tooltip={
- hasErrors
- ? i18n.str`Need to complete marked fields`
- : "confirm operation"
- }
- onClick={submitForm}
- >
- <i18n.Translate>Confirm</i18n.Translate>
- </AsyncButton>
- </div>
- </div>
- <div class="column" />
- </div>
- </section>
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
deleted file mode 100644
index cf60925a4..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
+++ /dev/null
@@ -1,104 +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 { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Fragment, VNode, h } from "preact";
-import { QR } from "../../../../components/exception/QR.js";
-import { CreatedSuccessfully as Template } from "../../../../components/notifications/CreatedSuccessfully.js";
-import { useInstanceContext } from "../../../../context/instance.js";
-import { MerchantBackend } from "../../../../declaration.js";
-import { useBackendContext } from "../../../../context/backend.js";
-
-type Entity = MerchantBackend.OTP.OtpDeviceAddDetails;
-
-interface Props {
- entity: Entity;
- onConfirm: () => void;
-}
-
-function isNotUndefined<X>(x: X | undefined): x is X {
- return !!x;
-}
-
-export function CreatedSuccessfully({
- entity,
- onConfirm,
-}: Props): VNode {
- const { i18n } = useTranslationContext();
- const { url: backendURL } = useBackendContext()
- const { id: instanceId } = useInstanceContext();
- const issuer = new URL(backendURL).hostname;
- const qrText = `otpauth://totp/${instanceId}/${entity.otp_device_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${entity.otp_key}`;
- const qrTextSafe = `otpauth://totp/${instanceId}/${entity.otp_device_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${entity.otp_key.substring(0, 6)}...`;
-
- return (
- <Template onConfirm={onConfirm} >
- <p class="is-size-5">
- <i18n.Translate>
- You can scan the next QR code with your device or safe the key before continue.
- </i18n.Translate>
- </p>
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label">ID</label>
- </div>
- <div class="field-body is-flex-grow-3">
- <div class="field">
- <p class="control">
- <input
- readonly
- class="input"
- value={entity.otp_device_id}
- />
- </p>
- </div>
- </div>
- </div>
- <div class="field is-horizontal">
- <div class="field-label is-normal">
- <label class="label"><i18n.Translate>Description</i18n.Translate></label>
- </div>
- <div class="field-body is-flex-grow-3">
- <div class="field">
- <p class="control">
- <input
- class="input"
- readonly
- value={entity.otp_device_description}
- />
- </p>
- </div>
- </div>
- </div>
- <QR
- text={qrText}
- />
- <div
- style={{
- color: "grey",
- fontSize: "small",
- width: 200,
- textAlign: "center",
- margin: "auto",
- wordBreak: "break-all",
- }}
- >
- {qrTextSafe}
- </div>
- </Template>
- );
-}
-
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
deleted file mode 100644
index f0b419f68..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
+++ /dev/null
@@ -1,70 +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 { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Fragment, h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { NotificationCard } from "../../../../components/menu/index.js";
-import { MerchantBackend } from "../../../../declaration.js";
-import { useWebhookAPI } from "../../../../hooks/webhooks.js";
-import { Notification } from "../../../../utils/types.js";
-import { CreatePage } from "./CreatePage.js";
-import { useOtpDeviceAPI } from "../../../../hooks/otp.js";
-import { CreatedSuccessfully } from "./CreatedSuccessfully.js";
-
-export type Entity = MerchantBackend.OTP.OtpDeviceAddDetails;
-interface Props {
- onBack?: () => void;
- onConfirm: () => void;
-}
-
-export default function CreateValidator({ onConfirm, onBack }: Props): VNode {
- const { createOtpDevice } = useOtpDeviceAPI();
- const [notif, setNotif] = useState<Notification | undefined>(undefined);
- const { i18n } = useTranslationContext();
- const [created, setCreated] = useState<MerchantBackend.OTP.OtpDeviceAddDetails | null>(null)
-
- if (created) {
- return <CreatedSuccessfully entity={created} onConfirm={onConfirm} />
- }
-
- return (
- <>
- <NotificationCard notification={notif} />
- <CreatePage
- onBack={onBack}
- onCreate={(request: Entity) => {
- return createOtpDevice(request)
- .then((d) => {
- setCreated(request)
- })
- .catch((error) => {
- setNotif({
- message: i18n.str`could not create device`,
- type: "ERROR",
- description: error.message,
- });
- });
- }}
- />
- </>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx
deleted file mode 100644
index 49032c80e..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx
+++ /dev/null
@@ -1,28 +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 { FunctionalComponent, h } from "preact";
-import { ListPage as TestedComponent } from "./ListPage.js";
-
-export default {
- title: "Pages/OtpDevices/List",
- component: TestedComponent,
-};
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx
deleted file mode 100644
index f3b5a2088..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx
+++ /dev/null
@@ -1,64 +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 { MerchantBackend } from "../../../../declaration.js";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { CardTable } from "./Table.js";
-
-export interface Props {
- devices: MerchantBackend.OTP.OtpDeviceEntry[];
- onLoadMoreBefore?: () => void;
- onLoadMoreAfter?: () => void;
- onCreate: () => void;
- onDelete: (e: MerchantBackend.OTP.OtpDeviceEntry) => void;
- onSelect: (e: MerchantBackend.OTP.OtpDeviceEntry) => void;
-}
-
-export function ListPage({
- devices,
- onCreate,
- onDelete,
- onSelect,
- onLoadMoreBefore,
- onLoadMoreAfter,
-}: Props): VNode {
- const form = { payto_uri: "" };
-
- const { i18n } = useTranslationContext();
- return (
- <section class="section is-main-section">
- <CardTable
- devices={devices.map((o) => ({
- ...o,
- id: String(o.otp_device_id),
- }))}
- onCreate={onCreate}
- onDelete={onDelete}
- onSelect={onSelect}
- onLoadMoreBefore={onLoadMoreBefore}
- hasMoreBefore={!onLoadMoreBefore}
- onLoadMoreAfter={onLoadMoreAfter}
- hasMoreAfter={!onLoadMoreAfter}
- />
- </section>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx
deleted file mode 100644
index d085d1c44..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx
+++ /dev/null
@@ -1,211 +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 { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { h, VNode } from "preact";
-import { StateUpdater, useState } from "preact/hooks";
-import { MerchantBackend } from "../../../../declaration.js";
-
-type Entity = MerchantBackend.OTP.OtpDeviceEntry;
-
-interface Props {
- devices: Entity[];
- onDelete: (e: Entity) => void;
- onSelect: (e: Entity) => void;
- onCreate: () => void;
- onLoadMoreBefore?: () => void;
- hasMoreBefore?: boolean;
- hasMoreAfter?: boolean;
- onLoadMoreAfter?: () => void;
-}
-
-export function CardTable({
- devices,
- onCreate,
- onDelete,
- onSelect,
- onLoadMoreAfter,
- onLoadMoreBefore,
- hasMoreAfter,
- hasMoreBefore,
-}: Props): VNode {
- const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
-
- const { i18n } = useTranslationContext();
-
- return (
- <div class="card has-table">
- <header class="card-header">
- <p class="card-header-title">
- <span class="icon">
- <i class="mdi mdi-newspaper" />
- </span>
- <i18n.Translate>OTP Devices</i18n.Translate>
- </p>
- <div class="card-header-icon" aria-label="more options">
- <span
- class="has-tooltip-left"
- data-tooltip={i18n.str`add new devices`}
- >
- <button class="button is-info" type="button" onClick={onCreate}>
- <span class="icon is-small">
- <i class="mdi mdi-plus mdi-36px" />
- </span>
- </button>
- </span>
- </div>
- </header>
- <div class="card-content">
- <div class="b-table has-pagination">
- <div class="table-wrapper has-mobile-cards">
- {devices.length > 0 ? (
- <Table
- instances={devices}
- onDelete={onDelete}
- onSelect={onSelect}
- rowSelection={rowSelection}
- rowSelectionHandler={rowSelectionHandler}
- onLoadMoreAfter={onLoadMoreAfter}
- onLoadMoreBefore={onLoadMoreBefore}
- hasMoreAfter={hasMoreAfter}
- hasMoreBefore={hasMoreBefore}
- />
- ) : (
- <EmptyTable />
- )}
- </div>
- </div>
- </div>
- </div>
- );
-}
-interface TableProps {
- rowSelection: string[];
- instances: Entity[];
- onDelete: (e: Entity) => void;
- onSelect: (e: Entity) => void;
- rowSelectionHandler: StateUpdater<string[]>;
- onLoadMoreBefore?: () => void;
- hasMoreBefore?: boolean;
- hasMoreAfter?: boolean;
- onLoadMoreAfter?: () => void;
-}
-
-function toggleSelected<T>(id: T): (prev: T[]) => T[] {
- return (prev: T[]): T[] =>
- prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
-}
-
-function Table({
- instances,
- onLoadMoreAfter,
- onDelete,
- onSelect,
- onLoadMoreBefore,
- hasMoreAfter,
- hasMoreBefore,
-}: TableProps): VNode {
- const { i18n } = useTranslationContext();
- return (
- <div class="table-container">
- {hasMoreBefore && (
- <button
- class="button is-fullwidth"
- data-tooltip={i18n.str`load more devices before the first one`}
- onClick={onLoadMoreBefore}
- >
- <i18n.Translate>load newer devices</i18n.Translate>
- </button>
- )}
- <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
- <thead>
- <tr>
- <th>
- <i18n.Translate>ID</i18n.Translate>
- </th>
- <th>
- <i18n.Translate>Description</i18n.Translate>
- </th>
- <th />
- </tr>
- </thead>
- <tbody>
- {instances.map((i) => {
- return (
- <tr key={i.otp_device_id}>
- <td
- onClick={(): void => onSelect(i)}
- style={{ cursor: "pointer" }}
- >
- {i.otp_device_id}
- </td>
- <td
- onClick={(): void => onSelect(i)}
- style={{ cursor: "pointer" }}
- >
- {i.otp_device_id}
- </td>
- <td class="is-actions-cell right-sticky">
- <div class="buttons is-right">
- <button
- class="button is-danger is-small has-tooltip-left"
- data-tooltip={i18n.str`delete selected devices from the database`}
- onClick={() => onDelete(i)}
- >
- Delete
- </button>
- </div>
- </td>
- </tr>
- );
- })}
- </tbody>
- </table>
- {hasMoreAfter && (
- <button
- class="button is-fullwidth"
- data-tooltip={i18n.str`load more devices after the last one`}
- onClick={onLoadMoreAfter}
- >
- <i18n.Translate>load older devices</i18n.Translate>
- </button>
- )}
- </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-sad mdi-48px" />
- </span>
- </p>
- <p>
- <i18n.Translate>
- There is no devices yet, add more pressing the + sign
- </i18n.Translate>
- </p>
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
deleted file mode 100644
index a3299326c..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
+++ /dev/null
@@ -1,106 +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 { HttpStatusCode } from "@gnu-taler/taler-util";
-import {
- ErrorType,
- HttpError,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
-import { Fragment, VNode, h } 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 { useInstanceOtpDevices, useOtpDeviceAPI } from "../../../../hooks/otp.js";
-import { Notification } from "../../../../utils/types.js";
-import { ListPage } from "./ListPage.js";
-
-interface Props {
- onUnauthorized: () => VNode;
- onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
- onNotFound: () => VNode;
- onCreate: () => void;
- onSelect: (id: string) => void;
-}
-
-export default function ListOtpDevices({
- onUnauthorized,
- onLoadError,
- onCreate,
- onSelect,
- onNotFound,
-}: Props): VNode {
- const [position, setPosition] = useState<string | undefined>(undefined);
- const { i18n } = useTranslationContext();
- const [notif, setNotif] = useState<Notification | undefined>(undefined);
- const { deleteOtpDevice } = useOtpDeviceAPI();
- const result = useInstanceOtpDevices({ position }, (id) => setPosition(id));
-
- 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 (
- <Fragment>
- <NotificationCard notification={notif} />
-
- <ListPage
- devices={result.data.otp_devices}
- onLoadMoreBefore={
- result.isReachingStart ? result.loadMorePrev : undefined
- }
- onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
- onCreate={onCreate}
- onSelect={(e) => {
- onSelect(e.otp_device_id);
- }}
- onDelete={(e: MerchantBackend.OTP.OtpDeviceEntry) =>
- deleteOtpDevice(e.otp_device_id)
- .then(() =>
- setNotif({
- message: i18n.str`validator delete successfully`,
- type: "SUCCESS",
- }),
- )
- .catch((error) =>
- setNotif({
- message: i18n.str`could not delete the validator`,
- type: "ERROR",
- description: error.message,
- }),
- )
- }
- />
- </Fragment>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx
deleted file mode 100644
index 06ea9d07a..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx
+++ /dev/null
@@ -1,32 +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, FunctionalComponent } from "preact";
-import { UpdatePage as TestedComponent } from "./UpdatePage.js";
-
-export default {
- title: "Pages/OtpDevices/Update",
- component: TestedComponent,
- argTypes: {
- onUpdate: { action: "onUpdate" },
- onBack: { action: "onBack" },
- },
-};
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx
deleted file mode 100644
index 310810576..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx
+++ /dev/null
@@ -1,186 +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 { randomRfc3548Base32Key } from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Fragment, h, VNode } from "preact";
-import { useState } from "preact/hooks";
-import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
-import {
- FormErrors,
- FormProvider,
-} from "../../../../components/form/FormProvider.js";
-import { Input } from "../../../../components/form/Input.js";
-import { InputSelector } from "../../../../components/form/InputSelector.js";
-import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
-import { MerchantBackend, WithId } from "../../../../declaration.js";
-
-type Entity = MerchantBackend.OTP.OtpDevicePatchDetails & WithId;
-
-interface Props {
- onUpdate: (d: Entity) => Promise<void>;
- onBack?: () => void;
- device: Entity;
-}
-const algorithms = [0, 1, 2];
-const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d eTOTP-SHA1"];
-export function UpdatePage({ device, onUpdate, onBack }: Props): VNode {
- const { i18n } = useTranslationContext();
-
- const [state, setState] = useState<Partial<Entity>>(device);
- const [showKey, setShowKey] = useState(false);
-
- const errors: FormErrors<Entity> = {};
-
- const hasErrors = Object.keys(errors).some(
- (k) => (errors as any)[k] !== undefined,
- );
-
- const submitForm = () => {
- if (hasErrors) return Promise.reject();
- return onUpdate(state as any);
- };
-
- return (
- <div>
- <section class="section">
- <section class="hero is-hero-bar">
- <div class="hero-body">
- <div class="level">
- <div class="level-left">
- <div class="level-item">
- <span class="is-size-4">
- Device: <b>{device.id}</b>
- </span>
- </div>
- </div>
- </div>
- </div>
- </section>
- <hr />
-
- <section class="section is-main-section">
- <div class="columns">
- <div class="column is-four-fifths">
- <FormProvider
- object={state}
- valueHandler={setState}
- errors={errors}
- >
- <Input<Entity>
- name="otp_device_description"
- label={i18n.str`Description`}
- tooltip={i18n.str`Useful to identify the device physically`}
- />
- <InputSelector<Entity>
- name="otp_algorithm"
- label={i18n.str`Verification algorithm`}
- tooltip={i18n.str`Algorithm to use to verify transaction in offline mode`}
- values={algorithms}
- toStr={(v) => algorithmsNames[v]}
- fromStr={(v) => Number(v)}
- />
- {state.otp_algorithm && state.otp_algorithm > 0 ? (
- <Fragment>
- <InputWithAddon<Entity>
- name="otp_key"
- label={i18n.str`Device key`}
- readonly={state.otp_key === undefined}
- inputType={showKey ? "text" : "password"}
- help={
- state.otp_key === undefined
- ? "Not modified"
- : "Be sure to be very hard to guess or use the random generator"
- }
- tooltip={i18n.str`Your device need to have exactly the same value`}
- fromStr={(v) => v.toUpperCase()}
- addonAfterAction={() => {
- setShowKey(!showKey);
- }}
- addonAfter={
- <span
- class="icon"
- onClick={() => {
- setShowKey(!showKey);
- }}
- >
- {showKey ? (
- <i class="mdi mdi-eye" />
- ) : (
- <i class="mdi mdi-eye-off" />
- )}
- </span>
- }
- side={
- state.otp_key === undefined ? (
- <button
- onClick={(e) => {
- setState((s) => ({ ...s, otp_key: "" }));
- }}
- class="button"
- >
- change key
- </button>
- ) : (
- <button
- data-tooltip={i18n.str`generate random secret key`}
- class="button is-info mr-3"
- onClick={(e) => {
- setState((s) => ({
- ...s,
- otp_key: randomRfc3548Base32Key(),
- }));
- }}
- >
- <i18n.Translate>random</i18n.Translate>
- </button>
- )
- }
- />
- </Fragment>
- ) : undefined}{" "}
- </FormProvider>
-
- <div class="buttons is-right mt-5">
- {onBack && (
- <button class="button" onClick={onBack}>
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- )}
- <AsyncButton
- disabled={hasErrors}
- data-tooltip={
- hasErrors
- ? i18n.str`Need to complete marked fields`
- : "confirm operation"
- }
- onClick={submitForm}
- >
- <i18n.Translate>Confirm</i18n.Translate>
- </AsyncButton>
- </div>
- </div>
- </div>
- </section>
- </section>
- </div>
- );
-}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
deleted file mode 100644
index 3128608e1..000000000
--- a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
+++ /dev/null
@@ -1,102 +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 {
- ErrorType,
- HttpError,
- useTranslationContext,
-} from "@gnu-taler/web-util/browser";
-import { Fragment, 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, WithId } from "../../../../declaration.js";
-import { Notification } from "../../../../utils/types.js";
-import { UpdatePage } from "./UpdatePage.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
-import { useOtpDeviceAPI, useOtpDeviceDetails } from "../../../../hooks/otp.js";
-
-export type Entity = MerchantBackend.OTP.OtpDevicePatchDetails & WithId;
-
-interface Props {
- onBack?: () => void;
- onConfirm: () => void;
- onUnauthorized: () => VNode;
- onNotFound: () => VNode;
- onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
- vid: string;
-}
-export default function UpdateValidator({
- vid,
- onConfirm,
- onBack,
- onUnauthorized,
- onNotFound,
- onLoadError,
-}: Props): VNode {
- const { updateOtpDevice } = useOtpDeviceAPI();
- const result = useOtpDeviceDetails(vid);
- 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 (
- <Fragment>
- <NotificationCard notification={notif} />
- <UpdatePage
- device={{
- id: vid,
- otp_algorithm: result.data.otp_algorithm,
- otp_device_description: result.data.device_description,
- otp_key: undefined,
- otp_ctr: result.data.otp_ctr
- }}
- onBack={onBack}
- onUpdate={(data) => {
- return updateOtpDevice(vid, data)
- .then(onConfirm)
- .catch((error) => {
- setNotif({
- message: i18n.str`could not update template`,
- type: "ERROR",
- description: error.message,
- });
- });
- }}
- />
- </Fragment>
- );
-}