diff options
Diffstat (limited to 'packages/merchant-backoffice-ui/src/utils')
-rw-r--r-- | packages/merchant-backoffice-ui/src/utils/amount.ts | 71 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/utils/constants.ts | 194 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/utils/regex.test.ts | 88 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/utils/table.ts | 56 | ||||
-rw-r--r-- | packages/merchant-backoffice-ui/src/utils/types.ts | 31 |
5 files changed, 440 insertions, 0 deletions
diff --git a/packages/merchant-backoffice-ui/src/utils/amount.ts b/packages/merchant-backoffice-ui/src/utils/amount.ts new file mode 100644 index 000000000..c94101b4b --- /dev/null +++ b/packages/merchant-backoffice-ui/src/utils/amount.ts @@ -0,0 +1,71 @@ +/* + 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, + TalerMerchantApi, +} from "@gnu-taler/taler-util"; + +/** + * 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: TalerMerchantApi.RefundDetails[], + cur: TalerMerchantApi.RefundDetails, +): TalerMerchantApi.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; +} diff --git a/packages/merchant-backoffice-ui/src/utils/constants.ts b/packages/merchant-backoffice-ui/src/utils/constants.ts new file mode 100644 index 000000000..6b4d8eade --- /dev/null +++ b/packages/merchant-backoffice-ui/src/utils/constants.ts @@ -0,0 +1,194 @@ +/* + 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 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+))?)\/$/; + +export const PAGINATED_LIST_SIZE = 5; +// when doing paginated request, ask for one more +// and use it to know if there are more to request +export const PAGINATED_LIST_REQUEST = PAGINATED_LIST_SIZE + 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/merchant-backoffice-ui/src/utils/regex.test.ts b/packages/merchant-backoffice-ui/src/utils/regex.test.ts new file mode 100644 index 000000000..78f2ef5ae --- /dev/null +++ b/packages/merchant-backoffice-ui/src/utils/regex.test.ts @@ -0,0 +1,88 @@ +/* + 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/merchant-backoffice-ui/src/utils/table.ts b/packages/merchant-backoffice-ui/src/utils/table.ts new file mode 100644 index 000000000..982b68e5e --- /dev/null +++ b/packages/merchant-backoffice-ui/src/utils/table.ts @@ -0,0 +1,56 @@ +/* + 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) + */ + +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/merchant-backoffice-ui/src/utils/types.ts b/packages/merchant-backoffice-ui/src/utils/types.ts new file mode 100644 index 000000000..9ce6da4d1 --- /dev/null +++ b/packages/merchant-backoffice-ui/src/utils/types.ts @@ -0,0 +1,31 @@ +/* + 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 { VNode } from "preact"; + +export interface KeyValue { + [key: string]: string; +} + +export interface Notification { + message: string; + description?: string | VNode; + details?: string | VNode | string; + type: MessageType; +} + +export type ValueOrFunction<T> = T | ((p: T) => T); +export type MessageType = "INFO" | "WARN" | "ERROR" | "SUCCESS"; |