From 3e060b80428943c6562250a6ff77eff10a0259b7 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Mon, 24 Oct 2022 10:46:14 +0200 Subject: repo: integrate packages from former merchant-backoffice.git --- packages/demobank-ui/.gitignore | 5 + packages/demobank-ui/.storybook/.babelrc | 25 + packages/demobank-ui/.storybook/main.js | 57 + packages/demobank-ui/.storybook/preview.js | 55 + packages/demobank-ui/README.md | 19 + packages/demobank-ui/TODO | 45 + packages/demobank-ui/build-bank-translations.sh | 32 + packages/demobank-ui/contrib/po2ts | 42 + packages/demobank-ui/mocks/json-server/db.json | 4 + packages/demobank-ui/mocks/window.js | 27 + packages/demobank-ui/package.json | 100 + packages/demobank-ui/preact.config.js | 70 + packages/demobank-ui/preact.mock.js | 55 + packages/demobank-ui/preact.single-config.js | 60 + packages/demobank-ui/remove-link-stylesheet.sh | 8 + packages/demobank-ui/src/.babelrc | 3 + packages/demobank-ui/src/assets/empty.png | Bin 0 -> 2785 bytes packages/demobank-ui/src/assets/example/id1.jpg | Bin 0 -> 103558 bytes packages/demobank-ui/src/assets/favicon.ico | Bin 0 -> 15086 bytes .../src/assets/icons/android-chrome-192x192.png | Bin 0 -> 14058 bytes .../src/assets/icons/android-chrome-512x512.png | Bin 0 -> 51484 bytes .../src/assets/icons/apple-touch-icon.png | Bin 0 -> 12746 bytes .../src/assets/icons/auth_method/email.svg | 1 + .../src/assets/icons/auth_method/postal.svg | 1 + .../src/assets/icons/auth_method/question.svg | 1 + .../src/assets/icons/auth_method/sms.svg | 1 + .../src/assets/icons/auth_method/video.svg | 1 + .../demobank-ui/src/assets/icons/favicon-16x16.png | Bin 0 -> 626 bytes .../demobank-ui/src/assets/icons/favicon-32x32.png | Bin 0 -> 1487 bytes .../demobank-ui/src/assets/icons/languageicon.svg | 48 + .../src/assets/icons/mstile-150x150.png | Bin 0 -> 9050 bytes packages/demobank-ui/src/assets/logo-white.svg | 45 + packages/demobank-ui/src/assets/logo.jpeg | Bin 0 -> 39336 bytes .../demobank-ui/src/components/AsyncButton.tsx | 66 + packages/demobank-ui/src/components/FileButton.tsx | 57 + .../demobank-ui/src/components/Notifications.tsx | 74 + packages/demobank-ui/src/components/QR.tsx | 48 + packages/demobank-ui/src/components/app.tsx | 14 + .../src/components/fields/DateInput.tsx | 90 + .../src/components/fields/EmailInput.tsx | 57 + .../src/components/fields/FileInput.tsx | 104 + .../src/components/fields/ImageInput.tsx | 93 + .../src/components/fields/NumberInput.tsx | 56 + .../src/components/fields/TextInput.tsx | 68 + .../src/components/menu/LangSelector.tsx | 101 + .../src/components/menu/NavigationBar.tsx | 53 + .../demobank-ui/src/components/menu/SideBar.tsx | 73 + packages/demobank-ui/src/components/menu/index.tsx | 135 ++ .../src/components/picker/DatePicker.tsx | 356 ++++ .../components/picker/DurationPicker.stories.tsx | 55 + .../src/components/picker/DurationPicker.tsx | 211 ++ packages/demobank-ui/src/context/translation.ts | 73 + packages/demobank-ui/src/declaration.d.ts | 20 + packages/demobank-ui/src/hooks/async.ts | 80 + packages/demobank-ui/src/hooks/index.ts | 151 ++ packages/demobank-ui/src/i18n/bank.pot | 258 +++ packages/demobank-ui/src/i18n/de.po | 257 +++ packages/demobank-ui/src/i18n/en.po | 266 +++ packages/demobank-ui/src/i18n/index.tsx | 211 ++ packages/demobank-ui/src/i18n/it.po | 258 +++ packages/demobank-ui/src/i18n/poheader | 27 + packages/demobank-ui/src/i18n/strings-prelude | 19 + packages/demobank-ui/src/i18n/strings.ts | 472 +++++ packages/demobank-ui/src/index.tsx | 3 + packages/demobank-ui/src/manifest.json | 21 + packages/demobank-ui/src/pages/home/index.tsx | 2018 ++++++++++++++++++++ packages/demobank-ui/src/pages/notfound/index.tsx | 16 + packages/demobank-ui/src/pages/notfound/style.css | 0 .../src/pages/profile/index.stories.tsx | 38 + packages/demobank-ui/src/pages/profile/index.tsx | 42 + packages/demobank-ui/src/pages/profile/style.css | 0 packages/demobank-ui/src/scss/DurationPicker.scss | 70 + packages/demobank-ui/src/scss/_aside.scss | 128 ++ packages/demobank-ui/src/scss/_card.scss | 69 + .../demobank-ui/src/scss/_custom-calendar.scss | 263 +++ packages/demobank-ui/src/scss/_footer.scss | 35 + packages/demobank-ui/src/scss/_form.scss | 71 + packages/demobank-ui/src/scss/_hero-bar.scss | 55 + packages/demobank-ui/src/scss/_loading.scss | 51 + packages/demobank-ui/src/scss/_main-section.scss | 24 + packages/demobank-ui/src/scss/_misc.scss | 50 + packages/demobank-ui/src/scss/_mixins.scss | 34 + packages/demobank-ui/src/scss/_modal.scss | 35 + packages/demobank-ui/src/scss/_nav-bar.scss | 144 ++ packages/demobank-ui/src/scss/_table.scss | 179 ++ packages/demobank-ui/src/scss/_theme-default.scss | 136 ++ packages/demobank-ui/src/scss/_tiles.scss | 24 + packages/demobank-ui/src/scss/_title-bar.scss | 50 + packages/demobank-ui/src/scss/bank.scss | 264 +++ packages/demobank-ui/src/scss/colors-bank.scss | 31 + packages/demobank-ui/src/scss/demo.scss | 157 ++ .../src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf | Bin 0 -> 43752 bytes packages/demobank-ui/src/scss/fonts/nunito.css | 22 + .../fonts/materialdesignicons-webfont-4.9.95.eot | Bin 0 -> 844600 bytes .../fonts/materialdesignicons-webfont-4.9.95.ttf | Bin 0 -> 844380 bytes .../fonts/materialdesignicons-webfont-4.9.95.woff | Bin 0 -> 404384 bytes .../fonts/materialdesignicons-webfont-4.9.95.woff2 | Bin 0 -> 283040 bytes .../scss/icons/materialdesignicons-4.9.95.min.css | 3 + packages/demobank-ui/src/scss/libs/_all.scss | 29 + packages/demobank-ui/src/scss/main.scss | 4 + packages/demobank-ui/src/scss/pure.scss | 1328 +++++++++++++ packages/demobank-ui/src/style/index.css | 0 packages/demobank-ui/src/template.html | 52 + .../demobank-ui/tests/__mocks__/browserMocks.ts | 21 + packages/demobank-ui/tests/__mocks__/fileMocks.ts | 3 + packages/demobank-ui/tests/__mocks__/setupTests.ts | 6 + packages/demobank-ui/tests/__tests__/homepage.js | 466 +++++ packages/demobank-ui/tests/declarations.d.ts | 3 + packages/demobank-ui/tsconfig.json | 60 + 109 files changed, 10513 insertions(+) create mode 100644 packages/demobank-ui/.gitignore create mode 100644 packages/demobank-ui/.storybook/.babelrc create mode 100644 packages/demobank-ui/.storybook/main.js create mode 100644 packages/demobank-ui/.storybook/preview.js create mode 100644 packages/demobank-ui/README.md create mode 100644 packages/demobank-ui/TODO create mode 100755 packages/demobank-ui/build-bank-translations.sh create mode 100755 packages/demobank-ui/contrib/po2ts create mode 100644 packages/demobank-ui/mocks/json-server/db.json create mode 100644 packages/demobank-ui/mocks/window.js create mode 100644 packages/demobank-ui/package.json create mode 100644 packages/demobank-ui/preact.config.js create mode 100644 packages/demobank-ui/preact.mock.js create mode 100644 packages/demobank-ui/preact.single-config.js create mode 100755 packages/demobank-ui/remove-link-stylesheet.sh create mode 100644 packages/demobank-ui/src/.babelrc create mode 100644 packages/demobank-ui/src/assets/empty.png create mode 100644 packages/demobank-ui/src/assets/example/id1.jpg create mode 100644 packages/demobank-ui/src/assets/favicon.ico create mode 100644 packages/demobank-ui/src/assets/icons/android-chrome-192x192.png create mode 100644 packages/demobank-ui/src/assets/icons/android-chrome-512x512.png create mode 100644 packages/demobank-ui/src/assets/icons/apple-touch-icon.png create mode 100644 packages/demobank-ui/src/assets/icons/auth_method/email.svg create mode 100644 packages/demobank-ui/src/assets/icons/auth_method/postal.svg create mode 100644 packages/demobank-ui/src/assets/icons/auth_method/question.svg create mode 100644 packages/demobank-ui/src/assets/icons/auth_method/sms.svg create mode 100644 packages/demobank-ui/src/assets/icons/auth_method/video.svg create mode 100644 packages/demobank-ui/src/assets/icons/favicon-16x16.png create mode 100644 packages/demobank-ui/src/assets/icons/favicon-32x32.png create mode 100644 packages/demobank-ui/src/assets/icons/languageicon.svg create mode 100644 packages/demobank-ui/src/assets/icons/mstile-150x150.png create mode 100644 packages/demobank-ui/src/assets/logo-white.svg create mode 100644 packages/demobank-ui/src/assets/logo.jpeg create mode 100644 packages/demobank-ui/src/components/AsyncButton.tsx create mode 100644 packages/demobank-ui/src/components/FileButton.tsx create mode 100644 packages/demobank-ui/src/components/Notifications.tsx create mode 100644 packages/demobank-ui/src/components/QR.tsx create mode 100644 packages/demobank-ui/src/components/app.tsx create mode 100644 packages/demobank-ui/src/components/fields/DateInput.tsx create mode 100644 packages/demobank-ui/src/components/fields/EmailInput.tsx create mode 100644 packages/demobank-ui/src/components/fields/FileInput.tsx create mode 100644 packages/demobank-ui/src/components/fields/ImageInput.tsx create mode 100644 packages/demobank-ui/src/components/fields/NumberInput.tsx create mode 100644 packages/demobank-ui/src/components/fields/TextInput.tsx create mode 100644 packages/demobank-ui/src/components/menu/LangSelector.tsx create mode 100644 packages/demobank-ui/src/components/menu/NavigationBar.tsx create mode 100644 packages/demobank-ui/src/components/menu/SideBar.tsx create mode 100644 packages/demobank-ui/src/components/menu/index.tsx create mode 100644 packages/demobank-ui/src/components/picker/DatePicker.tsx create mode 100644 packages/demobank-ui/src/components/picker/DurationPicker.stories.tsx create mode 100644 packages/demobank-ui/src/components/picker/DurationPicker.tsx create mode 100644 packages/demobank-ui/src/context/translation.ts create mode 100644 packages/demobank-ui/src/declaration.d.ts create mode 100644 packages/demobank-ui/src/hooks/async.ts create mode 100644 packages/demobank-ui/src/hooks/index.ts create mode 100644 packages/demobank-ui/src/i18n/bank.pot create mode 100644 packages/demobank-ui/src/i18n/de.po create mode 100644 packages/demobank-ui/src/i18n/en.po create mode 100644 packages/demobank-ui/src/i18n/index.tsx create mode 100644 packages/demobank-ui/src/i18n/it.po create mode 100644 packages/demobank-ui/src/i18n/poheader create mode 100644 packages/demobank-ui/src/i18n/strings-prelude create mode 100644 packages/demobank-ui/src/i18n/strings.ts create mode 100644 packages/demobank-ui/src/index.tsx create mode 100644 packages/demobank-ui/src/manifest.json create mode 100644 packages/demobank-ui/src/pages/home/index.tsx create mode 100644 packages/demobank-ui/src/pages/notfound/index.tsx create mode 100644 packages/demobank-ui/src/pages/notfound/style.css create mode 100644 packages/demobank-ui/src/pages/profile/index.stories.tsx create mode 100644 packages/demobank-ui/src/pages/profile/index.tsx create mode 100644 packages/demobank-ui/src/pages/profile/style.css create mode 100644 packages/demobank-ui/src/scss/DurationPicker.scss create mode 100644 packages/demobank-ui/src/scss/_aside.scss create mode 100644 packages/demobank-ui/src/scss/_card.scss create mode 100644 packages/demobank-ui/src/scss/_custom-calendar.scss create mode 100644 packages/demobank-ui/src/scss/_footer.scss create mode 100644 packages/demobank-ui/src/scss/_form.scss create mode 100644 packages/demobank-ui/src/scss/_hero-bar.scss create mode 100644 packages/demobank-ui/src/scss/_loading.scss create mode 100644 packages/demobank-ui/src/scss/_main-section.scss create mode 100644 packages/demobank-ui/src/scss/_misc.scss create mode 100644 packages/demobank-ui/src/scss/_mixins.scss create mode 100644 packages/demobank-ui/src/scss/_modal.scss create mode 100644 packages/demobank-ui/src/scss/_nav-bar.scss create mode 100644 packages/demobank-ui/src/scss/_table.scss create mode 100644 packages/demobank-ui/src/scss/_theme-default.scss create mode 100644 packages/demobank-ui/src/scss/_tiles.scss create mode 100644 packages/demobank-ui/src/scss/_title-bar.scss create mode 100644 packages/demobank-ui/src/scss/bank.scss create mode 100644 packages/demobank-ui/src/scss/colors-bank.scss create mode 100644 packages/demobank-ui/src/scss/demo.scss create mode 100644 packages/demobank-ui/src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf create mode 100644 packages/demobank-ui/src/scss/fonts/nunito.css create mode 100644 packages/demobank-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.eot create mode 100644 packages/demobank-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.ttf create mode 100644 packages/demobank-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff create mode 100644 packages/demobank-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff2 create mode 100644 packages/demobank-ui/src/scss/icons/materialdesignicons-4.9.95.min.css create mode 100644 packages/demobank-ui/src/scss/libs/_all.scss create mode 100644 packages/demobank-ui/src/scss/main.scss create mode 100644 packages/demobank-ui/src/scss/pure.scss create mode 100644 packages/demobank-ui/src/style/index.css create mode 100644 packages/demobank-ui/src/template.html create mode 100644 packages/demobank-ui/tests/__mocks__/browserMocks.ts create mode 100644 packages/demobank-ui/tests/__mocks__/fileMocks.ts create mode 100644 packages/demobank-ui/tests/__mocks__/setupTests.ts create mode 100644 packages/demobank-ui/tests/__tests__/homepage.js create mode 100644 packages/demobank-ui/tests/declarations.d.ts create mode 100644 packages/demobank-ui/tsconfig.json (limited to 'packages/demobank-ui') diff --git a/packages/demobank-ui/.gitignore b/packages/demobank-ui/.gitignore new file mode 100644 index 000000000..32d0a5057 --- /dev/null +++ b/packages/demobank-ui/.gitignore @@ -0,0 +1,5 @@ +node_modules +/build +/*.log +/size-plugin.json +/storybook-static/ diff --git a/packages/demobank-ui/.storybook/.babelrc b/packages/demobank-ui/.storybook/.babelrc new file mode 100644 index 000000000..610b6f339 --- /dev/null +++ b/packages/demobank-ui/.storybook/.babelrc @@ -0,0 +1,25 @@ +/* + 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 + */ + + /** + * + * @author Sebastian Javier Marchano (sebasjm) + */ +{ + "presets": [ + "preact-cli/babel" + ] +} \ No newline at end of file diff --git a/packages/demobank-ui/.storybook/main.js b/packages/demobank-ui/.storybook/main.js new file mode 100644 index 000000000..f8e4bbcc7 --- /dev/null +++ b/packages/demobank-ui/.storybook/main.js @@ -0,0 +1,57 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + + +module.exports = { + "stories": [ + "../src/**/*.stories.mdx", + "../src/**/*.stories.@(js|jsx|ts|tsx)" + ], + "addons": [ + "@storybook/preset-scss", + "@storybook/addon-a11y", + "@storybook/addon-essentials" //docs, control, actions, viewpot, toolbar, background + ], + // sb does not yet support new jsx transform by default + // https://github.com/storybookjs/storybook/issues/12881 + // https://github.com/storybookjs/storybook/issues/12952 + babel: async (options) => ({ + ...options, + presets: [ + ...options.presets, + [ + '@babel/preset-react', { + runtime: 'automatic', + }, + 'preset-react-jsx-transform' + ], + ], + }), + webpackFinal: (config) => { + // should be removed after storybook 6.3 + // https://github.com/storybookjs/storybook/issues/12853#issuecomment-821576113 + config.resolve.alias = { + react: "preact/compat", + "react-dom": "preact/compat", + }; + return config; + }, +} \ No newline at end of file diff --git a/packages/demobank-ui/.storybook/preview.js b/packages/demobank-ui/.storybook/preview.js new file mode 100644 index 000000000..9ab4d9404 --- /dev/null +++ b/packages/demobank-ui/.storybook/preview.js @@ -0,0 +1,55 @@ +/* + 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 + */ + +import "../src/scss/main.scss" +import { TranslationProvider } from '../src/context/translation' +import { h } from 'preact'; + + +export const parameters = { + controls: { expanded: true }, + options: { + storySort: (a, b) => { + return (a[1].args.order ?? 0) - (b[1].args.order ?? 0) + // return a[1].kind === b[1].kind ? 0 : a[1].id.localeCompare(b[1].id, undefined, { numeric: true }) + } + }, +} + +export const globalTypes = { + locale: { + name: 'Locale', + description: 'Internationalization locale', + defaultValue: 'en', + toolbar: { + icon: 'globe', + items: [ + { value: 'en', right: 'πŸ‡ΊπŸ‡Έ', title: 'English' }, + { value: 'es', right: 'πŸ‡ͺπŸ‡Έ', title: 'Spanish' }, + ], + }, + }, +}; + +export const decorators = [ + (Story, { globals }) => { + document.body.parentElement.classList = "has-aside-left has-aside-mobile-transition has-navbar-fixed-top has-aside-expanded" + return + }, + (Story, { globals }) => + + , +]; diff --git a/packages/demobank-ui/README.md b/packages/demobank-ui/README.md new file mode 100644 index 000000000..c014929ce --- /dev/null +++ b/packages/demobank-ui/README.md @@ -0,0 +1,19 @@ +# bank web + +## CLI Commands + +- `npm install`: Installs dependencies + +- `npm run dev`: Run a development, HMR server + +- `npm run serve`: Run a production-like server + +- `npm run build`: Production-ready build + +- `npm run lint`: Pass TypeScript files using ESLint + +- `npm run test`: Run Jest and Enzyme with + [`enzyme-adapter-preact-pure`](https://github.com/preactjs/enzyme-adapter-preact-pure) for + your tests + +For detailed explanation on how things work, checkout the [CLI Readme](https://github.com/developit/preact-cli/blob/master/README.md). diff --git a/packages/demobank-ui/TODO b/packages/demobank-ui/TODO new file mode 100644 index 000000000..a399ada58 --- /dev/null +++ b/packages/demobank-ui/TODO @@ -0,0 +1,45 @@ +Urgent TODOs: + +- General: + * not only Nora dark-theme, but default light! (CSS) + * auto-focus on input fields is not working well + * buttons should be visibly insensitive + as long as required input fields are not + working + * next required invalid/missing input field is + not properly highlighted in red + * Logout button needs more padding to the right (CSS) + +- Error bar: + * shows JSON, should only show good error message + and numeric code, not JSON syntax + * should auto-hide after next action, no need for + "clear"! + * need variant "status bar" in green (or blue) + which shows status of last operation + +* H1-Titles: + * Center more (currently way on the left) (CSS) + +- Assets: + * Numeric amount needs to be shown MUCH bigger (CSS) + * Center more? (CSS) + +- Payments: + * Amount to withdraw currently shown in white-on-white (CSS) + * Big frame drawn around notebook-tabs is not nice (CSS) + * Center more? (CSS) + * "Wire to bank account" + - maybe split two types (payto and IBAN) into + two tabs? + - currently cannot switch back from payto to IBAN + +- Withdraw: + * Should use new 'status' bar at the end, instead + of extra dialog with "close" button + * ditto for bank-wire-transfer final stage + +- Footer: + * overlaps with transaction history or other + content, needs to consistently show at the + end! => change rendering logic!? (CSS?) diff --git a/packages/demobank-ui/build-bank-translations.sh b/packages/demobank-ui/build-bank-translations.sh new file mode 100755 index 000000000..85c8ad0c1 --- /dev/null +++ b/packages/demobank-ui/build-bank-translations.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -eu + +# NOTE: the node somehow didn't get +# the strings extracted. Only i18n`` did + +function build { + POTGEN=node_modules/@gnu-taler/pogen/bin/pogen + PACKAGE_NAME=$1 + + find src/ \( -type f -name "*.ts" -or -name "*.tsx" \) ! -name "*.d.ts" \ + | xargs node $POTGEN \ + | msguniq \ + | msgmerge src/i18n/poheader - \ + > src/i18n/$PACKAGE_NAME.pot + + # merge existing translations: fails when NO .po-files were found. + for pofile in $(ls src/i18n/*.po 2> /dev/null || true); do + echo merging $pofile; + msgmerge -o $pofile $pofile src/i18n/$PACKAGE_NAME.pot; + done; + + # generate .ts file containing all translations + cat src/i18n/strings-prelude > src/i18n/strings.ts + for pofile in $(ls src/i18n/*.po 2> /dev/null || true); do \ + echo appending $pofile; \ + ./contrib/po2ts $pofile >> src/i18n/strings.ts; \ + done; +} + +build bank diff --git a/packages/demobank-ui/contrib/po2ts b/packages/demobank-ui/contrib/po2ts new file mode 100755 index 000000000..a135da61b --- /dev/null +++ b/packages/demobank-ui/contrib/po2ts @@ -0,0 +1,42 @@ +#!/usr/bin/env node +/* + This file is part of GNU Taler + (C) 2020 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 + */ + +/** + * Convert a .po file into a JavaScript / TypeScript expression. + */ + +const po2json = require("po2json"); + +const filename = process.argv[2]; + +if (!filename) { + console.error("error: missing filename"); + process.exit(1); +} + +const m = filename.match(/([a-zA-Z0-9-_]+).po/); + +if (!m) { + console.error("error: unexpected filename (expected .po)"); + process.exit(1); +} + +const lang = m[1]; +const pojson = po2json.parseFileSync(filename, { format: "jed1.x", fuzzy: true }); +const s = + "strings['" + lang + "'] = " + JSON.stringify(pojson, null, " ") + ";\n"; +console.log(s); diff --git a/packages/demobank-ui/mocks/json-server/db.json b/packages/demobank-ui/mocks/json-server/db.json new file mode 100644 index 000000000..44d3ccab2 --- /dev/null +++ b/packages/demobank-ui/mocks/json-server/db.json @@ -0,0 +1,4 @@ +{ + "register": {}, + "transactions": {} +} diff --git a/packages/demobank-ui/mocks/window.js b/packages/demobank-ui/mocks/window.js new file mode 100644 index 000000000..f396ff9e3 --- /dev/null +++ b/packages/demobank-ui/mocks/window.js @@ -0,0 +1,27 @@ +Object.defineProperty(window, 'requestAnimationFrame', { + value: function(cb) {} // Silence the browser. +}) + +Object.defineProperty(window, 'localStorage', { + value: { + store: {}, + getItem: function(key) { + return this.store[key]; + }, + setItem: function(key, value) { + return this.store[key] = value; + }, + clear: function() { + this.store = {}; + } + } +}); +Object.defineProperty(window, 'location', { + value: { + origin: "http://localhost:8080", /* where taler-local rev proxy listens to */ + search: "", + pathname: "/sandbox/demobanks/default", + } +}) + +export default window; diff --git a/packages/demobank-ui/package.json b/packages/demobank-ui/package.json new file mode 100644 index 000000000..bd686365b --- /dev/null +++ b/packages/demobank-ui/package.json @@ -0,0 +1,100 @@ +{ + "private": true, + "name": "bank", + "version": "0.1.0", + "license": "AGPL-3.0-OR-LATER", + "scripts": { + "dev": "preact watch --port ${PORT:=9090} --no-sw --no-esm -c preact.mock.js", + "build": "preact build --no-sw --no-esm -c preact.single-config.js --dest build && sh remove-link-stylesheet.sh", + "serve": "sirv build --port ${PORT:=8080} --cors --single", + "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'", + "test": "jest ./tests", + "build-storybook": "build-storybook", + "serve-single": "sirv single --port ${PORT:=8080} --cors --single", + "pretty": "prettier --write src", + "storybook": "start-storybook -p 6006" + }, + "eslintConfig": { + "parser": "@typescript-eslint/parser", + "extends": [ + "preact", + "plugin:@typescript-eslint/recommended" + ], + "ignorePatterns": [ + "build/" + ], + "rules": { + "@typescript-eslint/no-explicit-any": [0], + "@typescript-eslint/ban-ts-comment": [1], + "quotes": [2, "single", {"allowTemplateLiterals": true,"avoidEscape": false}], + "indent": [2,2], + "prefer-arrow-callback": [2, {"allowNamedFunctions": false, "allowUnboundThis": true}], + "curly": [2,"multi"], + "prefer-template": [1] + } + }, + "dependencies": { + "base64-inline-loader": "1.1.1", + "date-fns": "2.25.0", + "jed": "1.1.1", + "preact": "^10.5.15", + "preact-render-to-string": "^5.1.19", + "preact-router": "^3.2.1", + "qrcode-generator": "^1.4.4", + "swr": "1.1" + }, + "devDependencies": { + "@babel/core": "^7.13.16", + "@babel/plugin-transform-react-jsx": "^7.12.13", + "@babel/plugin-transform-react-jsx-source": "^7.12.13", + "@babel/preset-env": "^7.16.7", + "@creativebulma/bulma-tooltip": "^1.2.0", + "@gnu-taler/pogen": "^0.0.5", + "@storybook/addon-a11y": "6.2.9", + "@storybook/addon-actions": "6.2.9", + "@storybook/addon-essentials": "6.2.9", + "@storybook/addon-links": "6.2.9", + "@storybook/preact": "6.2.9", + "@storybook/preset-scss": "^1.0.3", + "@testing-library/jest-dom": "^5.16.1", + "@testing-library/preact": "^2.0.1", + "@testing-library/preact-hooks": "^1.1.0", + "@types/enzyme": "^3.10.10", + "@types/jest": "^27.0.2", + "@typescript-eslint/eslint-plugin": "^5.3.0", + "@typescript-eslint/parser": "^5.3.0", + "babel-loader": "^8.2.2", + "base64-inline-loader": "^1.1.1", + "bulma": "^0.9.3", + "bulma-checkbox": "^1.1.1", + "bulma-radio": "^1.1.1", + "enzyme": "^3.11.0", + "enzyme-adapter-preact-pure": "^3.2.0", + "eslint": "^8.1.0", + "eslint-config-preact": "^1.2.0", + "html-webpack-inline-chunk-plugin": "^1.1.1", + "html-webpack-inline-source-plugin": "0.0.10", + "html-webpack-skip-assets-plugin": "^1.0.1", + "inline-chunk-html-plugin": "^1.1.1", + "jest": "^27.3.1", + "jest-fetch-mock": "^3.0.3", + "jest-preset-preact": "^4.0.5", + "jest-watch-typeahead": "^1.0.0", + "jest-environment-jsdom": "^27.4.6", + "jssha": "^3.2.0", + "po2json": "^0.4.5", + "preact-cli": "3.0.5", + "sass": "1.32.13", + "sass-loader": "^10", + "script-ext-html-webpack-plugin": "^2.1.5", + "sirv-cli": "^1.0.14", + "typescript": "^4.4.4" + }, + "jest": { + "preset": "jest-preset-preact", + "setupFiles": [ + "/tests/__mocks__/browserMocks.ts", + "/tests/__mocks__/setupTests.ts" + ] + } +} diff --git a/packages/demobank-ui/preact.config.js b/packages/demobank-ui/preact.config.js new file mode 100644 index 000000000..8e640f3ff --- /dev/null +++ b/packages/demobank-ui/preact.config.js @@ -0,0 +1,70 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { DefinePlugin } from 'webpack'; + +import pack from './package.json'; +import * as cp from 'child_process'; + +const commitHash = cp.execSync('git rev-parse --short HEAD').toString(); + +export default { + webpack(config, env, helpers) { + // ensure that process.env will not be undefined on runtime + config.node.process = 'mock' + + // add __VERSION__ to be use in the html + config.plugins.push( + new DefinePlugin({ + 'process.env.__VERSION__': JSON.stringify(env.isProd ? pack.version : `dev-${commitHash}`) , + }), + ); + + // suddenly getting out of memory error from build process, error below [1] + // FIXME: remove preact-cli, use rollup + let { index } = helpers.getPluginsByName(config, 'WebpackFixStyleOnlyEntriesPlugin')[0] + config.plugins.splice(index, 1) + } +} + + + +/* [1] from this error decided to remove plugin 'webpack-fix-style-only-entries + leaving this error for future reference + + +<--- Last few GCs ---> + +[32479:0x2e01870] 19969 ms: Mark-sweep 1869.4 (1950.2) -> 1443.1 (1504.1) MB, 497.5 / 0.0 ms (average mu = 0.631, current mu = 0.455) allocation failure scavenge might not succeed +[32479:0x2e01870] 21907 ms: Mark-sweep 2016.9 (2077.9) -> 1628.6 (1681.4) MB, 1596.0 / 0.0 ms (average mu = 0.354, current mu = 0.176) allocation failure scavenge might not succeed + +<--- JS stacktrace ---> + +==== JS stack trace ========================================= + + 0: ExitFrame [pc: 0x13cf099] +Security context: 0x2f4ca66c08d1 + 1: /* anonymous * / [0x35d05555b4b9] [...path/merchant-backoffice/node_modules/.pnpm/webpack-fix-style-only-entries@0.5.2/node_modules/webpack-fix-style-only-entries/index.js:~80] [pc=0x2145e699d1a4](this=0x1149465410e9 ,0x047e52e36a49 ) + 2: arguments adaptor frame: 3... + +FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory + +*/ \ No newline at end of file diff --git a/packages/demobank-ui/preact.mock.js b/packages/demobank-ui/preact.mock.js new file mode 100644 index 000000000..dc3ceb66d --- /dev/null +++ b/packages/demobank-ui/preact.mock.js @@ -0,0 +1,55 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import { DefinePlugin, ProvidePlugin } from 'webpack'; + +import pack from './package.json'; +import * as cp from 'child_process'; + +const commitHash = cp.execSync('git rev-parse --short HEAD').toString(); +import path from 'path'; + +export default { + webpack(config, env, helpers) { + // Ensure that process.env will not be undefined at runtime. + config.node.process = 'mock' + let DEMO_SITES = { + "Blog": process.env.TALER_ENV_URL_MERCHANT_BLOG, + "Donations": process.env.TALER_ENV_URL_MERCHANT_DONATIONS, + "Survey": process.env.TALER_ENV_URL_MERCHANT_SURVEY, + "Landing": process.env.TALER_ENV_URL_INTRO, + "Bank": process.env.TALER_ENV_URL_BANK, + } + console.log("demo links found", DEMO_SITES); + // Add __VERSION__ to be use in the html. + config.plugins.push( + new DefinePlugin({ + 'process.env.__VERSION__': JSON.stringify(env.isProd ? pack.version : `dev-${commitHash}`) , + }), + // 'window' gets mocked to point at a running euFin instance. + new ProvidePlugin({window: path.resolve("mocks/window")}), + new DefinePlugin({"DEMO_SITES": JSON.stringify(DEMO_SITES)}) + ); + + let { index } = helpers.getPluginsByName(config, 'WebpackFixStyleOnlyEntriesPlugin')[0] + config.plugins.splice(index, 1) + } +} diff --git a/packages/demobank-ui/preact.single-config.js b/packages/demobank-ui/preact.single-config.js new file mode 100644 index 000000000..0fb6f1d0e --- /dev/null +++ b/packages/demobank-ui/preact.single-config.js @@ -0,0 +1,60 @@ +/* + 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 + */ + +/** +* +* @author Sebastian Javier Marchano (sebasjm) +*/ + +import defaultConfig from './preact.config' + +export default { + webpack(config, env, helpers, options) { + defaultConfig.webpack(config, env, helpers, options) + + //1. check no file is under /routers or /component/{routers,async} to prevent async components + // https://github.com/preactjs/preact-cli#route-based-code-splitting + + //2. remove devtools to prevent sourcemaps + config.devtool = false + + //3. change assetLoader to load assets inline + const loaders = helpers.getLoaders(config) + const assetsLoader = loaders.find(lo => lo.rule.test.test('something.woff')) + if (assetsLoader) { + assetsLoader.rule.use = 'base64-inline-loader' + assetsLoader.rule.loader = undefined + } + + //4. remove critters + //critters remove the css bundle from htmlWebpackPlugin.files.css + //for now, pushing all the content into the html is enough + const crittersWrapper = helpers.getPluginsByName(config, 'Critters') + if (crittersWrapper && crittersWrapper.length > 0) { + const [{ index }] = crittersWrapper + config.plugins.splice(index, 1) + } + + //5. remove favicon from src/assets + + //6. remove performance hints since we now that this is going to be big + if (config.performance) { + config.performance.hints = false + } + + //7. template.html should have a favicon and add js/css content + } +} diff --git a/packages/demobank-ui/remove-link-stylesheet.sh b/packages/demobank-ui/remove-link-stylesheet.sh new file mode 100755 index 000000000..d3376b8e6 --- /dev/null +++ b/packages/demobank-ui/remove-link-stylesheet.sh @@ -0,0 +1,8 @@ +# This script has been placed in the public domain. + +FILE=$(ls build/bundle.*.css) +BUNDLE=${FILE#build} +grep -q '' build/index.html || { echo bundle $BUNDLE not found in index.html; exit 1; } +echo -n Removing link from index.html ... +sed 's___' -i build/index.html +echo done diff --git a/packages/demobank-ui/src/.babelrc b/packages/demobank-ui/src/.babelrc new file mode 100644 index 000000000..05f4dcc81 --- /dev/null +++ b/packages/demobank-ui/src/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["preact-cli/babel"] +} diff --git a/packages/demobank-ui/src/assets/empty.png b/packages/demobank-ui/src/assets/empty.png new file mode 100644 index 000000000..5120d3138 Binary files /dev/null and b/packages/demobank-ui/src/assets/empty.png differ diff --git a/packages/demobank-ui/src/assets/example/id1.jpg b/packages/demobank-ui/src/assets/example/id1.jpg new file mode 100644 index 000000000..5d022a379 Binary files /dev/null and b/packages/demobank-ui/src/assets/example/id1.jpg differ diff --git a/packages/demobank-ui/src/assets/favicon.ico b/packages/demobank-ui/src/assets/favicon.ico new file mode 100644 index 000000000..07419145b Binary files /dev/null and b/packages/demobank-ui/src/assets/favicon.ico differ diff --git a/packages/demobank-ui/src/assets/icons/android-chrome-192x192.png b/packages/demobank-ui/src/assets/icons/android-chrome-192x192.png new file mode 100644 index 000000000..93ebe2e2c Binary files /dev/null and b/packages/demobank-ui/src/assets/icons/android-chrome-192x192.png differ diff --git a/packages/demobank-ui/src/assets/icons/android-chrome-512x512.png b/packages/demobank-ui/src/assets/icons/android-chrome-512x512.png new file mode 100644 index 000000000..52d1623ea Binary files /dev/null and b/packages/demobank-ui/src/assets/icons/android-chrome-512x512.png differ diff --git a/packages/demobank-ui/src/assets/icons/apple-touch-icon.png b/packages/demobank-ui/src/assets/icons/apple-touch-icon.png new file mode 100644 index 000000000..254e4bb4d Binary files /dev/null and b/packages/demobank-ui/src/assets/icons/apple-touch-icon.png differ diff --git a/packages/demobank-ui/src/assets/icons/auth_method/email.svg b/packages/demobank-ui/src/assets/icons/auth_method/email.svg new file mode 100644 index 000000000..3e44b8779 --- /dev/null +++ b/packages/demobank-ui/src/assets/icons/auth_method/email.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/demobank-ui/src/assets/icons/auth_method/postal.svg b/packages/demobank-ui/src/assets/icons/auth_method/postal.svg new file mode 100644 index 000000000..3787b8350 --- /dev/null +++ b/packages/demobank-ui/src/assets/icons/auth_method/postal.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/demobank-ui/src/assets/icons/auth_method/question.svg b/packages/demobank-ui/src/assets/icons/auth_method/question.svg new file mode 100644 index 000000000..a346556b2 --- /dev/null +++ b/packages/demobank-ui/src/assets/icons/auth_method/question.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/demobank-ui/src/assets/icons/auth_method/sms.svg b/packages/demobank-ui/src/assets/icons/auth_method/sms.svg new file mode 100644 index 000000000..ed15679bf --- /dev/null +++ b/packages/demobank-ui/src/assets/icons/auth_method/sms.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/demobank-ui/src/assets/icons/auth_method/video.svg b/packages/demobank-ui/src/assets/icons/auth_method/video.svg new file mode 100644 index 000000000..69de5e0b4 --- /dev/null +++ b/packages/demobank-ui/src/assets/icons/auth_method/video.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/demobank-ui/src/assets/icons/favicon-16x16.png b/packages/demobank-ui/src/assets/icons/favicon-16x16.png new file mode 100644 index 000000000..e81177dcb Binary files /dev/null and b/packages/demobank-ui/src/assets/icons/favicon-16x16.png differ diff --git a/packages/demobank-ui/src/assets/icons/favicon-32x32.png b/packages/demobank-ui/src/assets/icons/favicon-32x32.png new file mode 100644 index 000000000..40e9b5b47 Binary files /dev/null and b/packages/demobank-ui/src/assets/icons/favicon-32x32.png differ diff --git a/packages/demobank-ui/src/assets/icons/languageicon.svg b/packages/demobank-ui/src/assets/icons/languageicon.svg new file mode 100644 index 000000000..22d58da65 --- /dev/null +++ b/packages/demobank-ui/src/assets/icons/languageicon.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/demobank-ui/src/assets/icons/mstile-150x150.png b/packages/demobank-ui/src/assets/icons/mstile-150x150.png new file mode 100644 index 000000000..9cfb889be Binary files /dev/null and b/packages/demobank-ui/src/assets/icons/mstile-150x150.png differ diff --git a/packages/demobank-ui/src/assets/logo-white.svg b/packages/demobank-ui/src/assets/logo-white.svg new file mode 100644 index 000000000..cb1f023c5 --- /dev/null +++ b/packages/demobank-ui/src/assets/logo-white.svg @@ -0,0 +1,45 @@ + + + + diff --git a/packages/demobank-ui/src/assets/logo.jpeg b/packages/demobank-ui/src/assets/logo.jpeg new file mode 100644 index 000000000..489832f7c Binary files /dev/null and b/packages/demobank-ui/src/assets/logo.jpeg differ diff --git a/packages/demobank-ui/src/components/AsyncButton.tsx b/packages/demobank-ui/src/components/AsyncButton.tsx new file mode 100644 index 000000000..0c4305668 --- /dev/null +++ b/packages/demobank-ui/src/components/AsyncButton.tsx @@ -0,0 +1,66 @@ +/* + 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 + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ + +import { ComponentChildren, h, VNode } from 'preact'; +import { useLayoutEffect, useRef } from 'preact/hooks'; +// import { LoadingModal } from "../modal"; +import { useAsync } from '../hooks/async'; +// import { Translate } from "../../i18n"; + +type Props = { + children: ComponentChildren; + disabled?: boolean; + onClick?: () => Promise; + grabFocus?: boolean; + [rest: string]: any; +}; + +export function AsyncButton({ + onClick, + grabFocus, + disabled, + children, + ...rest +}: Props): VNode { + const { isLoading, request } = useAsync(onClick); + + const buttonRef = useRef(null); + useLayoutEffect(() => { + if (grabFocus) + buttonRef.current?.focus(); + + }, [grabFocus]); + + // if (isSlow) { + // return ; + // } + if (isLoading) + return ; + + + return ( + + + + ); +} diff --git a/packages/demobank-ui/src/components/FileButton.tsx b/packages/demobank-ui/src/components/FileButton.tsx new file mode 100644 index 000000000..dba86ccbf --- /dev/null +++ b/packages/demobank-ui/src/components/FileButton.tsx @@ -0,0 +1,57 @@ +import { h, VNode } from 'preact'; +import { useRef, useState } from 'preact/hooks'; + +const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024; + +export interface FileTypeContent { + content: string; + type: string; + name: string; +} + +interface Props { + label: string; + onChange: (v: FileTypeContent | undefined) => void; +} +export function FileButton(props: Props): VNode { + const fileInputRef = useRef(null); + const [sizeError, setSizeError] = useState(false); + return ( +
+ + { + const f: FileList | null = e.currentTarget.files; + if (!f || f.length != 1) + return props.onChange(undefined); + + console.log(f); + if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { + setSizeError(true); + return props.onChange(undefined); + } + setSizeError(false); + return f[0].arrayBuffer().then((b) => { + const content = new Uint8Array(b).reduce( + (data, byte) => data + String.fromCharCode(byte), + '', + ); + return props.onChange({ + content, + name: f[0].name, + type: f[0].type, + }); + }); + }} + /> + {sizeError && ( +

File should be smaller than 1 MB

+ )} +
+ ); +} diff --git a/packages/demobank-ui/src/components/Notifications.tsx b/packages/demobank-ui/src/components/Notifications.tsx new file mode 100644 index 000000000..09329442a --- /dev/null +++ b/packages/demobank-ui/src/components/Notifications.tsx @@ -0,0 +1,74 @@ +/* + 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 + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ + +import { h, VNode } from 'preact'; + +export interface Notification { + message: string; + description?: string | VNode; + type: MessageType; +} + +export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS'; + +interface Props { + notifications: Notification[]; + removeNotification?: (n: Notification) => void; +} + +function messageStyle(type: MessageType): string { + switch (type) { + case 'INFO': + return 'message is-info'; + case 'WARN': + return 'message is-warning'; + case 'ERROR': + return 'message is-danger'; + case 'SUCCESS': + return 'message is-success'; + default: + return 'message'; + } +} + +export function Notifications({ + notifications, + removeNotification, +}: Props): VNode { + return ( +
+ {notifications.map((n, i) => ( +
+
+

{n.message}

+ {removeNotification && ( +
+ {n.description &&
{n.description}
} +
+ ))} +
+ ); +} diff --git a/packages/demobank-ui/src/components/QR.tsx b/packages/demobank-ui/src/components/QR.tsx new file mode 100644 index 000000000..ee5b73c69 --- /dev/null +++ b/packages/demobank-ui/src/components/QR.tsx @@ -0,0 +1,48 @@ +/* + 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 + */ + +import { h, VNode } from 'preact'; +import { useEffect, useRef } from 'preact/hooks'; +import qrcode from 'qrcode-generator'; + +export function QR({ text }: { text: string }): VNode { + const divRef = useRef(null); + useEffect(() => { + const qr = qrcode(0, 'L'); + qr.addData(text); + qr.make(); + if (divRef.current) + divRef.current.innerHTML = qr.createSvgTag({ + scalable: true, + }); + }); + + return ( +
+
+
+ ); +} diff --git a/packages/demobank-ui/src/components/app.tsx b/packages/demobank-ui/src/components/app.tsx new file mode 100644 index 000000000..5338c548e --- /dev/null +++ b/packages/demobank-ui/src/components/app.tsx @@ -0,0 +1,14 @@ +import { FunctionalComponent, h } from 'preact'; +import { TranslationProvider } from '../context/translation'; +import { BankHome } from '../pages/home/index'; +import { Menu } from './menu'; + +const App: FunctionalComponent = () => { + return ( + + + + ); +}; + +export default App; diff --git a/packages/demobank-ui/src/components/fields/DateInput.tsx b/packages/demobank-ui/src/components/fields/DateInput.tsx new file mode 100644 index 000000000..06ec4b6a7 --- /dev/null +++ b/packages/demobank-ui/src/components/fields/DateInput.tsx @@ -0,0 +1,90 @@ +import { format, subYears } from 'date-fns'; +import { h, VNode } from 'preact'; +import { useLayoutEffect, useRef, useState } from 'preact/hooks'; +import { DatePicker } from '../picker/DatePicker'; + +export interface DateInputProps { + label: string; + grabFocus?: boolean; + tooltip?: string; + error?: string; + years?: Array; + onConfirm?: () => void; + bind: [string, (x: string) => void]; +} + +export function DateInput(props: DateInputProps): VNode { + const inputRef = useRef(null); + useLayoutEffect(() => { + if (props.grabFocus) + inputRef.current?.focus(); + + }, [props.grabFocus]); + const [opened, setOpened] = useState(false); + + const value = props.bind[0] || ''; + const [dirty, setDirty] = useState(false); + const showError = dirty && props.error; + + const calendar = subYears(new Date(), 30); + + return ( +
+ +
+
+

+ { + if (e.key === 'Enter' && props.onConfirm) + props.onConfirm() + + }} + onInput={(e) => { + const text = e.currentTarget.value; + setDirty(true); + props.bind[1](text); + }} + ref={inputRef} + /> +

+

+ { + setOpened(true); + }} + > + + + + +

+
+
+

Using the format yyyy-mm-dd

+ {showError &&

{props.error}

} + setOpened(false)} + dateReceiver={(d) => { + setDirty(true); + const v = format(d, 'yyyy-MM-dd'); + props.bind[1](v); + }} + /> +
+ ); +} diff --git a/packages/demobank-ui/src/components/fields/EmailInput.tsx b/packages/demobank-ui/src/components/fields/EmailInput.tsx new file mode 100644 index 000000000..8b64264ed --- /dev/null +++ b/packages/demobank-ui/src/components/fields/EmailInput.tsx @@ -0,0 +1,57 @@ +import { h, VNode } from 'preact'; +import { useLayoutEffect, useRef, useState } from 'preact/hooks'; + +export interface TextInputProps { + label: string; + grabFocus?: boolean; + error?: string; + placeholder?: string; + tooltip?: string; + onConfirm?: () => void; + bind: [string, (x: string) => void]; +} + +export function EmailInput(props: TextInputProps): VNode { + const inputRef = useRef(null); + useLayoutEffect(() => { + if (props.grabFocus) + inputRef.current?.focus(); + + }, [props.grabFocus]); + const value = props.bind[0]; + const [dirty, setDirty] = useState(false); + const showError = dirty && props.error; + return ( +
+ +
+ { + if (e.key === 'Enter' && props.onConfirm) + props.onConfirm() + + }} + onInput={(e) => { + setDirty(true); + props.bind[1]((e.target as HTMLInputElement).value); + }} + ref={inputRef} + style={{ display: 'block' }} + /> +
+ {showError &&

{props.error}

} +
+ ); +} diff --git a/packages/demobank-ui/src/components/fields/FileInput.tsx b/packages/demobank-ui/src/components/fields/FileInput.tsx new file mode 100644 index 000000000..17413b907 --- /dev/null +++ b/packages/demobank-ui/src/components/fields/FileInput.tsx @@ -0,0 +1,104 @@ +/* + 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 + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ +import { h, VNode } from 'preact'; +import { useLayoutEffect, useRef, useState } from 'preact/hooks'; + +const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024; + +export interface FileTypeContent { + content: string; + type: string; + name: string; +} + +export interface FileInputProps { + label: string; + grabFocus?: boolean; + disabled?: boolean; + error?: string; + placeholder?: string; + tooltip?: string; + onChange: (v: FileTypeContent | undefined) => void; +} + +export function FileInput(props: FileInputProps): VNode { + const inputRef = useRef(null); + useLayoutEffect(() => { + if (props.grabFocus) + inputRef.current?.focus(); + + }, [props.grabFocus]); + + const fileInputRef = useRef(null); + const [sizeError, setSizeError] = useState(false); + return ( +
+ +
+ { + const f: FileList | null = e.currentTarget.files; + if (!f || f.length != 1) + return props.onChange(undefined); + + console.log(f) + if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { + setSizeError(true); + return props.onChange(undefined); + } + setSizeError(false); + return f[0].arrayBuffer().then((b) => { + const b64 = btoa( + new Uint8Array(b).reduce( + (data, byte) => data + String.fromCharCode(byte), + '', + ), + ); + return props.onChange({content: `data:${f[0].type};base64,${b64}`, name: f[0].name, type: f[0].type}); + }); + }} + /> + {props.error &&

{props.error}

} + {sizeError && ( +

File should be smaller than 1 MB

+ )} +
+
+ ); +} diff --git a/packages/demobank-ui/src/components/fields/ImageInput.tsx b/packages/demobank-ui/src/components/fields/ImageInput.tsx new file mode 100644 index 000000000..98457af21 --- /dev/null +++ b/packages/demobank-ui/src/components/fields/ImageInput.tsx @@ -0,0 +1,93 @@ +/* + 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 + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ +import { h, VNode } from 'preact'; +import { useLayoutEffect, useRef, useState } from 'preact/hooks'; +import emptyImage from '../../assets/empty.png'; +import { TextInputProps } from './TextInput'; + +const MAX_IMAGE_UPLOAD_SIZE = 1024 * 1024; + +export function ImageInput(props: TextInputProps): VNode { + const inputRef = useRef(null); + useLayoutEffect(() => { + if (props.grabFocus) + inputRef.current?.focus(); + + }, [props.grabFocus]); + + const value = props.bind[0]; + // const [dirty, setDirty] = useState(false) + const image = useRef(null); + const [sizeError, setSizeError] = useState(false); + function onChange(v: string): void { + // setDirty(true); + props.bind[1](v); + } + return ( +
+ +
+ image.current?.click()} + /> + { + const f: FileList | null = e.currentTarget.files; + if (!f || f.length != 1) + return onChange(emptyImage); + + if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) { + setSizeError(true); + return onChange(emptyImage); + } + setSizeError(false); + return f[0].arrayBuffer().then((b) => { + const b64 = btoa( + new Uint8Array(b).reduce( + (data, byte) => data + String.fromCharCode(byte), + '', + ), + ); + return onChange(`data:${f[0].type};base64,${b64}` as any); + }); + }} + /> + {props.error &&

{props.error}

} + {sizeError && ( +

Image should be smaller than 1 MB

+ )} +
+
+ ); +} diff --git a/packages/demobank-ui/src/components/fields/NumberInput.tsx b/packages/demobank-ui/src/components/fields/NumberInput.tsx new file mode 100644 index 000000000..881c61c57 --- /dev/null +++ b/packages/demobank-ui/src/components/fields/NumberInput.tsx @@ -0,0 +1,56 @@ +import { h, VNode } from 'preact'; +import { useLayoutEffect, useRef, useState } from 'preact/hooks'; + +export interface TextInputProps { + label: string; + grabFocus?: boolean; + error?: string; + placeholder?: string; + tooltip?: string; + onConfirm?: () => void; + bind: [string, (x: string) => void]; +} + +export function PhoneNumberInput(props: TextInputProps): VNode { + const inputRef = useRef(null); + useLayoutEffect(() => { + if (props.grabFocus) + inputRef.current?.focus(); + + }, [props.grabFocus]); + const value = props.bind[0]; + const [dirty, setDirty] = useState(false); + const showError = dirty && props.error; + return ( +
+ +
+ { + if (e.key === 'Enter' && props.onConfirm) + props.onConfirm() + + }} + onInput={(e) => { + setDirty(true); + props.bind[1]((e.target as HTMLInputElement).value); + }} + ref={inputRef} + style={{ display: 'block' }} + /> +
+ {showError &&

{props.error}

} +
+ ); +} diff --git a/packages/demobank-ui/src/components/fields/TextInput.tsx b/packages/demobank-ui/src/components/fields/TextInput.tsx new file mode 100644 index 000000000..5cc9f32ad --- /dev/null +++ b/packages/demobank-ui/src/components/fields/TextInput.tsx @@ -0,0 +1,68 @@ +import { h, VNode } from 'preact'; +import { useLayoutEffect, useRef, useState } from 'preact/hooks'; + +export interface TextInputProps { + inputType?: 'text' | 'number' | 'multiline' | 'password'; + label: string; + grabFocus?: boolean; + disabled?: boolean; + error?: string; + placeholder?: string; + tooltip?: string; + onConfirm?: () => void; + bind: [string, (x: string) => void]; +} + +const TextInputType = function ({ inputType, grabFocus, ...rest }: any): VNode { + const inputRef = useRef(null); + useLayoutEffect(() => { + if (grabFocus) + inputRef.current?.focus(); + + }, [grabFocus]); + + return inputType === 'multiline' ? ( +