summaryrefslogtreecommitdiff
path: root/packages/merchant-backend-ui
diff options
context:
space:
mode:
Diffstat (limited to 'packages/merchant-backend-ui')
-rw-r--r--packages/merchant-backend-ui/README.md2
-rwxr-xr-xpackages/merchant-backend-ui/build.mjs56
-rw-r--r--packages/merchant-backend-ui/package.json7
-rw-r--r--packages/merchant-backend-ui/render-examples.ts122
-rw-r--r--packages/merchant-backend-ui/rollup.config.js116
-rw-r--r--packages/merchant-backend-ui/src/pages/DepletedTip.tsx60
-rw-r--r--packages/merchant-backend-ui/src/pages/OfferRefund.tsx2
-rw-r--r--packages/merchant-backend-ui/src/pages/OfferTip.stories.tsx45
-rw-r--r--packages/merchant-backend-ui/src/pages/OfferTip.tsx142
-rw-r--r--packages/merchant-backend-ui/src/pages/RequestPayment.tsx8
-rw-r--r--packages/merchant-backend-ui/src/pages/ShowOrderDetails.examples.ts28
-rw-r--r--packages/merchant-backend-ui/src/pages/ShowOrderDetails.tsx81
-rw-r--r--packages/merchant-backend-ui/src/render-examples.ts112
-rw-r--r--packages/merchant-backend-ui/src/utils.ts (renamed from packages/merchant-backend-ui/src/pages/DepletedTip.stories.tsx)43
-rw-r--r--packages/merchant-backend-ui/tsconfig.json2
15 files changed, 257 insertions, 569 deletions
diff --git a/packages/merchant-backend-ui/README.md b/packages/merchant-backend-ui/README.md
index bbf826e0e..7f9bcf5dc 100644
--- a/packages/merchant-backend-ui/README.md
+++ b/packages/merchant-backend-ui/README.md
@@ -4,9 +4,7 @@ Merchant Backend pages
This project generate 5 templates for the merchant backend:
-- DepletedTip
- OfferRefund
-- OfferTip
- RequestPayment
- ShowOrderDetails
diff --git a/packages/merchant-backend-ui/build.mjs b/packages/merchant-backend-ui/build.mjs
index fd2a52b9e..e72113dc5 100755
--- a/packages/merchant-backend-ui/build.mjs
+++ b/packages/merchant-backend-ui/build.mjs
@@ -44,7 +44,7 @@ const preactCompatPlugin = {
},
};
-const pages = ["OfferTip","OfferRefund","DepletedTip","RequestPayment","ShowOrderDetails"]
+const pages = ["OfferRefund", "RequestPayment", "ShowOrderDetails"]
const entryPoints = pages.map(p => `src/pages/${p}.tsx`);
let GIT_ROOT = BASE;
@@ -87,8 +87,8 @@ function templatePlugin(options) {
setup(build) {
build.onEnd(() => {
for (const pageName of options.pages) {
- const css = fs.readFileSync(path.join(build.initialOptions.outdir, `${pageName}.css`),"utf8").toString()
- const js = fs.readFileSync(path.join(build.initialOptions.outdir, `${pageName}.js`),"utf8").toString()
+ const css = fs.readFileSync(path.join(build.initialOptions.outdir, `${pageName}.css`), "utf8").toString()
+ const js = fs.readFileSync(path.join(build.initialOptions.outdir, `${pageName}.js`), "utf8").toString()
const location = path.join(build.initialOptions.outdir, toCamelCaseName(pageName))
const render = new Function(`${js}; return page.buildTimeRendering();`)()
const html = `
@@ -113,20 +113,18 @@ function templatePlugin(options) {
};
}
-
-
export const buildConfig = {
entryPoints: [...entryPoints],
bundle: true,
outdir: "dist/pages",
- /*
- * Doing a minified version will replace templatestring to common strings
- * This app is building mustache template with placeholders that will be replaced
- * with string in runtime by the merchant-backend
- *
- * To the date, merchant backend is replacing with multiline string so
- * doing minified version will brake at runtime
- * */
+ /*
+ * Doing a minified version will replace templatestring to common strings
+ * This app is building mustache template with placeholders that will be replaced
+ * with string in runtime by the merchant-backend
+ *
+ * To the date, merchant backend is replacing with multiline string so
+ * doing minified version will brake at runtime
+ * */
minify: false,
loader: {
".svg": "file",
@@ -137,7 +135,7 @@ export const buildConfig = {
'.woff2': 'file',
'.eot': 'file',
},
- target: ["es6"],
+ target: ["es2020"],
format: "iife",
platform: "browser",
sourcemap: false,
@@ -157,8 +155,36 @@ export const buildConfig = {
sourceMap: true,
}),
preactCompatPlugin,
- templatePlugin({pages})
+ templatePlugin({ pages })
],
};
await esbuild.build(buildConfig)
+
+export const testingConfig = {
+ entryPoints: ["src/render-examples.ts"],
+ bundle: true,
+ outdir: "dist/test",
+ minify: false,
+ loader: {
+ ".svg": "file",
+ ".png": "dataurl",
+ ".jpeg": "dataurl",
+ '.ttf': 'file',
+ '.woff': 'file',
+ '.woff2': 'file',
+ '.eot': 'file',
+ },
+ target: ["es2020"],
+ format: "iife",
+ platform: "node",
+ sourcemap: true,
+ define: {
+ __VERSION__: `"${_package.version}"`,
+ __GIT_HASH__: `"${GIT_HASH}"`,
+ },
+ plugins: [
+ ],
+};
+
+await esbuild.build(testingConfig)
diff --git a/packages/merchant-backend-ui/package.json b/packages/merchant-backend-ui/package.json
index e8a72bf09..bd16317f5 100644
--- a/packages/merchant-backend-ui/package.json
+++ b/packages/merchant-backend-ui/package.json
@@ -1,12 +1,12 @@
{
"private": true,
"name": "@gnu-taler/merchant-backend-ui",
- "version": "0.0.5",
+ "version": "0.10.7",
"license": "AGPL-3.0-or-later",
"scripts": {
"compile": "tsc && ./build.mjs",
"build": "pnpm compile",
- "render-examples": "ts-node -O '{\"module\": \"commonjs\"}' -T render-examples.ts dist/pages dist/examples",
+ "render-examples": "node dist/test/render-examples.js dist/pages dist/examples",
"lint-check": "eslint '{src,tests}/**/*.{js,jsx,ts,tsx}'",
"lint-fix": "eslint --fix '{src,tests}/**/*.{js,jsx,ts,tsx}'",
"clean": "rm -rf dist lib tsconfig.tsbuildinfo",
@@ -42,7 +42,7 @@
},
"devDependencies": {
"@babel/core": "7.18.9",
- "@gnu-taler/pogen": "^0.0.5",
+ "@gnu-taler/pogen": "workspace:*",
"@linaria/babel-preset": "3.0.0-beta.22",
"@linaria/core": "3.0.0-beta.22",
"@linaria/react": "3.0.0-beta.22",
@@ -50,6 +50,7 @@
"@linaria/webpack-loader": "3.0.0-beta.22",
"@types/mocha": "^8.2.2",
"@types/mustache": "^4.1.2",
+ "@types/node": "^20.11.13",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"babel-loader": "^8.2.2",
diff --git a/packages/merchant-backend-ui/render-examples.ts b/packages/merchant-backend-ui/render-examples.ts
deleted file mode 100644
index e8c4a8cd0..000000000
--- a/packages/merchant-backend-ui/render-examples.ts
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 mustache from "mustache";
-import fs from "fs";
-import { format, formatDuration, intervalToDuration } from "date-fns";
-
-/**
- * This script will emulate what the merchant backend will do when being requested
- *
- */
-
-const sourceDirectory = process.argv[2];
-const destDirectory = process.argv[3];
-
-if (!sourceDirectory || !destDirectory) {
- console.log("usage: render-mustache <source-directory> <dest-directory>");
- process.exit(1);
-}
-
-if (!fs.existsSync(destDirectory)) {
- fs.mkdirSync(destDirectory);
-}
-
-function fromCamelCaseName(name) {
- const result = name
- .replace(/^[a-z]/, (letter) => `${letter.toUpperCase()}`) //first letter lowercase
- .replace(/_[a-z]/g, (letter) => `${letter[1].toUpperCase()}`); //snake case
- return result;
-}
-/**
- * Load all the html files
- */
-const files = fs.readdirSync(sourceDirectory).filter((f) => /.html/.test(f));
-
-files.forEach((file) => {
- const html = fs.readFileSync(`${sourceDirectory}/${file}`, "utf8");
-
- const testName = file.replace(".en.html", "");
- const exampleFileName = `./src/pages/${fromCamelCaseName(testName)}.examples`;
- if (!fs.existsSync(exampleFileName + ".ts")) {
- console.log(`skipping ${testName}: no examples found`);
- return;
- }
- // eslint-disable-next-line @typescript-eslint/no-var-requires
- const { exampleData } = require(exampleFileName);
-
- Object.keys(exampleData).forEach((exampleName) => {
- const example = exampleData[exampleName];
-
- //enhance the example with more information
- example.contract_terms_json = () => JSON.stringify(example.contract_terms);
- example.contract_terms.timestamp_str = () =>
- example.contract_terms.timestamp &&
- format(example.contract_terms.timestamp.t_s, "dd MMM yyyy HH:mm:ss");
-
- example.contract_terms.hasProducts = () =>
- example.contract_terms.products?.length > 0;
- example.contract_terms.hasAuditors = () =>
- example.contract_terms.auditors?.length > 0;
- example.contract_terms.hasExchanges = () =>
- example.contract_terms.exchanges?.length > 0;
-
- example.contract_terms.products.forEach((p) => {
- p.delivery_date_str = () =>
- p.delivery_date && format(p.delivery_date.t_s, "dd MM yyyy HH:mm:ss");
- p.hasTaxes = () => p.taxes?.length > 0;
- });
- example.contract_terms.has_delivery_info = () =>
- example.contract_terms.delivery_date ||
- example.contract_terms.delivery_location;
-
- example.contract_terms.delivery_date_str = () =>
- example.contract_terms.delivery_date &&
- format(example.contract_terms.delivery_date.t_s, "dd MM yyyy HH:mm:ss");
- example.contract_terms.pay_deadline_str = () =>
- example.contract_terms.pay_deadline &&
- format(example.contract_terms.pay_deadline.t_s, "dd MM yyyy HH:mm:ss");
- example.contract_terms.wire_transfer_deadline_str = () =>
- example.contract_terms.wire_transfer_deadline &&
- format(
- example.contract_terms.wire_transfer_deadline.t_s,
- "dd MM yyyy HH:mm:ss",
- );
- example.contract_terms.refund_deadline_str = () =>
- example.contract_terms.refund_deadline &&
- format(example.contract_terms.refund_deadline.t_s, "dd MM yyyy HH:mm:ss");
- example.contract_terms.auto_refund_str = () =>
- example.contract_terms.auto_refund &&
- formatDuration(
- intervalToDuration({
- start: 0,
- end: example.contract_terms.auto_refund.d_us,
- }),
- );
-
- const output = mustache.render(html, example);
-
- fs.writeFileSync(
- `${destDirectory}/${testName}.${exampleName}.html`,
- output,
- );
- });
-});
diff --git a/packages/merchant-backend-ui/rollup.config.js b/packages/merchant-backend-ui/rollup.config.js
deleted file mode 100644
index 18d72e56b..000000000
--- a/packages/merchant-backend-ui/rollup.config.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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/>
- */
-
-// rollup.config.js
-import linaria from '@linaria/rollup';
-import nodeResolve from "@rollup/plugin-node-resolve";
-import alias from "@rollup/plugin-alias";
-import image from '@rollup/plugin-image';
-import json from "@rollup/plugin-json";
-import ts from "@rollup/plugin-typescript";
-import replace from "@rollup/plugin-replace";
-import css from 'rollup-plugin-css-only';
-import html from '@rollup/plugin-html';
-import commonjs from "@rollup/plugin-commonjs";
-
-const template = async ({
- files,
-}) => {
- const scripts = (files.js || []).map(({ code }) => `<script>${code}</script>`).join('\n');
- const css = (files.css || []).map(({ source }) => `<style>${source}</style>`).join('\n');
- const ssr = (files.js || []).map(({ code }) => code).join('\n');
- const page = new Function(`${ssr}; return page.buildTimeRendering();`)()
- return `
-<!doctype html>
-<html>
- <head>
- ${page.head}
- ${css}
- </head>
- <script id="built_time_data">
- </script>
- <body>
- ${page.body}
- ${scripts}
- <script>page.mount()</script>
- </body>
-</html>`;
-};
-
-const makePlugins = (name) => [
- alias({
- entries: [
- { find: 'react', replacement: 'preact/compat' },
- { find: 'react-dom', replacement: 'preact/compat' }
- ]
- }),
-
- replace({
- "process.env.NODE_ENV": JSON.stringify("production"),
- preventAssignment: true,
- }),
-
- commonjs({
- include: [/node_modules/, /dist/],
- extensions: [".js"],
- ignoreGlobal: true,
- sourceMap: true,
- }),
-
- nodeResolve({
- browser: true,
- preferBuiltins: true,
- }),
-
- json(),
- image(),
-
- linaria({
- sourceMap: process.env.NODE_ENV !== 'production',
- }),
- css(),
- ts({
- sourceMap: false,
- outputToFilesystem: false,
- }),
- html({ template, fileName: name }),
-];
-
-function formatHtmlName(name) {
- return name
- .replace(/^[A-Z]/, letter => `${letter.toLowerCase()}`) //first letter lowercase
- .replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`) //snake case
- .concat(".en.html"); //extension
-}
-
-const pageDefinition = (name) => ({
- input: `src/pages/${name}.tsx`,
- output: {
- file: `dist/pages/${name}.js`,
- format: "iife",
- exports: 'named',
- name: 'page',
- },
- plugins: makePlugins(formatHtmlName(name)),
-});
-
-export default [
- pageDefinition("OfferTip"),
- pageDefinition("OfferRefund"),
- pageDefinition("DepletedTip"),
- pageDefinition("RequestPayment"),
- pageDefinition("ShowOrderDetails"),
-]
diff --git a/packages/merchant-backend-ui/src/pages/DepletedTip.tsx b/packages/merchant-backend-ui/src/pages/DepletedTip.tsx
deleted file mode 100644
index 61fc52cdf..000000000
--- a/packages/merchant-backend-ui/src/pages/DepletedTip.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { Fragment, h, render, VNode } from "preact";
-import { render as renderToString } from "preact-render-to-string";
-import { Footer } from "../components/Footer";
-import "../css/pure-min.css";
-import "../css/style.css";
-import { Page } from "../styled";
-
-function Head(): VNode {
- return <title>Status of your tip</title>;
-}
-
-export function DepletedTip(): VNode {
- return (
- <Page>
- <section>
- <h1>Tip already collected</h1>
- <div>You have already collected this tip.</div>
- </section>
- <Footer />
- </Page>
- );
-}
-
-export function mount(): void {
- try {
- render(<DepletedTip />, document.body);
- } catch (e) {
- console.error("got error", e);
- if (e instanceof Error) {
- document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
- }
- }
-}
-
-export function buildTimeRendering(): { head: string; body: string } {
- return {
- head: renderToString(<Head />),
- body: renderToString(<DepletedTip />),
- };
-}
diff --git a/packages/merchant-backend-ui/src/pages/OfferRefund.tsx b/packages/merchant-backend-ui/src/pages/OfferRefund.tsx
index ffd657e7e..b1cf63572 100644
--- a/packages/merchant-backend-ui/src/pages/OfferRefund.tsx
+++ b/packages/merchant-backend-ui/src/pages/OfferRefund.tsx
@@ -52,6 +52,8 @@ function Head({ order_summary }: { order_summary?: string }): VNode {
return <Fragment>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="taler-support" content="uri" />
+ <meta name="taler-uri" content="{{ taler_refund_uri }}"></meta>
<noscript>
<meta http-equiv="refresh" content="1" />
</noscript>
diff --git a/packages/merchant-backend-ui/src/pages/OfferTip.stories.tsx b/packages/merchant-backend-ui/src/pages/OfferTip.stories.tsx
deleted file mode 100644
index dfbf71fff..000000000
--- a/packages/merchant-backend-ui/src/pages/OfferTip.stories.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 Taler Systems S.A.
-
- GNU Taler is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along with
- GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-/**
-*
-* @author Sebastian Javier Marchano (sebasjm)
-*/
-
-import { h, VNode, FunctionalComponent } from 'preact';
-import { createSVG } from '../components/QR';
-import { OfferTip as TestedComponent } from './OfferTip';
-
-
-export default {
- title: 'OfferTip',
- component: TestedComponent,
- argTypes: {
- },
-};
-
-function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
- const r = (args: any) => <Component {...args} />
- r.args = props
- return r
-}
-
-const TIP_URI_EXAMPLE = 'taler+http://tip/merchant-backend.taler/2021.242-01G2X4275RBWG/?c=66BE594PDZR24744J6EQK52XM0'
-
-export const Example = createExample(TestedComponent, {
- tipURI: TIP_URI_EXAMPLE,
- qr_code: createSVG(TIP_URI_EXAMPLE)
-});
diff --git a/packages/merchant-backend-ui/src/pages/OfferTip.tsx b/packages/merchant-backend-ui/src/pages/OfferTip.tsx
deleted file mode 100644
index cb3ce33fd..000000000
--- a/packages/merchant-backend-ui/src/pages/OfferTip.tsx
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- This file is part of GNU Taler
- (C) 2021 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 { Fragment, h, render, VNode } from 'preact';
-import { render as renderToString } from 'preact-render-to-string';
-import { useEffect } from 'preact/hooks';
-import { Footer } from '../components/Footer';
-import { QR } from '../components/QR';
-import "../css/pure-min.css";
-import "../css/style.css";
-import { Page, QRPlaceholder, WalletLink } from '../styled';
-
-
-/**
- * This page creates a tip offer QR code
- *
- * It will build into a mustache html template for server side rendering
- *
- * server side rendering params:
- * - tip_status_url
- * - taler_tip_qrcode_svg
- * - taler_tip_uri
- *
- * request params:
- * - tip_uri
- * - tip_status_url
- */
-
-interface Props {
- tipURI?: string,
- tip_status_url?: string,
- qr_code?: string,
-}
-
-export function Head(): VNode {
- return <Fragment>
- <meta charSet="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <noscript>
- <meta http-equiv="refresh" content="1" />
- </noscript>
- <title>Tip available</title>
- </Fragment>
-}
-
-export function OfferTip({ tipURI, qr_code, tip_status_url }: Props): VNode {
- useEffect(() => {
- const longpollDelayMs = 60 * 1000;
- const delayMs = 500;
- let checkUrl: URL;
- try {
- checkUrl = new URL(tip_status_url ? tip_status_url : "{{& tip_status_url }}");
- } catch (e) {
- return;
- }
- checkUrl.searchParams.set("timeout_ms", longpollDelayMs.toString());
-
- function check() {
- let retried = false;
- function retryOnce() {
- if (!retried) {
- retried = true;
- check();
- }
- }
- const req = new XMLHttpRequest();
- req.onreadystatechange = function () {
- if (req.readyState === XMLHttpRequest.DONE) {
- if (req.status === 410) {
- window.location.reload();
- }
- setTimeout(retryOnce, delayMs);
- }
- };
- req.onerror = function () {
- setTimeout(retryOnce, delayMs);
- }
- req.open("GET", checkUrl.href);
- req.send();
- }
-
- setTimeout(check, delayMs);
- })
- return <Page>
- <section>
- <h1 >Collect Taler tip</h1>
- <p>
- Scan this QR code with your Taler mobile wallet:
- </p>
- <QRPlaceholder dangerouslySetInnerHTML={{ __html: qr_code ? qr_code : `{{{ taler_tip_qrcode_svg }}}` }} />
- <p>
- <WalletLink href={tipURI ? tipURI : `{{ taler_tip_uri }}`}>
- Or open your Taler wallet
- </WalletLink>
- </p>
- <p>
- <a href="https://wallet.taler.net/">Don't have a Taler wallet yet? Install it!</a>
- </p>
- </section>
- <Footer />
- </Page>
-}
-
-export function mount(): void {
- try {
- const fromLocation = new URL(window.location.href).searchParams
-
- const uri = fromLocation.get('tip_uri') || undefined
- const tsu = fromLocation.get('tip_status_url') || undefined
-
- render(<OfferTip tipURI={uri} tip_status_url={tsu} />, document.body);
- } catch (e) {
- console.error("got error", e);
- if (e instanceof Error) {
- document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
- }
- }
-}
-
-export function buildTimeRendering(): { head: string, body: string } {
- return {
- head: renderToString(<Head />),
- body: renderToString(<OfferTip />)
- }
-}
diff --git a/packages/merchant-backend-ui/src/pages/RequestPayment.tsx b/packages/merchant-backend-ui/src/pages/RequestPayment.tsx
index 86c7e6f60..513438ba2 100644
--- a/packages/merchant-backend-ui/src/pages/RequestPayment.tsx
+++ b/packages/merchant-backend-ui/src/pages/RequestPayment.tsx
@@ -55,6 +55,8 @@ function Head({ order_summary }: { order_summary?: string }): VNode {
<Fragment>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="taler-support" content="uri" />
+ <meta name="taler-uri" content="{{ taler_pay_uri }}"></meta>
<noscript>
<meta http-equiv="refresh" content="1" />
</noscript>
@@ -81,7 +83,7 @@ export function RequestPayment({
} catch (e) {
return;
}
- checkUrl.searchParams.set("timeout_s", longpollDelayMs.toString());
+ checkUrl.searchParams.set("timeout_ms", longpollDelayMs.toString());
const delayMs = 500;
function check() {
let retried = false;
@@ -99,6 +101,8 @@ export function RequestPayment({
const resp = JSON.parse(req.responseText);
if (resp.fulfillment_url) {
window.location.replace(resp.fulfillment_url);
+ } else {
+ window.location.reload()
}
} catch (e) {
console.error("could not parse response:", e);
@@ -109,6 +113,8 @@ export function RequestPayment({
const resp = JSON.parse(req.responseText);
if (resp.fulfillment_url) {
window.location.replace(resp.fulfillment_url);
+ } else {
+ window.location.reload()
}
} catch (e) {
console.error("could not parse response:", e);
diff --git a/packages/merchant-backend-ui/src/pages/ShowOrderDetails.examples.ts b/packages/merchant-backend-ui/src/pages/ShowOrderDetails.examples.ts
index d80401129..86992c9e1 100644
--- a/packages/merchant-backend-ui/src/pages/ShowOrderDetails.examples.ts
+++ b/packages/merchant-backend-ui/src/pages/ShowOrderDetails.examples.ts
@@ -61,7 +61,7 @@ const defaultContractTerms: MerchantBackend.ContractTerms = {
},
wire_method: 'x-taler-bank',
wire_transfer_deadline: {
- t_s: Math.round(new Date().getTime() / 1000) + 3 * 24 * 60 * 60
+ t_s: Math.round(new Date().getTime() / 1000) + 3 * 24 * 60 * 60
},
};
@@ -224,4 +224,30 @@ export const exampleData: { [name: string]: Props } = {
fulfillment_message: "Congratulations! You just purchased an valuable item!"
},
},
+ WithFulfillmentMessage: {
+ order_summary: 'this is the order with fulfillment message',
+ contract_terms: {
+ ...defaultContractTerms,
+ fulfillment_message: "Congratulations! You just purchased an valuable item!"
+ },
+ },
+ WithoutWireTransferDeadline: {
+ order_summary: 'this is the order without transfer deadline',
+ contract_terms: {
+ ...defaultContractTerms,
+ // @ts-ignore
+ wire_transfer_deadline: undefined,
+ },
+ },
+ ZeroFee: {
+ order_summary: 'example with zero fee',
+ contract_terms: {
+ ...defaultContractTerms,
+ // @ts-ignore
+ max_fee: undefined,
+ // @ts-ignore
+ max_wire_fee: undefined,
+ fulfillment_message: "Congratulations! You just purchased an valuable item!"
+ },
+ },
}
diff --git a/packages/merchant-backend-ui/src/pages/ShowOrderDetails.tsx b/packages/merchant-backend-ui/src/pages/ShowOrderDetails.tsx
index ca93c3f7d..7d11eb21d 100644
--- a/packages/merchant-backend-ui/src/pages/ShowOrderDetails.tsx
+++ b/packages/merchant-backend-ui/src/pages/ShowOrderDetails.tsx
@@ -27,6 +27,7 @@ import "../css/pure-min.css";
import "../css/style.css";
import { MerchantBackend } from "../declaration";
import { Page, InfoBox, TableExpanded, TableSimple } from "../styled";
+import { TIME_DATE_FORMAT } from "../utils";
/**
* This page creates a payment request QR code
@@ -56,6 +57,7 @@ function Head({ order_summary }: { order_summary?: string }): VNode {
<Fragment>
<meta charSet="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="taler-support" content="uri" />
<noscript>
<meta http-equiv="refresh" content="1" />
</noscript>
@@ -79,7 +81,7 @@ function Location({
location: MerchantBackend.Location | undefined;
btr?: boolean;
}) {
- //FIXME: mustache strings show be constructed in a way that ends in the final output of the html but is not present in the
+ //FIXME: mustache strings will be constructed in a way that ends in the final output of the html but is not present in the
// javascript code, otherwise when mustache render engine run over the html it will also replace string in the javascript code
// that is made to run when the browser has javascript enable leading into undefined behavior.
// that's why in the next fields we are using concatenations to build the mustache placeholder.
@@ -196,9 +198,9 @@ export function ShowOrderDetails({
{contract_terms?.timestamp
? contract_terms?.timestamp.t_s != "never"
? format(
- contract_terms?.timestamp.t_s,
- "dd MMM yyyy HH:mm:ss",
- )
+ contract_terms?.timestamp.t_s * 1000,
+ TIME_DATE_FORMAT,
+ )
: "never"
: `{{ contract_terms.timestamp_str }}`}{" "}
</dd>
@@ -256,9 +258,9 @@ export function ShowOrderDetails({
{p.delivery_date
? p.delivery_date.t_s != "never"
? format(
- p.delivery_date.t_s,
- "dd MMM yyyy HH:mm:ss",
- )
+ p.delivery_date.t_s,
+ TIME_DATE_FORMAT,
+ )
: "never"
: `{{ delivery_date_str }}`}{" "}
</dd>
@@ -306,9 +308,9 @@ export function ShowOrderDetails({
{contract_terms?.delivery_date
? contract_terms?.delivery_date.t_s != "never"
? format(
- contract_terms?.delivery_date.t_s,
- "dd MMM yyyy HH:mm:ss",
- )
+ contract_terms?.delivery_date.t_s,
+ TIME_DATE_FORMAT,
+ )
: "never"
: `{{ contract_terms.delivery_date_str }}`}{" "}
</dd>
@@ -336,48 +338,47 @@ export function ShowOrderDetails({
<section>
<h2>Full payment information</h2>
<TableExpanded>
- <dt>Amount paid:</dt>
- <dd>{contract_terms?.amount || `{{ contract_terms.amount }}`}</dd>
- <dt>Wire transfer method:</dt>
- <dd>
- {contract_terms?.wire_method ||
- `{{ contract_terms.wire_method }}`}
- </dd>
- <dt>Payment deadline:</dt>
- <dd>
- {contract_terms?.pay_deadline
- ? contract_terms?.pay_deadline.t_s != "never"
- ? format(
- contract_terms?.pay_deadline.t_s,
- "dd MMM yyyy HH:mm:ss",
- )
- : "never"
- : `{{ contract_terms.pay_deadline_str }}`}{" "}
- </dd>
<dt>Exchange transfer deadline:</dt>
+ {btr && `{{` + `#contract_terms.wire_transfer_deadline_str}}`}
<dd>
{contract_terms?.wire_transfer_deadline
? contract_terms?.wire_transfer_deadline.t_s != "never"
? format(
- contract_terms?.wire_transfer_deadline.t_s,
- "dd MMM yyyy HH:mm:ss",
- )
+ contract_terms?.wire_transfer_deadline.t_s * 1000,
+ TIME_DATE_FORMAT,
+ )
: "never"
: `{{ contract_terms.wire_transfer_deadline_str }}`}{" "}
</dd>
+ {btr && `{{` + `/contract_terms.wire_transfer_deadline_str}}`}
+
+ {btr && `{{` + `^contract_terms.wire_transfer_deadline_str}}`}
+ <dd>
+ Wire transfer settled.
+ </dd>
+ {btr && `{{` + `/contract_terms.wire_transfer_deadline_str}}`}
+
+ {btr && `{{` + `#contract_terms.max_fee}}`}
<dt>Maximum deposit fee:</dt>
<dd>{contract_terms?.max_fee || `{{ contract_terms.max_fee }}`}</dd>
+ {btr && `{{` + `/contract_terms.max_fee}}`}
+
+ {btr && `{{` + `#contract_terms.max_wire_fee}}`}
<dt>Maximum wire fee:</dt>
<dd>
{contract_terms?.max_wire_fee ||
`{{ contract_terms.max_wire_fee }}`}
</dd>
+ {btr && `{{` + `/contract_terms.max_wire_fee}}`}
+
+ {btr && `{{` + `#contract_terms.wire_fee_amortization}}`}
<dt>Wire fee amortization:</dt>
<dd>
{contract_terms?.wire_fee_amortization ||
`{{ contract_terms.wire_fee_amortization }}`}{" "}
transactions
</dd>
+ {btr && `{{` + `/contract_terms.wire_fee_amortization}}`}
</TableExpanded>
</section>
@@ -389,9 +390,9 @@ export function ShowOrderDetails({
{contract_terms?.refund_deadline
? contract_terms?.refund_deadline.t_s != "never"
? format(
- contract_terms?.refund_deadline.t_s,
- "dd MMM yyyy HH:mm:ss",
- )
+ contract_terms?.refund_deadline.t_s * 1000,
+ TIME_DATE_FORMAT,
+ )
: "never"
: `{{ contract_terms.refund_deadline_str }}`}{" "}
</dd>
@@ -404,11 +405,11 @@ export function ShowOrderDetails({
{contract_terms?.auto_refund
? contract_terms?.auto_refund.d_us != "forever"
? formatDuration(
- intervalToDuration({
- start: 0,
- end: contract_terms?.auto_refund.d_us,
- }),
- )
+ intervalToDuration({
+ start: 0,
+ end: contract_terms?.auto_refund.d_us,
+ }),
+ )
: "forever"
: `{{ contract_terms.auto_refund_str }}`}{" "}
</dd>
@@ -539,7 +540,7 @@ export function mount(): void {
let contractTerms: MerchantBackend.ContractTerms | undefined;
try {
contractTerms = JSON.parse((window as any).contractTermsStr);
- } catch {}
+ } catch { }
render(
<ShowOrderDetails
diff --git a/packages/merchant-backend-ui/src/render-examples.ts b/packages/merchant-backend-ui/src/render-examples.ts
new file mode 100644
index 000000000..957e06a58
--- /dev/null
+++ b/packages/merchant-backend-ui/src/render-examples.ts
@@ -0,0 +1,112 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 fs from "fs";
+import mustache from "mustache";
+import { createDateToStringFunction, createDurationToStringFunction, createNonEmptyFunction } from "./utils.js"
+import { exampleData as ShowOrderDetailsExamples } from "./pages/ShowOrderDetails.examples.js";
+/**
+ * This script will emulate what the merchant backend will do when being requested
+ *
+ */
+
+const templateDirectory = process.argv[2];
+const destDirectory = process.argv[3];
+
+if (!templateDirectory || !destDirectory) {
+ console.log("usage: render-mustache <source-directory> <dest-directory>");
+ process.exit(1);
+}
+
+if (!fs.existsSync(destDirectory)) {
+ fs.mkdirSync(destDirectory);
+}
+
+function fromCamelCaseName(name: string) {
+ const result = name
+ .replace(/^[a-z]/, (letter) => `${letter.toUpperCase()}`) //first letter lowercase
+ .replace(/_[a-z]/g, (letter) => `${letter[1].toUpperCase()}`); //snake case
+ return result;
+}
+/**
+ * Load all the html files
+ */
+const templateFiles = fs.readdirSync(templateDirectory).filter((f) => /.html/.test(f));
+const exampleByTemplate: Record<string, any> = {
+ "show_order_details.en.html": ShowOrderDetailsExamples
+}
+
+templateFiles.forEach((templateFile) => {
+ const html = fs.readFileSync(`${templateDirectory}/${templateFile}`, "utf8");
+
+ const templateFileWithoutExt = templateFile.replace(".en.html", "");
+ // const exampleFileName = `src/pages/${fromCamelCaseName(testName)}.examples`;
+ // if (!fs.existsSync(`./${exampleFileName}.ts`)) {
+ // console.log(`- skipping ${testName}: no examples found`);
+ // return;
+ // }
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
+ // const pepe = `./${exampleFileName}.ts`
+ // const { exampleData } = require(pepe);
+
+ const exampleData = exampleByTemplate[templateFile]
+ if (!exampleData) {
+ console.log(`- skipping ${templateFile}: no examples found`);
+ return;
+ }
+ const exampleNames = Object.keys(exampleData)
+ console.log(`+ rendering ${templateFile}: ${exampleNames.length} examples`);
+ exampleNames.forEach((exampleName) => {
+ const example = exampleData[exampleName];
+
+ //enhance the example with more information
+ example.contract_terms_json = () => JSON.stringify(example.contract_terms);
+
+ example.contract_terms.timestamp_str = createDateToStringFunction(example.contract_terms.timestamp)
+
+ example.contract_terms.hasProducts = createNonEmptyFunction(example.contract_terms.products)
+ example.contract_terms.hasAuditors = createNonEmptyFunction(example.contract_terms.auditors)
+ example.contract_terms.hasExchanges = createNonEmptyFunction(example.contract_terms.exchanges)
+
+ example.contract_terms.products.forEach((p: any) => {
+ p.delivery_date_str = createDateToStringFunction(p.delivery_date)
+ p.hasTaxes = createNonEmptyFunction(p.taxes)
+ });
+
+ example.contract_terms.has_delivery_info = () =>
+ example.contract_terms.delivery_date ||
+ example.contract_terms.delivery_location;
+
+ example.contract_terms.delivery_date_str = createDateToStringFunction(example.contract_terms.delivery_date)
+ example.contract_terms.pay_deadline_str = createDateToStringFunction(example.contract_terms.pay_deadline)
+ example.contract_terms.wire_transfer_deadline_str = createDateToStringFunction(example.contract_terms.wire_transfer_deadline)
+
+ example.contract_terms.refund_deadline_str = createDateToStringFunction(example.contract_terms.refund_deadline)
+ example.contract_terms.auto_refund_str = createDurationToStringFunction(example.contract_terms.auto_refund)
+
+ const output = mustache.render(html, example);
+
+ fs.writeFileSync(
+ `${destDirectory}/${templateFileWithoutExt}.${exampleName}.html`,
+ output,
+ );
+ });
+});
diff --git a/packages/merchant-backend-ui/src/pages/DepletedTip.stories.tsx b/packages/merchant-backend-ui/src/utils.ts
index 41c3e26a5..0a420aa22 100644
--- a/packages/merchant-backend-ui/src/pages/DepletedTip.stories.tsx
+++ b/packages/merchant-backend-ui/src/utils.ts
@@ -14,27 +14,28 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-/**
- *
- * @author Sebastian Javier Marchano (sebasjm)
- */
+import { format, formatDuration, intervalToDuration } from "date-fns";
+
+export const TIME_DATE_FORMAT = "dd MMM yyyy HH:mm:ss"
+
+export function createDateToStringFunction(date: any) {
+ return () => {
+ if (!date) return "";
+ return format(date.t_s * 1000, TIME_DATE_FORMAT);
+ }
+}
+
+export function createDurationToStringFunction(duration: any) {
+ return () => {
+ if (!duration) return "";
+ return formatDuration(intervalToDuration({ start: 0, end: duration.d_us }));
+ }
+}
-import { h, VNode, FunctionalComponent } from "preact";
-import { DepletedTip as TestedComponent } from "./DepletedTip";
-
-export default {
- title: "DepletedTip",
- component: TestedComponent,
- argTypes: {},
-};
-
-function createExample<Props>(
- Component: FunctionalComponent<Props>,
- props: Partial<Props>,
-) {
- const r = (args: any) => <Component {...args} />;
- r.args = props;
- return r;
+export function createNonEmptyFunction(list: any) {
+ return () => {
+ if (!list) return false;
+ return list.length > 0;
+ }
}
-export const Example = createExample(TestedComponent, {});
diff --git a/packages/merchant-backend-ui/tsconfig.json b/packages/merchant-backend-ui/tsconfig.json
index 7a4d70a17..d9cd57c4e 100644
--- a/packages/merchant-backend-ui/tsconfig.json
+++ b/packages/merchant-backend-ui/tsconfig.json
@@ -1,7 +1,7 @@
{
"compilerOptions": {
/* Basic Options */
- "target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
+ "target": "ES2020", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
"module": "ESNext", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation: */
"allowJs": true, /* Allow javascript files to be compiled. */