taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit f547bf658742751a9b9b046a869cec116b025f46
parent f5dd32d1cfc1f363ba0f68b1c7dad29610253edd
Author: Florian Dold <florian@dold.me>
Date:   Tue, 27 Aug 2024 02:17:47 +0200

auditor SPA: DCE

Diffstat:
Mpackages/auditor-backoffice-ui/src/components/exception/loading.tsx | 40++++++++++++++++++++--------------------
Dpackages/auditor-backoffice-ui/src/components/forms/Input.tsx | 116-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/components/forms/InputCurrency.tsx | 67-------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/components/forms/InputNumber.tsx | 60------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/components/forms/InputSelector.tsx | 94-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/components/forms/InputToggle.tsx | 91-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/components/forms/InputWithAddon.tsx | 116-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/components/forms/useField.tsx | 92-------------------------------------------------------------------------------
Mpackages/auditor-backoffice-ui/src/declaration.d.ts | 626+------------------------------------------------------------------------------
Mpackages/auditor-backoffice-ui/src/paths/default/Table.tsx | 120+++++++++++++++++++++++++++++++++++++------------------------------------------
Mpackages/auditor-backoffice-ui/src/paths/details/ListPage.tsx | 145+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Mpackages/auditor-backoffice-ui/src/paths/details/index.tsx | 4+---
Mpackages/auditor-backoffice-ui/src/paths/notfound/index.tsx | 16++++++++--------
Mpackages/auditor-backoffice-ui/src/paths/operations/ListPage.tsx | 70+++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mpackages/auditor-backoffice-ui/src/paths/operations/index.tsx | 31++++++++++++-------------------
Mpackages/auditor-backoffice-ui/src/paths/security/ListPage.tsx | 51+++++++++++++++++++++++++++++++++------------------
Mpackages/auditor-backoffice-ui/src/paths/security/index.tsx | 34++++++++++++++++------------------
Mpackages/auditor-backoffice-ui/src/paths/settings/index.tsx | 133++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Dpackages/auditor-backoffice-ui/src/schemas/index.ts | 245-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/utils/amount.ts | 73-------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/utils/constants.ts | 197-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/utils/regex.test.ts | 88-------------------------------------------------------------------------------
Dpackages/auditor-backoffice-ui/src/utils/table.ts | 57---------------------------------------------------------
Mpackages/auditor-backoffice-ui/src/utils/types.ts | 7+++----
24 files changed, 360 insertions(+), 2213 deletions(-)

diff --git 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/Input.tsx b/packages/auditor-backoffice-ui/src/components/forms/Input.tsx @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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/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/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/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 @@ -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/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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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/utils/amount.ts b/packages/auditor-backoffice-ui/src/utils/amount.ts @@ -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 @@ -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 @@ -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 @@ -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 @@ -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;