repo: integrate packages from former merchant-backoffice.git
5
packages/demobank-ui/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
node_modules
|
||||
/build
|
||||
/*.log
|
||||
/size-plugin.json
|
||||
/storybook-static/
|
25
packages/demobank-ui/.storybook/.babelrc
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
{
|
||||
"presets": [
|
||||
"preact-cli/babel"
|
||||
]
|
||||
}
|
57
packages/demobank-ui/.storybook/main.js
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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;
|
||||
},
|
||||
}
|
55
packages/demobank-ui/.storybook/preview.js
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
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 />
|
||||
},
|
||||
(Story, { globals }) => <TranslationProvider initial='en' forceLang={globals.locale}>
|
||||
<Story />
|
||||
</TranslationProvider>,
|
||||
];
|
19
packages/demobank-ui/README.md
Normal file
@ -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).
|
45
packages/demobank-ui/TODO
Normal file
@ -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?)
|
32
packages/demobank-ui/build-bank-translations.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
# NOTE: the <Translate> 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
|
42
packages/demobank-ui/contrib/po2ts
Executable file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a <lang>.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 <lang>.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);
|
4
packages/demobank-ui/mocks/json-server/db.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"register": {},
|
||||
"transactions": {}
|
||||
}
|
27
packages/demobank-ui/mocks/window.js
Normal file
@ -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;
|
100
packages/demobank-ui/package.json
Normal file
@ -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": [
|
||||
"<rootDir>/tests/__mocks__/browserMocks.ts",
|
||||
"<rootDir>/tests/__mocks__/setupTests.ts"
|
||||
]
|
||||
}
|
||||
}
|
70
packages/demobank-ui/preact.config.js
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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 <JSObject>
|
||||
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 <GlobalObject Object map = 0xff481b5b5f9>,0x047e52e36a49 <Dependency map = 0x1ed1fe41cd19>)
|
||||
2: arguments adaptor frame: 3...
|
||||
|
||||
FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of memory
|
||||
|
||||
*/
|
55
packages/demobank-ui/preact.mock.js
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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)
|
||||
}
|
||||
}
|
60
packages/demobank-ui/preact.single-config.js
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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
|
||||
}
|
||||
}
|
8
packages/demobank-ui/remove-link-stylesheet.sh
Executable file
@ -0,0 +1,8 @@
|
||||
# This script has been placed in the public domain.
|
||||
|
||||
FILE=$(ls build/bundle.*.css)
|
||||
BUNDLE=${FILE#build}
|
||||
grep -q '<link href="'$BUNDLE'" rel="stylesheet">' build/index.html || { echo bundle $BUNDLE not found in index.html; exit 1; }
|
||||
echo -n Removing link from index.html ...
|
||||
sed 's_<link href="'$BUNDLE'" rel="stylesheet">__' -i build/index.html
|
||||
echo done
|
3
packages/demobank-ui/src/.babelrc
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["preact-cli/babel"]
|
||||
}
|
BIN
packages/demobank-ui/src/assets/empty.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
packages/demobank-ui/src/assets/example/id1.jpg
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
packages/demobank-ui/src/assets/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
packages/demobank-ui/src/assets/icons/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
packages/demobank-ui/src/assets/icons/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
packages/demobank-ui/src/assets/icons/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6zm-2 0l-8 5-8-5h16zm0 12H4V8l8 5 8-5v10z"/></svg>
|
After Width: | Height: | Size: 274 B |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 15h2v2h-2zM17 11h2v2h-2zM17 7h2v2h-2zM13.74 7l1.26.84V7z"/><path d="M10 3v1.51l2 1.33V5h9v14h-4v2h6V3z"/><path d="M8.17 5.7L15 10.25V21H1V10.48L8.17 5.7zM10 19h3v-7.84L8.17 8.09 3 11.38V19h3v-6h4v6z"/></svg>
|
After Width: | Height: | Size: 359 B |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 23.59v-3.6c-5.01-.26-9-4.42-9-9.49C2 5.26 6.26 1 11.5 1S21 5.26 21 10.5c0 4.95-3.44 9.93-8.57 12.4l-1.43.69zM11.5 3C7.36 3 4 6.36 4 10.5S7.36 18 11.5 18H13v2.3c3.64-2.3 6-6.08 6-9.8C19 6.36 15.64 3 11.5 3zm-1 11.5h2v2h-2zm2-1.5h-2c0-3.25 3-3 3-5 0-1.1-.9-2-2-2s-2 .9-2 2h-2c0-2.21 1.79-4 4-4s4 1.79 4 4c0 2.5-3 2.75-3 5z"/></svg>
|
After Width: | Height: | Size: 483 B |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17 1.01L7 1c-1.1 0-1.99.9-1.99 2v18c0 1.1.89 2 1.99 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></svg>
|
After Width: | Height: | Size: 272 B |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><g><path d="M18,10.48V6c0-1.1-0.9-2-2-2H4C2.9,4,2,4.9,2,6v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-4.48l4,3.98v-11L18,10.48z M16,9.69V18H4V6h12V9.69z"/><circle cx="10" cy="10" r="2"/><path d="M14,15.43c0-0.81-0.48-1.53-1.22-1.85C11.93,13.21,10.99,13,10,13c-0.99,0-1.93,0.21-2.78,0.58C6.48,13.9,6,14.62,6,15.43 V16h8V15.43z"/></g></g></svg>
|
After Width: | Height: | Size: 525 B |
BIN
packages/demobank-ui/src/assets/icons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 626 B |
BIN
packages/demobank-ui/src/assets/icons/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
48
packages/demobank-ui/src/assets/icons/languageicon.svg
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 2411.2 2794" style="enable-background:new 0 0 2411.2 2794;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
|
||||
</style>
|
||||
<g id="Layer_2">
|
||||
</g>
|
||||
<g id="Layer_x5F_1_x5F_1">
|
||||
<g>
|
||||
<polygon points="1204.6,359.2 271.8,30 271.8,2060.1 1204.6,1758.3 "/>
|
||||
<polygon class="st0" points="1182.2,358.1 2150.6,29 2150.6,2059 1182.2,1757.3 "/>
|
||||
<polygon class="st0" points="30,2415.4 1182.2,2031.4 1182.2,357.9 30,742 "/>
|
||||
<polygon points="1707.2,2440.7 1870.5,2709.4 1956.6,2459.8 "/>
|
||||
<g>
|
||||
<path d="M421.7,934.8c-6.1-6,8,49.1,27.6,68.9c34.8,35.1,61.9,39.6,76.4,40.2c32,1.3,71.5-8,94.9-17.8
|
||||
c22.7-9.7,62.4-30,77.5-59.6c3.2-6.3,11.9-17,6.4-43.2c-4.2-20.2-17-27.3-32.7-26.2c-15.7,1.1-63.2,13.7-86.1,20.8
|
||||
c-23,7-70.3,21.4-90.9,25.8C474.3,948.2,429,941.7,421.7,934.8z"/>
|
||||
<path d="M1003.1,1593.7c-9.1-3.3-196.9-81.1-223.6-93.9c-21.8-10.5-75.2-33.1-100.4-43.3c70.8-109.2,115.5-191.6,121.5-204.1
|
||||
c11-23,86-169.6,87.7-178.7c1.7-9.1,3.8-42.9,2.2-51c-1.7-8.2-29.1,7.6-66.4,20.2c-37.4,12.6-108.4,58.8-135.8,64.6
|
||||
c-27.5,5.7-115.5,39.1-160.5,54c-45,14.9-130.2,40.9-165.2,50.4c-35.1,9.5-65.7,10.2-85.3,16.2c0,0,2.6,27.5,7.8,35.7
|
||||
c5.2,8.2,23.7,28.4,45.3,34.1c21.6,5.7,57.3,3.4,73.6-0.3c16.3-3.8,44.4-17.5,48.2-23.6c3.8-6.1-2-24.9,4.5-30.6
|
||||
c6.5-5.6,92.2-25.7,124.6-35.4c32.4-10,156.3-52.6,173.1-50.5c-5.3,17.7-105,215.1-137.1,274c-32.1,58.9-218.6,318-258.3,363.6
|
||||
c-30.1,34.7-103.2,123.5-128.5,143.6c6.4,1.8,51.6-2.1,59.9-7.2c51.3-31.6,136.9-138.1,164.4-170.5
|
||||
c81.9-96,153.8-196.8,210.8-283.4h0.1c11.1,4.6,100.9,77.8,124.4,94c23.4,16.2,115.9,67.8,136,76.4c20,8.7,97.1,44.2,100.3,32.2
|
||||
C1029.4,1668,1012.2,1597.1,1003.1,1593.7z"/>
|
||||
</g>
|
||||
<path class="st1" d="M569,2572c18,11,35,20,54,29c38,19,81,39,122,54c56,21,112,38,168,51c31,7,65,13,98,18c3,0,92,11,110,11h90
|
||||
c35-3,68-5,103-10c28-4,59-9,89-16c22-5,45-10,67-17c21-6,45-14,68-22c15-5,31-12,47-18c13-6,29-13,44-19c18-8,39-19,59-29
|
||||
c16-8,34-18,51-28c13-7,43-30,59-30c18,0,30,16,30,30c0,29-39,38-57,51c-19,13-42,23-62,34c-40,21-81,39-120,54
|
||||
c-51,19-107,37-157,49c-19,4-38,9-57,12c-10,2-114,18-143,18h-132c-35-3-72-7-107-12c-31-5-64-11-95-18c-24-5-50-12-73-19
|
||||
c-40-11-79-25-117-40c-69-26-141-60-209-105c-12-8-13-16-13-25c0-15,11-29,29-29C531,2546,563,2569,569,2572z"/>
|
||||
<path class="st1" d="M1151,2009L61,2372V764l1090-363V2009z M1212,354v1680c-1,5-3,10-7,15c-2,3-6,7-9,8c-25,10-1151,388-1166,388
|
||||
c-12,0-23-8-29-21c0-1-1-2-1-4V739c2-5,3-12,7-16c8-11,22-13,31-16c17-6,1126-378,1142-378C1190,329,1212,336,1212,354z"/>
|
||||
<path class="st1" d="M2120,2017l-907-282V380l907-308V2017z M2181,32v2023c-1,23-17,33-32,33c-13,0-107-32-123-37
|
||||
c-126-39-253-78-378-117c-28-9-57-18-84-27c-24-7-50-15-74-23c-107-33-216-66-323-102c-4-1-14-15-14-18V351c2-5,4-11,9-15
|
||||
c8-9,351-123,486-168c36-13,487-168,501-168C2167,0,2181,13,2181,32z"/>
|
||||
<polygon points="2411.2,2440.7 1199.5,2054.5 1204.6,373.2 2411.2,757.2 "/>
|
||||
<g>
|
||||
<path class="st2" d="M1800.3,1124.6L1681.4,1412l218.6,66.3L1800.3,1124.6z M1729,853.2l156.1,47.3l284.4,1025l-160.3-48.7
|
||||
l-57.6-210.4L1620.2,1566l-71.3,171.4l-160.4-48.7L1729,853.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
BIN
packages/demobank-ui/src/assets/icons/mstile-150x150.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
45
packages/demobank-ui/src/assets/logo-white.svg
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="670"
|
||||
height="300"
|
||||
viewBox="0 0 201 90"
|
||||
version="1.1"
|
||||
id="svg8">
|
||||
<g
|
||||
id="logo">
|
||||
<g
|
||||
id="circles"
|
||||
style="fill:#FFF;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.327943">
|
||||
<path
|
||||
d="m 86.662153,1.1211936 c 15.589697,0 29.129227,9.4011664 35.961027,23.2018054 h -5.81736 C 110.4866,13.623304 99.349002,6.5180852 86.662153,6.5180852 c -19.690571,0 -35.652876,17.1120008 -35.652876,38.2205688 0,10.331797 3.825597,19.704678 10.03957,26.582945 -1.342357,1.120912 -2.771532,2.127905 -4.275488,3.006754 C 50.071485,66.553412 45.974857,56.15992 45.974857,44.738654 c 0,-24.089211 18.216325,-43.6174604 40.687296,-43.6174604 z M 122.51416,65.375898 c -6.86645,13.680134 -20.34561,22.980218 -35.852007,22.980218 -1.052702,0 -2.096093,-0.04291 -3.128683,-0.127026 3.052192,-1.561167 5.913582,-3.480387 8.538307,-5.707305 10.320963,-1.684389 19.185983,-8.113638 24.601813,-17.145887 z"
|
||||
id="path2350" />
|
||||
<path
|
||||
d="m 64.212372,1.1211936 c 1.052607,0 2.095998,0.042919 3.128684,0.1270583 C 64.288864,2.8094199 61.427378,4.728606 58.802653,6.9555572 41.679542,9.7498571 28.559494,25.601563 28.559494,44.738654 c 0,14.264563 7.29059,26.702023 18.093843,33.268925 -1.593656,0.26719 -3.226966,0.406948 -4.890748,0.406948 -1.239545,0 -2.46151,-0.07952 -3.663522,-0.229364 C 29.191129,70.184015 23.525076,58.171633 23.525076,44.738654 23.525076,20.649443 41.7414,1.1211936 64.212372,1.1211936 Z M 69.62209,82.521785 C 79.943207,80.837396 88.808164,74.407841 94.224059,65.375422 h 5.840511 c -6.866354,13.680305 -20.345548,22.980694 -35.852198,22.980694 -1.052703,0 -2.095999,-0.04291 -3.128684,-0.127026 3.052002,-1.561371 5.913836,-3.480218 8.538402,-5.707305 z M 94.355885,24.322999 c -3.13939,-5.314721 -7.467551,-9.74275 -12.584511,-12.853269 1.593656,-0.26719 3.226904,-0.406948 4.890779,-0.406948 1.239451,0 2.461512,0.07952 3.663524,0.229364 4.016018,3.607242 7.373195,8.030111 9.849053,13.030853 z"
|
||||
id="path2352" />
|
||||
<path
|
||||
d="m 41.762589,1.1211936 c 1.064296,0 2.118804,0.044379 3.162607,0.1302161 -3.046523,1.558961 -5.903162,3.4745139 -8.52358,5.6968133 C 19.254624,9.7205882 6.1097128,25.583465 6.1097128,44.738654 c 0,21.108568 15.9624012,38.22057 35.6528762,38.22057 12.599746,0 23.672446,-7.007056 30.013748,-17.583802 h 5.838515 C 70.748498,79.055727 57.26924,88.356116 41.762589,88.356116 c -22.470907,0 -40.6871998,-19.52825 -40.6871998,-43.617462 0,-24.089211 18.2162928,-43.6174604 40.6871998,-43.6174604 z M 71.905375,24.322999 c -1.31192,-2.220567 -2.830984,-4.287049 -4.528877,-6.166508 1.342452,-1.120945 2.771374,-2.128381 4.275139,-3.00723 2.372984,2.753011 4.418875,5.834636 6.072489,9.173738 z"
|
||||
id="path2354" />
|
||||
</g>
|
||||
<g
|
||||
id="letters"
|
||||
style="fill:#FFF">
|
||||
<path
|
||||
d="m 76.135411,34.409066 h 9.161042 V 29.36588 H 61.857537 v 5.043186 h 9.161137 v 25.92317 h 5.116737 z"
|
||||
id="path2346" />
|
||||
<path
|
||||
d="m 92.647571,52.856334 h 13.659009 l 2.93009,7.476072 h 5.36461 L 101.89122,29.144903 H 97.187186 L 84.477089,60.332406 h 5.199533 z m 11.802109,-4.822276 h -9.944771 l 4.951718,-12.386462 z"
|
||||
id="path2362" />
|
||||
<path
|
||||
d="m 123.80641,29.366084 h -4.58038 v 30.966322 h 20.54728 v -4.910253 c -5.32227,0 -10.64463,0 -15.9669,0 z"
|
||||
id="path2356" />
|
||||
<path
|
||||
d="m 166.4722,29.366084 h -21.37564 v 30.966322 h 21.58203 v -4.910253 h -16.54771 v -8.27275 h 14.48439 V 42.23925 h -14.48439 v -7.962811 h 16.34132 z"
|
||||
id="path2360" />
|
||||
<path
|
||||
d="m 191.19035,39.474593 c 0,1.59947 -0.53646,2.87535 -1.61628,3.818883 -1.07281,0.95124 -2.52409,1.422837 -4.34678,1.422837 h -7.44851 V 34.276439 h 7.4073 c 1.9051,0 3.38376,0.435027 4.42939,1.312178 1.05226,0.870258 1.57488,2.167734 1.57488,3.885976 z m 6.06602,20.857813 -7.79911,-11.723191 c 1.01771,-0.294794 1.94631,-0.714813 2.78553,-1.260566 0.83885,-0.545619 1.56122,-1.209263 2.16629,-1.990627 0.60541,-0.781738 1.07981,-1.681096 1.42369,-2.698345 0.34378,-1.017553 0.51561,-2.175238 0.51561,-3.472883 0,-1.50409 -0.24743,-2.867948 -0.74267,-4.092048 -0.49515,-1.223794 -1.20344,-2.256186 -2.12499,-3.096734 -0.92173,-0.840446 -2.04957,-1.489252 -3.38375,-1.946452 -1.33447,-0.457267 -2.82692,-0.685476 -4.4774,-0.685476 h -12.87512 v 30.966322 h 5.03433 V 49.538522 h 6.37569 l 7.11829,10.793884 z"
|
||||
id="path2358" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.5 KiB |
BIN
packages/demobank-ui/src/assets/logo.jpeg
Normal file
After Width: | Height: | Size: 38 KiB |
66
packages/demobank-ui/src/components/AsyncButton.tsx
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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<void>;
|
||||
grabFocus?: boolean;
|
||||
[rest: string]: any;
|
||||
};
|
||||
|
||||
export function AsyncButton({
|
||||
onClick,
|
||||
grabFocus,
|
||||
disabled,
|
||||
children,
|
||||
...rest
|
||||
}: Props): VNode {
|
||||
const { isLoading, request } = useAsync(onClick);
|
||||
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
useLayoutEffect(() => {
|
||||
if (grabFocus)
|
||||
buttonRef.current?.focus();
|
||||
|
||||
}, [grabFocus]);
|
||||
|
||||
// if (isSlow) {
|
||||
// return <LoadingModal onCancel={cancel} />;
|
||||
// }
|
||||
if (isLoading)
|
||||
return <button class="button">Loading...</button>;
|
||||
|
||||
|
||||
return (
|
||||
<span data-tooltip={rest['data-tooltip']} style={{ marginLeft: 5 }}>
|
||||
<button {...rest} ref={buttonRef} onClick={request} disabled={disabled}>
|
||||
{children}
|
||||
</button>
|
||||
</span>
|
||||
);
|
||||
}
|
57
packages/demobank-ui/src/components/FileButton.tsx
Normal file
@ -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<HTMLInputElement>(null);
|
||||
const [sizeError, setSizeError] = useState(false);
|
||||
return (
|
||||
<div>
|
||||
<button class="button" onClick={(e) => fileInputRef.current?.click()}>
|
||||
<span>{props.label}</span>
|
||||
</button>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
style={{ display: 'none' }}
|
||||
type="file"
|
||||
onChange={(e) => {
|
||||
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 && (
|
||||
<p class="help is-danger">File should be smaller than 1 MB</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
74
packages/demobank-ui/src/components/Notifications.tsx
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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 (
|
||||
<div class="block">
|
||||
{notifications.map((n, i) => (
|
||||
<article key={i} class={messageStyle(n.type)}>
|
||||
<div class="message-header">
|
||||
<p>{n.message}</p>
|
||||
{removeNotification && (
|
||||
<button
|
||||
class="delete"
|
||||
onClick={() => removeNotification && removeNotification(n)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{n.description && <div class="message-body">{n.description}</div>}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
48
packages/demobank-ui/src/components/QR.tsx
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
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<HTMLDivElement>(null);
|
||||
useEffect(() => {
|
||||
const qr = qrcode(0, 'L');
|
||||
qr.addData(text);
|
||||
qr.make();
|
||||
if (divRef.current)
|
||||
divRef.current.innerHTML = qr.createSvgTag({
|
||||
scalable: true,
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'left',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{ width: '50%', minWidth: 200, maxWidth: 300 }}
|
||||
ref={divRef}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
14
packages/demobank-ui/src/components/app.tsx
Normal file
@ -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 (
|
||||
<TranslationProvider>
|
||||
<BankHome />
|
||||
</TranslationProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
90
packages/demobank-ui/src/components/fields/DateInput.tsx
Normal file
@ -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<number>;
|
||||
onConfirm?: () => void;
|
||||
bind: [string, (x: string) => void];
|
||||
}
|
||||
|
||||
export function DateInput(props: DateInputProps): VNode {
|
||||
const inputRef = useRef<HTMLInputElement>(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 (
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{props.label}
|
||||
{props.tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
<div class="control">
|
||||
<div class="field has-addons">
|
||||
<p class="control">
|
||||
<input
|
||||
type="text"
|
||||
class={showError ? 'input is-danger' : 'input'}
|
||||
value={value}
|
||||
onKeyPress={(e) => {
|
||||
if (e.key === 'Enter' && props.onConfirm)
|
||||
props.onConfirm()
|
||||
|
||||
}}
|
||||
onInput={(e) => {
|
||||
const text = e.currentTarget.value;
|
||||
setDirty(true);
|
||||
props.bind[1](text);
|
||||
}}
|
||||
ref={inputRef}
|
||||
/>
|
||||
</p>
|
||||
<p class="control">
|
||||
<a
|
||||
class="button"
|
||||
onClick={() => {
|
||||
setOpened(true);
|
||||
}}
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-calendar" />
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="help">Using the format yyyy-mm-dd</p>
|
||||
{showError && <p class="help is-danger">{props.error}</p>}
|
||||
<DatePicker
|
||||
opened={opened}
|
||||
initialDate={calendar}
|
||||
years={props.years}
|
||||
closeFunction={() => setOpened(false)}
|
||||
dateReceiver={(d) => {
|
||||
setDirty(true);
|
||||
const v = format(d, 'yyyy-MM-dd');
|
||||
props.bind[1](v);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
57
packages/demobank-ui/src/components/fields/EmailInput.tsx
Normal file
@ -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<HTMLInputElement>(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 (
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{props.label}
|
||||
{props.tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
value={value}
|
||||
required
|
||||
placeholder={props.placeholder}
|
||||
type="email"
|
||||
class={showError ? 'input is-danger' : 'input'}
|
||||
onKeyPress={(e) => {
|
||||
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' }}
|
||||
/>
|
||||
</div>
|
||||
{showError && <p class="help is-danger">{props.error}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
104
packages/demobank-ui/src/components/fields/FileInput.tsx
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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<HTMLInputElement>(null);
|
||||
useLayoutEffect(() => {
|
||||
if (props.grabFocus)
|
||||
inputRef.current?.focus();
|
||||
|
||||
}, [props.grabFocus]);
|
||||
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [sizeError, setSizeError] = useState(false);
|
||||
return (
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
<a class="button" onClick={(e) => fileInputRef.current?.click()}>
|
||||
<div class="icon is-small ">
|
||||
<i class="mdi mdi-folder" />
|
||||
</div>
|
||||
<span>
|
||||
{props.label}
|
||||
</span>
|
||||
</a>
|
||||
{props.tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
<div class="control">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
style={{ display: 'none' }}
|
||||
type="file"
|
||||
// name={String(name)}
|
||||
onChange={(e) => {
|
||||
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 && <p class="help is-danger">{props.error}</p>}
|
||||
{sizeError && (
|
||||
<p class="help is-danger">File should be smaller than 1 MB</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
93
packages/demobank-ui/src/components/fields/ImageInput.tsx
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @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<HTMLInputElement>(null);
|
||||
useLayoutEffect(() => {
|
||||
if (props.grabFocus)
|
||||
inputRef.current?.focus();
|
||||
|
||||
}, [props.grabFocus]);
|
||||
|
||||
const value = props.bind[0];
|
||||
// const [dirty, setDirty] = useState(false)
|
||||
const image = useRef<HTMLInputElement>(null);
|
||||
const [sizeError, setSizeError] = useState(false);
|
||||
function onChange(v: string): void {
|
||||
// setDirty(true);
|
||||
props.bind[1](v);
|
||||
}
|
||||
return (
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{props.label}
|
||||
{props.tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
<div class="control">
|
||||
<img
|
||||
src={!value ? emptyImage : value}
|
||||
style={{ width: 200, height: 200 }}
|
||||
onClick={() => image.current?.click()}
|
||||
/>
|
||||
<input
|
||||
ref={image}
|
||||
style={{ display: 'none' }}
|
||||
type="file"
|
||||
name={String(name)}
|
||||
onChange={(e) => {
|
||||
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 && <p class="help is-danger">{props.error}</p>}
|
||||
{sizeError && (
|
||||
<p class="help is-danger">Image should be smaller than 1 MB</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
56
packages/demobank-ui/src/components/fields/NumberInput.tsx
Normal file
@ -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<HTMLInputElement>(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 (
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{props.label}
|
||||
{props.tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
<div class="control has-icons-right">
|
||||
<input
|
||||
value={value}
|
||||
type="tel"
|
||||
placeholder={props.placeholder}
|
||||
class={showError ? 'input is-danger' : 'input'}
|
||||
onKeyPress={(e) => {
|
||||
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' }}
|
||||
/>
|
||||
</div>
|
||||
{showError && <p class="help is-danger">{props.error}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
68
packages/demobank-ui/src/components/fields/TextInput.tsx
Normal file
@ -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<HTMLInputElement>(null);
|
||||
useLayoutEffect(() => {
|
||||
if (grabFocus)
|
||||
inputRef.current?.focus();
|
||||
|
||||
}, [grabFocus]);
|
||||
|
||||
return inputType === 'multiline' ? (
|
||||
<textarea {...rest} rows={5} ref={inputRef} style={{ height: 'unset' }} />
|
||||
) : (
|
||||
<input {...rest} type={inputType} ref={inputRef} />
|
||||
);
|
||||
};
|
||||
|
||||
export function TextInput(props: TextInputProps): VNode {
|
||||
const value = props.bind[0];
|
||||
const [dirty, setDirty] = useState(false);
|
||||
const showError = dirty && props.error;
|
||||
return (
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{props.label}
|
||||
{props.tooltip && (
|
||||
<span class="icon has-tooltip-right" data-tooltip={props.tooltip}>
|
||||
<i class="mdi mdi-information" />
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
<div class="control has-icons-right">
|
||||
<TextInputType
|
||||
inputType={props.inputType}
|
||||
value={value}
|
||||
grabFocus={props.grabFocus}
|
||||
disabled={props.disabled}
|
||||
placeholder={props.placeholder}
|
||||
class={showError ? 'input is-danger' : 'input'}
|
||||
onKeyPress={(e: any) => {
|
||||
if (e.key === 'Enter' && props.onConfirm)
|
||||
props.onConfirm();
|
||||
|
||||
}}
|
||||
onInput={(e: any) => {
|
||||
setDirty(true);
|
||||
props.bind[1]((e.target as HTMLInputElement).value);
|
||||
}}
|
||||
style={{ display: 'block' }}
|
||||
/>
|
||||
</div>
|
||||
{showError && <p class="help is-danger">{props.error}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
101
packages/demobank-ui/src/components/menu/LangSelector.tsx
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
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, Fragment } from 'preact';
|
||||
import { useCallback, useEffect, useState } from 'preact/hooks';
|
||||
import langIcon from '../../assets/icons/languageicon.svg';
|
||||
import { useTranslationContext } from '../../context/translation';
|
||||
import { strings as messages } from '../../i18n/strings';
|
||||
|
||||
type LangsNames = {
|
||||
[P in keyof typeof messages]: string;
|
||||
};
|
||||
|
||||
const names: LangsNames = {
|
||||
es: 'Español [es]',
|
||||
en: 'English [en]',
|
||||
fr: 'Français [fr]',
|
||||
de: 'Deutsch [de]',
|
||||
sv: 'Svenska [sv]',
|
||||
it: 'Italiano [it]',
|
||||
};
|
||||
|
||||
function getLangName(s: keyof LangsNames | string): string {
|
||||
if (names[s]) return names[s];
|
||||
return String(s);
|
||||
}
|
||||
|
||||
// FIXME: explain "like py".
|
||||
export function LangSelectorLikePy(): VNode {
|
||||
const [updatingLang, setUpdatingLang] = useState(false);
|
||||
const { lang, changeLanguage } = useTranslationContext();
|
||||
const [hidden, setHidden] = useState(true)
|
||||
useEffect(() => {
|
||||
function bodyKeyPress(event:KeyboardEvent) {
|
||||
if (event.code === 'Escape')
|
||||
setHidden(true);
|
||||
|
||||
}
|
||||
function bodyOnClick(event:Event) {
|
||||
setHidden(true);
|
||||
}
|
||||
document.body.addEventListener('click', bodyOnClick)
|
||||
document.body.addEventListener('keydown', bodyKeyPress as any)
|
||||
return () => {
|
||||
document.body.removeEventListener('keydown', bodyKeyPress as any)
|
||||
document.body.removeEventListener('click', bodyOnClick)
|
||||
}
|
||||
},[])
|
||||
return (
|
||||
<Fragment>
|
||||
<button name="language" onClick={(ev) => {
|
||||
setHidden(h => !h);
|
||||
ev.stopPropagation();
|
||||
}}>
|
||||
{getLangName(lang)}
|
||||
</button>
|
||||
<div id="lang" class={hidden ? 'hide' : ''}>
|
||||
<div style="position: relative; overflow: visible;">
|
||||
<div
|
||||
class="nav"
|
||||
style="position: absolute; max-height: 60vh; overflow-y: scroll">
|
||||
{Object.keys(messages)
|
||||
.filter((l) => l !== lang)
|
||||
.map((l) => (
|
||||
<a
|
||||
key={l}
|
||||
href="#"
|
||||
class="navbtn langbtn"
|
||||
value={l}
|
||||
onClick={() => {
|
||||
changeLanguage(l);
|
||||
setUpdatingLang(false);
|
||||
}}>
|
||||
{getLangName(l)}
|
||||
</a>
|
||||
))}
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
53
packages/demobank-ui/src/components/menu/NavigationBar.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
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 } from 'preact';
|
||||
import logo from '../../assets/logo.jpeg';
|
||||
import { LangSelectorLikePy as LangSelector } from './LangSelector';
|
||||
|
||||
interface Props {
|
||||
onMobileMenu: () => void;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export function NavigationBar({ onMobileMenu, title }: Props): VNode {
|
||||
return (
|
||||
<nav
|
||||
class="navbar is-fixed-top"
|
||||
role="navigation"
|
||||
aria-label="main navigation"
|
||||
>
|
||||
<div class="navbar-brand">
|
||||
<span class="navbar-item" style={{ fontSize: 24, fontWeight: 900 }}>
|
||||
{title}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="navbar-menu ">
|
||||
<div class="navbar-end">
|
||||
<div class="navbar-item" style={{ paddingTop: 4, paddingBottom: 4 }}>
|
||||
{/* <LangSelector /> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
73
packages/demobank-ui/src/components/menu/SideBar.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
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 } from 'preact';
|
||||
import { Translate } from '../../i18n';
|
||||
|
||||
interface Props {
|
||||
mobile?: boolean;
|
||||
}
|
||||
|
||||
export function Sidebar({ mobile }: Props): VNode {
|
||||
// const config = useConfigContext();
|
||||
const config = { version: 'none' };
|
||||
// FIXME: add replacement for __VERSION__ with the current version
|
||||
const process = { env: { __VERSION__: '0.0.0' } };
|
||||
|
||||
return (
|
||||
<aside class="aside is-placed-left is-expanded">
|
||||
<div class="aside-tools">
|
||||
<div class="aside-tools-label">
|
||||
<div>
|
||||
<b>euFin bank</b>
|
||||
</div>
|
||||
<div
|
||||
class="is-size-7 has-text-right"
|
||||
style={{ lineHeight: 0, marginTop: -10 }}
|
||||
>
|
||||
Version {process.env.__VERSION__} ({config.version})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu is-menu-main">
|
||||
<p class="menu-label">
|
||||
<Translate>Bank menu</Translate>
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<div class="ml-4">
|
||||
<span class="menu-item-label">
|
||||
<Translate>Select option1</Translate>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="ml-4">
|
||||
<span class="menu-item-label">
|
||||
<Translate>Select option2</Translate>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
135
packages/demobank-ui/src/components/menu/index.tsx
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
import { ComponentChildren, Fragment, h, VNode } from 'preact';
|
||||
import Match from 'preact-router/match';
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { NavigationBar } from './NavigationBar';
|
||||
import { Sidebar } from './SideBar';
|
||||
|
||||
interface MenuProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
function WithTitle({
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
title: string;
|
||||
children: ComponentChildren;
|
||||
}): VNode {
|
||||
useEffect(() => {
|
||||
document.title = `${title}`;
|
||||
}, [title]);
|
||||
return <Fragment>{children}</Fragment>;
|
||||
}
|
||||
|
||||
export function Menu({ title }: MenuProps): VNode {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Match>
|
||||
{({ path }: { path: string }) => {
|
||||
const titleWithSubtitle = title; // title ? title : (!admin ? getInstanceTitle(path, instance) : getAdminTitle(path, instance))
|
||||
return (
|
||||
<WithTitle title={titleWithSubtitle}>
|
||||
<div
|
||||
class={mobileOpen ? 'has-aside-mobile-expanded' : ''}
|
||||
onClick={() => setMobileOpen(false)}
|
||||
>
|
||||
<NavigationBar
|
||||
onMobileMenu={() => setMobileOpen(!mobileOpen)}
|
||||
title={titleWithSubtitle}
|
||||
/>
|
||||
|
||||
<Sidebar mobile={mobileOpen} />
|
||||
</div>
|
||||
</WithTitle>
|
||||
);
|
||||
}}
|
||||
</Match>
|
||||
);
|
||||
}
|
||||
|
||||
interface NotYetReadyAppMenuProps {
|
||||
title: string;
|
||||
onLogout?: () => void;
|
||||
}
|
||||
|
||||
interface NotifProps {
|
||||
notification?: Notification;
|
||||
}
|
||||
export function NotificationCard({
|
||||
notification: n,
|
||||
}: NotifProps): VNode | null {
|
||||
if (!n) return null;
|
||||
return (
|
||||
<div class="notification">
|
||||
<div class="columns is-vcentered">
|
||||
<div class="column is-12">
|
||||
<article
|
||||
class={
|
||||
n.type === 'ERROR'
|
||||
? 'message is-danger'
|
||||
: n.type === 'WARN'
|
||||
? 'message is-warning'
|
||||
: 'message is-info'
|
||||
}
|
||||
>
|
||||
<div class="message-header">
|
||||
<p>{n.message}</p>
|
||||
</div>
|
||||
{n.description && <div class="message-body">{n.description}</div>}
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function NotYetReadyAppMenu({
|
||||
onLogout,
|
||||
title,
|
||||
}: NotYetReadyAppMenuProps): VNode {
|
||||
const [mobileOpen, setMobileOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `Taler Backoffice: ${title}`;
|
||||
}, [title]);
|
||||
|
||||
return (
|
||||
<div
|
||||
class="has-aside-mobile-expanded"
|
||||
// class={mobileOpen ? "has-aside-mobile-expanded" : ""}
|
||||
onClick={() => setMobileOpen(false)}
|
||||
>
|
||||
<NavigationBar
|
||||
onMobileMenu={() => setMobileOpen(!mobileOpen)}
|
||||
title={title}
|
||||
/>
|
||||
{onLogout && <Sidebar mobile={mobileOpen} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
message: string;
|
||||
description?: string | VNode;
|
||||
type: MessageType;
|
||||
}
|
||||
|
||||
export type ValueOrFunction<T> = T | ((p: T) => T);
|
||||
export type MessageType = 'INFO' | 'WARN' | 'ERROR' | 'SUCCESS';
|
356
packages/demobank-ui/src/components/picker/DatePicker.tsx
Normal file
@ -0,0 +1,356 @@
|
||||
/*
|
||||
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, Component } from 'preact';
|
||||
|
||||
interface Props {
|
||||
closeFunction?: () => void;
|
||||
dateReceiver?: (d: Date) => void;
|
||||
initialDate?: Date;
|
||||
years?: Array<number>;
|
||||
opened?: boolean;
|
||||
}
|
||||
interface State {
|
||||
displayedMonth: number;
|
||||
displayedYear: number;
|
||||
selectYearMode: boolean;
|
||||
currentDate: Date;
|
||||
}
|
||||
const now = new Date();
|
||||
|
||||
const monthArrShortFull = [
|
||||
'January',
|
||||
'February',
|
||||
'March',
|
||||
'April',
|
||||
'May',
|
||||
'June',
|
||||
'July',
|
||||
'August',
|
||||
'September',
|
||||
'October',
|
||||
'November',
|
||||
'December',
|
||||
];
|
||||
|
||||
const monthArrShort = [
|
||||
'Jan',
|
||||
'Feb',
|
||||
'Mar',
|
||||
'Apr',
|
||||
'May',
|
||||
'Jun',
|
||||
'Jul',
|
||||
'Aug',
|
||||
'Sep',
|
||||
'Oct',
|
||||
'Nov',
|
||||
'Dec',
|
||||
];
|
||||
|
||||
const dayArr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
|
||||
const yearArr: number[] = [];
|
||||
|
||||
// inspired by https://codepen.io/m4r1vs/pen/MOOxyE
|
||||
export class DatePicker extends Component<Props, State> {
|
||||
closeDatePicker() {
|
||||
this.props.closeFunction && this.props.closeFunction(); // Function gets passed by parent
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets fired when a day gets clicked.
|
||||
* @param {object} e The event thrown by the <span /> element clicked
|
||||
*/
|
||||
dayClicked(e: any) {
|
||||
const element = e.target; // the actual element clicked
|
||||
|
||||
if (element.innerHTML === '') return false; // don't continue if <span /> empty
|
||||
|
||||
// get date from clicked element (gets attached when rendered)
|
||||
const date = new Date(element.getAttribute('data-value'));
|
||||
|
||||
// update the state
|
||||
this.setState({ currentDate: date });
|
||||
this.passDateToParent(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns days in month as array
|
||||
* @param {number} month the month to display
|
||||
* @param {number} year the year to display
|
||||
*/
|
||||
getDaysByMonth(month: number, year: number) {
|
||||
const calendar = [];
|
||||
|
||||
const date = new Date(year, month, 1); // month to display
|
||||
|
||||
const firstDay = new Date(year, month, 1).getDay(); // first weekday of month
|
||||
const lastDate = new Date(year, month + 1, 0).getDate(); // last date of month
|
||||
|
||||
let day: number | null = 0;
|
||||
|
||||
// the calendar is 7*6 fields big, so 42 loops
|
||||
for (let i = 0; i < 42; i++) {
|
||||
if (i >= firstDay && day !== null) day = day + 1;
|
||||
if (day !== null && day > lastDate) day = null;
|
||||
|
||||
// append the calendar Array
|
||||
calendar.push({
|
||||
day: day === 0 || day === null ? null : day, // null or number
|
||||
date: day === 0 || day === null ? null : new Date(year, month, day), // null or Date()
|
||||
today:
|
||||
day === now.getDate() &&
|
||||
month === now.getMonth() &&
|
||||
year === now.getFullYear(), // boolean
|
||||
});
|
||||
}
|
||||
|
||||
return calendar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display previous month by updating state
|
||||
*/
|
||||
displayPrevMonth() {
|
||||
if (this.state.displayedMonth <= 0)
|
||||
this.setState({
|
||||
displayedMonth: 11,
|
||||
displayedYear: this.state.displayedYear - 1,
|
||||
});
|
||||
else
|
||||
this.setState({
|
||||
displayedMonth: this.state.displayedMonth - 1,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display next month by updating state
|
||||
*/
|
||||
displayNextMonth() {
|
||||
if (this.state.displayedMonth >= 11)
|
||||
this.setState({
|
||||
displayedMonth: 0,
|
||||
displayedYear: this.state.displayedYear + 1,
|
||||
});
|
||||
else
|
||||
this.setState({
|
||||
displayedMonth: this.state.displayedMonth + 1,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the selected month (gets fired when clicking on the date string)
|
||||
*/
|
||||
displaySelectedMonth() {
|
||||
if (this.state.selectYearMode)
|
||||
this.toggleYearSelector();
|
||||
else {
|
||||
if (!this.state.currentDate) return false;
|
||||
this.setState({
|
||||
displayedMonth: this.state.currentDate.getMonth(),
|
||||
displayedYear: this.state.currentDate.getFullYear(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
toggleYearSelector() {
|
||||
this.setState({ selectYearMode: !this.state.selectYearMode });
|
||||
}
|
||||
|
||||
changeDisplayedYear(e: any) {
|
||||
const element = e.target;
|
||||
this.toggleYearSelector();
|
||||
this.setState({
|
||||
displayedYear: parseInt(element.innerHTML, 10),
|
||||
displayedMonth: 0,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the selected date to parent when 'OK' is clicked
|
||||
*/
|
||||
passSavedDateDateToParent() {
|
||||
this.passDateToParent(this.state.currentDate);
|
||||
}
|
||||
passDateToParent(date: Date) {
|
||||
if (typeof this.props.dateReceiver === 'function')
|
||||
this.props.dateReceiver(date);
|
||||
this.closeDatePicker();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
// if (this.state.selectYearMode) {
|
||||
// document.getElementsByClassName('selected')[0].scrollIntoView(); // works in every browser incl. IE, replace with scrollIntoViewIfNeeded when browsers support it
|
||||
// }
|
||||
}
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
|
||||
this.closeDatePicker = this.closeDatePicker.bind(this);
|
||||
this.dayClicked = this.dayClicked.bind(this);
|
||||
this.displayNextMonth = this.displayNextMonth.bind(this);
|
||||
this.displayPrevMonth = this.displayPrevMonth.bind(this);
|
||||
this.getDaysByMonth = this.getDaysByMonth.bind(this);
|
||||
this.changeDisplayedYear = this.changeDisplayedYear.bind(this);
|
||||
this.passDateToParent = this.passDateToParent.bind(this);
|
||||
this.toggleYearSelector = this.toggleYearSelector.bind(this);
|
||||
this.displaySelectedMonth = this.displaySelectedMonth.bind(this);
|
||||
|
||||
const initial = props.initialDate || now;
|
||||
|
||||
this.state = {
|
||||
currentDate: initial,
|
||||
displayedMonth: initial.getMonth(),
|
||||
displayedYear: initial.getFullYear(),
|
||||
selectYearMode: false,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
currentDate,
|
||||
displayedMonth,
|
||||
displayedYear,
|
||||
selectYearMode,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div class={`datePicker ${this.props.opened && 'datePicker--opened'}`}>
|
||||
<div class="datePicker--titles">
|
||||
<h3
|
||||
style={{
|
||||
color: selectYearMode
|
||||
? 'rgba(255,255,255,.87)'
|
||||
: 'rgba(255,255,255,.57)',
|
||||
}}
|
||||
onClick={this.toggleYearSelector}
|
||||
>
|
||||
{currentDate.getFullYear()}
|
||||
</h3>
|
||||
<h2
|
||||
style={{
|
||||
color: !selectYearMode
|
||||
? 'rgba(255,255,255,.87)'
|
||||
: 'rgba(255,255,255,.57)',
|
||||
}}
|
||||
onClick={this.displaySelectedMonth}
|
||||
>
|
||||
{dayArr[currentDate.getDay()]},{' '}
|
||||
{monthArrShort[currentDate.getMonth()]} {currentDate.getDate()}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{!selectYearMode && (
|
||||
<nav>
|
||||
<span onClick={this.displayPrevMonth} class="icon">
|
||||
<i
|
||||
style={{ transform: 'rotate(180deg)' }}
|
||||
class="mdi mdi-forward"
|
||||
/>
|
||||
</span>
|
||||
<h4>
|
||||
{monthArrShortFull[displayedMonth]} {displayedYear}
|
||||
</h4>
|
||||
<span onClick={this.displayNextMonth} class="icon">
|
||||
<i class="mdi mdi-forward" />
|
||||
</span>
|
||||
</nav>
|
||||
)}
|
||||
|
||||
<div class="datePicker--scroll">
|
||||
{!selectYearMode && (
|
||||
<div class="datePicker--calendar">
|
||||
<div class="datePicker--dayNames">
|
||||
{['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((day, i) => (
|
||||
<span key={i}>{day}</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div onClick={this.dayClicked} class="datePicker--days">
|
||||
{/*
|
||||
Loop through the calendar object returned by getDaysByMonth().
|
||||
*/}
|
||||
|
||||
{this.getDaysByMonth(
|
||||
this.state.displayedMonth,
|
||||
this.state.displayedYear,
|
||||
).map((day) => {
|
||||
let selected = false;
|
||||
|
||||
if (currentDate && day.date)
|
||||
selected =
|
||||
currentDate.toLocaleDateString() ===
|
||||
day.date.toLocaleDateString();
|
||||
|
||||
return (
|
||||
<span
|
||||
key={day.day}
|
||||
class={
|
||||
(day.today ? 'datePicker--today ' : '') +
|
||||
(selected ? 'datePicker--selected' : '')
|
||||
}
|
||||
disabled={!day.date}
|
||||
data-value={day.date}
|
||||
>
|
||||
{day.day}
|
||||
</span>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{selectYearMode && (
|
||||
<div class="datePicker--selectYear">
|
||||
{(this.props.years || yearArr).map((year) => (
|
||||
<span
|
||||
key={year}
|
||||
class={year === displayedYear ? 'selected' : ''}
|
||||
onClick={this.changeDisplayedYear}
|
||||
>
|
||||
{year}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="datePicker--background"
|
||||
onClick={this.closeDatePicker}
|
||||
style={{
|
||||
display: this.props.opened ? 'block' : 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 2010; i <= now.getFullYear() + 10; i++)
|
||||
yearArr.push(i);
|
||||
|
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
import { h, FunctionalComponent } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import { DurationPicker as TestedComponent } from './DurationPicker';
|
||||
|
||||
export default {
|
||||
title: 'Components/Picker/Duration',
|
||||
component: TestedComponent,
|
||||
argTypes: {
|
||||
onCreate: { action: 'onCreate' },
|
||||
goBack: { action: 'goBack' },
|
||||
},
|
||||
};
|
||||
|
||||
function createExample<Props>(
|
||||
Component: FunctionalComponent<Props>,
|
||||
props: Partial<Props>,
|
||||
) {
|
||||
const r = (args: any) => <Component {...args} />;
|
||||
r.args = props;
|
||||
return r;
|
||||
}
|
||||
|
||||
export const Example = createExample(TestedComponent, {
|
||||
days: true,
|
||||
minutes: true,
|
||||
hours: true,
|
||||
seconds: true,
|
||||
value: 10000000,
|
||||
});
|
||||
|
||||
export const WithState = () => {
|
||||
const [v, s] = useState<number>(1000000);
|
||||
return <TestedComponent value={v} onChange={s} days minutes hours seconds />;
|
||||
};
|
211
packages/demobank-ui/src/components/picker/DurationPicker.tsx
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
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 } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import { useTranslator } from '../../i18n';
|
||||
import '../../scss/DurationPicker.scss';
|
||||
|
||||
export interface Props {
|
||||
hours?: boolean;
|
||||
minutes?: boolean;
|
||||
seconds?: boolean;
|
||||
days?: boolean;
|
||||
onChange: (value: number) => void;
|
||||
value: number;
|
||||
}
|
||||
|
||||
// inspiration taken from https://github.com/flurmbo/react-duration-picker
|
||||
export function DurationPicker({
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds,
|
||||
onChange,
|
||||
value,
|
||||
}: Props): VNode {
|
||||
const ss = 1000;
|
||||
const ms = ss * 60;
|
||||
const hs = ms * 60;
|
||||
const ds = hs * 24;
|
||||
const i18n = useTranslator();
|
||||
|
||||
return (
|
||||
<div class="rdp-picker">
|
||||
{days && (
|
||||
<DurationColumn
|
||||
unit={i18n`days`}
|
||||
max={99}
|
||||
value={Math.floor(value / ds)}
|
||||
onDecrease={value >= ds ? () => onChange(value - ds) : undefined}
|
||||
onIncrease={value < 99 * ds ? () => onChange(value + ds) : undefined}
|
||||
onChange={(diff) => onChange(value + diff * ds)}
|
||||
/>
|
||||
)}
|
||||
{hours && (
|
||||
<DurationColumn
|
||||
unit={i18n`hours`}
|
||||
max={23}
|
||||
min={1}
|
||||
value={Math.floor(value / hs) % 24}
|
||||
onDecrease={value >= hs ? () => onChange(value - hs) : undefined}
|
||||
onIncrease={value < 99 * ds ? () => onChange(value + hs) : undefined}
|
||||
onChange={(diff) => onChange(value + diff * hs)}
|
||||
/>
|
||||
)}
|
||||
{minutes && (
|
||||
<DurationColumn
|
||||
unit={i18n`minutes`}
|
||||
max={59}
|
||||
min={1}
|
||||
value={Math.floor(value / ms) % 60}
|
||||
onDecrease={value >= ms ? () => onChange(value - ms) : undefined}
|
||||
onIncrease={value < 99 * ds ? () => onChange(value + ms) : undefined}
|
||||
onChange={(diff) => onChange(value + diff * ms)}
|
||||
/>
|
||||
)}
|
||||
{seconds && (
|
||||
<DurationColumn
|
||||
unit={i18n`seconds`}
|
||||
max={59}
|
||||
value={Math.floor(value / ss) % 60}
|
||||
onDecrease={value >= ss ? () => onChange(value - ss) : undefined}
|
||||
onIncrease={value < 99 * ds ? () => onChange(value + ss) : undefined}
|
||||
onChange={(diff) => onChange(value + diff * ss)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface ColProps {
|
||||
unit: string;
|
||||
min?: number;
|
||||
max: number;
|
||||
value: number;
|
||||
onIncrease?: () => void;
|
||||
onDecrease?: () => void;
|
||||
onChange?: (diff: number) => void;
|
||||
}
|
||||
|
||||
function InputNumber({
|
||||
initial,
|
||||
onChange,
|
||||
}: {
|
||||
initial: number;
|
||||
onChange: (n: number) => void;
|
||||
}) {
|
||||
const [value, handler] = useState<{ v: string }>({
|
||||
v: toTwoDigitString(initial),
|
||||
});
|
||||
|
||||
return (
|
||||
<input
|
||||
value={value.v}
|
||||
onBlur={(e) => onChange(parseInt(value.v, 10))}
|
||||
onInput={(e) => {
|
||||
e.preventDefault();
|
||||
const n = Number.parseInt(e.currentTarget.value, 10);
|
||||
if (isNaN(n)) return handler({ v: toTwoDigitString(initial) });
|
||||
return handler({ v: toTwoDigitString(n) });
|
||||
}}
|
||||
style={{
|
||||
width: 50,
|
||||
border: 'none',
|
||||
fontSize: 'inherit',
|
||||
background: 'inherit',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function DurationColumn({
|
||||
unit,
|
||||
min = 0,
|
||||
max,
|
||||
value,
|
||||
onIncrease,
|
||||
onDecrease,
|
||||
onChange,
|
||||
}: ColProps): VNode {
|
||||
const cellHeight = 35;
|
||||
return (
|
||||
<div class="rdp-column-container">
|
||||
<div class="rdp-masked-div">
|
||||
<hr class="rdp-reticule" style={{ top: cellHeight * 2 - 1 }} />
|
||||
<hr class="rdp-reticule" style={{ top: cellHeight * 3 - 1 }} />
|
||||
|
||||
<div class="rdp-column" style={{ top: 0 }}>
|
||||
<div class="rdp-cell" key={value - 2}>
|
||||
{onDecrease && (
|
||||
<button
|
||||
style={{ width: '100%', textAlign: 'center', margin: 5 }}
|
||||
onClick={onDecrease}
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-chevron-up" />
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div class="rdp-cell" key={value - 1}>
|
||||
{value > min ? toTwoDigitString(value - 1) : ''}
|
||||
</div>
|
||||
<div class="rdp-cell rdp-center" key={value}>
|
||||
{onChange ? (
|
||||
<InputNumber
|
||||
initial={value}
|
||||
onChange={(n) => onChange(n - value)}
|
||||
/>
|
||||
) : (
|
||||
toTwoDigitString(value)
|
||||
)}
|
||||
<div>{unit}</div>
|
||||
</div>
|
||||
|
||||
<div class="rdp-cell" key={value + 1}>
|
||||
{value < max ? toTwoDigitString(value + 1) : ''}
|
||||
</div>
|
||||
|
||||
<div class="rdp-cell" key={value + 2}>
|
||||
{onIncrease && (
|
||||
<button
|
||||
style={{ width: '100%', textAlign: 'center', margin: 5 }}
|
||||
onClick={onIncrease}
|
||||
>
|
||||
<span class="icon">
|
||||
<i class="mdi mdi-chevron-down" />
|
||||
</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function toTwoDigitString(n: number) {
|
||||
if (n < 10)
|
||||
return `0${n}`;
|
||||
|
||||
return `${n}`;
|
||||
}
|
73
packages/demobank-ui/src/context/translation.ts
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
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 { createContext, h, VNode } from 'preact';
|
||||
import { useContext, useEffect } from 'preact/hooks';
|
||||
import { useLang } from '../hooks';
|
||||
import * as jedLib from 'jed';
|
||||
import { strings } from '../i18n/strings';
|
||||
|
||||
interface Type {
|
||||
lang: string;
|
||||
handler: any;
|
||||
changeLanguage: (l: string) => void;
|
||||
}
|
||||
const initial = {
|
||||
lang: 'en',
|
||||
handler: null,
|
||||
changeLanguage: () => {
|
||||
/**
|
||||
* This function will be replaced by one with
|
||||
* the same signature _but_ coming from the state.
|
||||
* FIXME: clarify this design.
|
||||
*/
|
||||
},
|
||||
};
|
||||
const Context = createContext<Type>(initial);
|
||||
|
||||
interface Props {
|
||||
initial?: string;
|
||||
children: any;
|
||||
forceLang?: string;
|
||||
}
|
||||
|
||||
// Outmost UI wrapper.
|
||||
export const TranslationProvider = ({
|
||||
initial,
|
||||
children,
|
||||
forceLang,
|
||||
}: Props): VNode => {
|
||||
|
||||
const [lang, changeLanguage] = useLang(initial);
|
||||
useEffect(() => {
|
||||
if (forceLang)
|
||||
changeLanguage(forceLang);
|
||||
|
||||
});
|
||||
console.log('lang store', strings);
|
||||
const handler = new jedLib.Jed(strings[lang] || strings['en']);
|
||||
return h(Context.Provider, {
|
||||
value: { lang, handler, changeLanguage },
|
||||
children,
|
||||
});
|
||||
};
|
||||
|
||||
export const useTranslationContext = (): Type => useContext(Context);
|
20
packages/demobank-ui/src/declaration.d.ts
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
declare module '*.css' {
|
||||
const mapping: Record<string, string>;
|
||||
export default mapping;
|
||||
}
|
||||
declare module '*.svg' {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module '*.jpeg' {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module '*.png' {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module 'jed' {
|
||||
const x: any;
|
||||
export = x;
|
||||
}
|
80
packages/demobank-ui/src/hooks/async.ts
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
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 { useState } from 'preact/hooks';
|
||||
// import { cancelPendingRequest } from "./backend";
|
||||
|
||||
export interface Options {
|
||||
slowTolerance: number;
|
||||
}
|
||||
|
||||
export interface AsyncOperationApi<T> {
|
||||
request: (...a: any) => void;
|
||||
cancel: () => void;
|
||||
data: T | undefined;
|
||||
isSlow: boolean;
|
||||
isLoading: boolean;
|
||||
error: string | undefined;
|
||||
}
|
||||
|
||||
export function useAsync<T>(
|
||||
fn?: (...args: any) => Promise<T>,
|
||||
{ slowTolerance: tooLong }: Options = { slowTolerance: 1000 },
|
||||
): AsyncOperationApi<T> {
|
||||
const [data, setData] = useState<T | undefined>(undefined);
|
||||
const [isLoading, setLoading] = useState<boolean>(false);
|
||||
const [error, setError] = useState<any>(undefined);
|
||||
const [isSlow, setSlow] = useState(false);
|
||||
|
||||
const request = async (...args: any) => {
|
||||
if (!fn) return;
|
||||
setLoading(true);
|
||||
const handler = setTimeout(() => {
|
||||
setSlow(true);
|
||||
}, tooLong);
|
||||
|
||||
try {
|
||||
console.log('calling async', args);
|
||||
const result = await fn(...args);
|
||||
console.log('async back', result);
|
||||
setData(result);
|
||||
} catch (error) {
|
||||
setError(error);
|
||||
}
|
||||
setLoading(false);
|
||||
setSlow(false);
|
||||
clearTimeout(handler);
|
||||
};
|
||||
|
||||
function cancel() {
|
||||
// cancelPendingRequest()
|
||||
setLoading(false);
|
||||
setSlow(false);
|
||||
}
|
||||
|
||||
return {
|
||||
request,
|
||||
cancel,
|
||||
data,
|
||||
isSlow,
|
||||
isLoading,
|
||||
error,
|
||||
};
|
||||
}
|
151
packages/demobank-ui/src/hooks/index.ts
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
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 { StateUpdater, useState } from 'preact/hooks';
|
||||
export type ValueOrFunction<T> = T | ((p: T) => T);
|
||||
|
||||
const calculateRootPath = () => {
|
||||
const rootPath =
|
||||
typeof window !== undefined
|
||||
? window.location.origin + window.location.pathname
|
||||
: '/';
|
||||
return rootPath;
|
||||
};
|
||||
|
||||
export function useBackendURL(
|
||||
url?: string,
|
||||
): [string, boolean, StateUpdater<string>, () => void] {
|
||||
const [value, setter] = useNotNullLocalStorage(
|
||||
'backend-url',
|
||||
url || calculateRootPath(),
|
||||
);
|
||||
const [triedToLog, setTriedToLog] = useLocalStorage('tried-login');
|
||||
|
||||
const checkedSetter = (v: ValueOrFunction<string>) => {
|
||||
setTriedToLog('yes');
|
||||
return setter((p) => (v instanceof Function ? v(p) : v).replace(/\/$/, ''));
|
||||
};
|
||||
|
||||
const resetBackend = () => {
|
||||
setTriedToLog(undefined);
|
||||
};
|
||||
return [value, !!triedToLog, checkedSetter, resetBackend];
|
||||
}
|
||||
|
||||
export function useBackendDefaultToken(): [
|
||||
string | undefined,
|
||||
StateUpdater<string | undefined>,
|
||||
] {
|
||||
return useLocalStorage('backend-token');
|
||||
}
|
||||
|
||||
export function useBackendInstanceToken(
|
||||
id: string,
|
||||
): [string | undefined, StateUpdater<string | undefined>] {
|
||||
const [token, setToken] = useLocalStorage(`backend-token-${id}`);
|
||||
const [defaultToken, defaultSetToken] = useBackendDefaultToken();
|
||||
|
||||
// instance named 'default' use the default token
|
||||
if (id === 'default')
|
||||
return [defaultToken, defaultSetToken];
|
||||
|
||||
return [token, setToken];
|
||||
}
|
||||
|
||||
export function useLang(initial?: string): [string, StateUpdater<string>] {
|
||||
const browserLang =
|
||||
typeof window !== 'undefined'
|
||||
? navigator.language || (navigator as any).userLanguage
|
||||
: undefined;
|
||||
const defaultLang = (browserLang || initial || 'en').substring(0, 2);
|
||||
const [value, setValue] = useNotNullLocalStorage('lang-preference', defaultLang);
|
||||
function updateValue(newValue: (string | ((v: string) => string))) {
|
||||
if (document.body.parentElement) {
|
||||
const htmlElement = document.body.parentElement
|
||||
if (typeof newValue === 'string') {
|
||||
htmlElement.lang = newValue;
|
||||
setValue(newValue)
|
||||
} else if (typeof newValue === 'function')
|
||||
setValue((old) => {
|
||||
const nv = newValue(old)
|
||||
htmlElement.lang = nv;
|
||||
return nv
|
||||
})
|
||||
} else setValue(newValue)
|
||||
}
|
||||
return [value, updateValue]
|
||||
}
|
||||
|
||||
export function useLocalStorage(
|
||||
key: string,
|
||||
initialValue?: string,
|
||||
): [string | undefined, StateUpdater<string | undefined>] {
|
||||
const [storedValue, setStoredValue] = useState<string | undefined>(():
|
||||
| string
|
||||
| undefined => {
|
||||
return typeof window !== 'undefined'
|
||||
? window.localStorage.getItem(key) || initialValue
|
||||
: initialValue;
|
||||
});
|
||||
|
||||
const setValue = (
|
||||
value?: string | ((val?: string) => string | undefined),
|
||||
) => {
|
||||
setStoredValue((p) => {
|
||||
const toStore = value instanceof Function ? value(p) : value;
|
||||
if (typeof window !== 'undefined')
|
||||
if (!toStore)
|
||||
window.localStorage.removeItem(key);
|
||||
else
|
||||
window.localStorage.setItem(key, toStore);
|
||||
|
||||
|
||||
return toStore;
|
||||
});
|
||||
};
|
||||
|
||||
return [storedValue, setValue];
|
||||
}
|
||||
|
||||
export function useNotNullLocalStorage(
|
||||
key: string,
|
||||
initialValue: string,
|
||||
): [string, StateUpdater<string>] {
|
||||
const [storedValue, setStoredValue] = useState<string>((): string => {
|
||||
return typeof window !== 'undefined'
|
||||
? window.localStorage.getItem(key) || initialValue
|
||||
: initialValue;
|
||||
});
|
||||
|
||||
const setValue = (value: string | ((val: string) => string)) => {
|
||||
const valueToStore = value instanceof Function ? value(storedValue) : value;
|
||||
setStoredValue(valueToStore);
|
||||
if (typeof window !== 'undefined')
|
||||
if (!valueToStore)
|
||||
window.localStorage.removeItem(key);
|
||||
else
|
||||
window.localStorage.setItem(key, valueToStore);
|
||||
|
||||
|
||||
};
|
||||
|
||||
return [storedValue, setValue];
|
||||
}
|
258
packages/demobank-ui/src/i18n/bank.pot
Normal file
@ -0,0 +1,258 @@
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:55
|
||||
#, c-format
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:65
|
||||
#, c-format
|
||||
msgid "hours"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:76
|
||||
#, c-format
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:87
|
||||
#, c-format
|
||||
msgid "seconds"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:734
|
||||
#, c-format
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:761
|
||||
#, c-format
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:782
|
||||
#, c-format
|
||||
msgid "Demo Bank"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:837
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:840
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1189
|
||||
#, c-format
|
||||
msgid "Go back"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:845
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:906
|
||||
#, c-format
|
||||
msgid "Wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:846
|
||||
#, c-format
|
||||
msgid "Transfer money to another account of this bank:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:897
|
||||
#, c-format
|
||||
msgid "Want to try the raw payto://-format?"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:907
|
||||
#, c-format
|
||||
msgid "Transfer money via the Payto system:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:916
|
||||
#, c-format
|
||||
msgid "payto address"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:926
|
||||
#, c-format
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:956
|
||||
#, c-format
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1026
|
||||
#, c-format
|
||||
msgid "Waiting the bank to create the operaion..."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1044
|
||||
#, c-format
|
||||
msgid "This withdrawal was aborted!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1051
|
||||
#, c-format
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1052
|
||||
#, c-format
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1054
|
||||
#, c-format
|
||||
msgid "this link"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1060
|
||||
#, c-format
|
||||
msgid "Abort"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1084
|
||||
#, c-format
|
||||
msgid "Start withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1101
|
||||
#, c-format
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1105
|
||||
#, c-format
|
||||
msgid "Amount to withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1137
|
||||
#, c-format
|
||||
msgid "Please login!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1169
|
||||
#, c-format
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1184
|
||||
#, c-format
|
||||
msgid "Register to the euFin bank!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1194
|
||||
#, c-format
|
||||
msgid "Registration form"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1232
|
||||
#, c-format
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1272
|
||||
#, c-format
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1273
|
||||
#, c-format
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1274
|
||||
#, c-format
|
||||
msgid "Counterpart"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1275
|
||||
#, c-format
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1343
|
||||
#, c-format
|
||||
msgid "Username or account label '%1$s' not found. Won't login."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1365
|
||||
#, c-format
|
||||
msgid "Wrong credentials given."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1374
|
||||
#, c-format
|
||||
msgid "Account information could not be retrieved."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1394
|
||||
#, c-format
|
||||
msgid "Close wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1412
|
||||
#, c-format
|
||||
msgid "Close Taler withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1457
|
||||
#, c-format
|
||||
msgid "Bank account balance:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1469
|
||||
#, c-format
|
||||
msgid "Latest transactions:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1474
|
||||
#, c-format
|
||||
msgid "Transfer money manually"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1543
|
||||
#, c-format
|
||||
msgid "List of public accounts was not found."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1552
|
||||
#, c-format
|
||||
msgid "List of public accounts could not be retrieved."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1584
|
||||
#, c-format
|
||||
msgid "History of public accounts"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1643
|
||||
#, c-format
|
||||
msgid "Page has a problem: logged in but backend state is lost."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1667
|
||||
#, c-format
|
||||
msgid "Welcome to the euFin bank!"
|
||||
msgstr ""
|
||||
|
||||
# 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/>
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Taler Wallet\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-11-23 00:00+0100\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
257
packages/demobank-ui/src/i18n/de.po
Normal file
@ -0,0 +1,257 @@
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:55
|
||||
#, c-format
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:65
|
||||
#, c-format
|
||||
msgid "hours"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:76
|
||||
#, c-format
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:87
|
||||
#, c-format
|
||||
msgid "seconds"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:734
|
||||
#, c-format
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:761
|
||||
#, c-format
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:782
|
||||
#, c-format
|
||||
msgid "Demo Bank"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:837
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:840
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1189
|
||||
#, c-format
|
||||
msgid "Go back"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:845
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:906
|
||||
#, c-format
|
||||
msgid "Wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:846
|
||||
#, c-format
|
||||
msgid "Transfer money to another account of this bank:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:897
|
||||
#, c-format
|
||||
msgid "Want to try the raw payto://-format?"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:907
|
||||
#, c-format
|
||||
msgid "Transfer money via the Payto system:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:916
|
||||
#, c-format
|
||||
msgid "payto address"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:926
|
||||
#, c-format
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:956
|
||||
#, c-format
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1026
|
||||
#, c-format
|
||||
msgid "Waiting the bank to create the operaion..."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1044
|
||||
#, c-format
|
||||
msgid "This withdrawal was aborted!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1051
|
||||
#, c-format
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1052
|
||||
#, c-format
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1054
|
||||
#, c-format
|
||||
msgid "this link"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1060
|
||||
#, c-format
|
||||
msgid "Abort"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1084
|
||||
#, c-format
|
||||
msgid "Start withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1101
|
||||
#, c-format
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1105
|
||||
#, c-format
|
||||
msgid "Amount to withdraw"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1137
|
||||
#, c-format
|
||||
msgid "Please login!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1169
|
||||
#, c-format
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1184
|
||||
#, c-format
|
||||
msgid "Register to the euFin bank!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1194
|
||||
#, c-format
|
||||
msgid "Registration form"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1232
|
||||
#, c-format
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1272
|
||||
#, c-format
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1273
|
||||
#, c-format
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1274
|
||||
#, c-format
|
||||
msgid "Counterpart"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1275
|
||||
#, c-format
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1343
|
||||
#, c-format
|
||||
msgid "Username or account label '%1$s' not found. Won't login."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1365
|
||||
#, c-format
|
||||
msgid "Wrong credentials given."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1374
|
||||
#, c-format
|
||||
msgid "Account information could not be retrieved."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1394
|
||||
#, c-format
|
||||
msgid "Close wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1412
|
||||
#, c-format
|
||||
msgid "Close Taler withdrawal"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1457
|
||||
#, c-format
|
||||
msgid "Bank account balance:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1469
|
||||
#, c-format
|
||||
msgid "Latest transactions:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1474
|
||||
#, c-format
|
||||
msgid "Transfer money manually"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1543
|
||||
#, c-format
|
||||
msgid "List of public accounts was not found."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1552
|
||||
#, c-format
|
||||
msgid "List of public accounts could not be retrieved."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1584
|
||||
#, c-format
|
||||
msgid "History of public accounts"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1643
|
||||
#, c-format
|
||||
msgid "Page has a problem: logged in but backend state is lost."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1667
|
||||
#, c-format
|
||||
msgid "Welcome to the euFin bank!"
|
||||
msgstr ""
|
||||
|
||||
# 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/>
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Taler Wallet\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-11-23 00:00+0100\n"
|
||||
"PO-Revision-Date: 2022-01-08 09:57+0100\n"
|
||||
"Last-Translator: <translate@taler.net>\n"
|
||||
"Language-Team: German\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
266
packages/demobank-ui/src/i18n/en.po
Normal file
@ -0,0 +1,266 @@
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:55
|
||||
#, c-format
|
||||
msgid "days"
|
||||
msgstr "days"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:65
|
||||
#, c-format
|
||||
msgid "hours"
|
||||
msgstr "hours"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:76
|
||||
#, c-format
|
||||
msgid "minutes"
|
||||
msgstr "minutes"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:87
|
||||
#, c-format
|
||||
msgid "seconds"
|
||||
msgstr "seconds"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:734
|
||||
#, c-format
|
||||
msgid "Clear"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:761
|
||||
#, c-format
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:782
|
||||
#, c-format
|
||||
msgid "Demo Bank"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:837
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:840
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1189
|
||||
#, c-format
|
||||
msgid "Go back"
|
||||
msgstr "Go back"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:845
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:906
|
||||
#, c-format
|
||||
msgid "Wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:846
|
||||
#, c-format
|
||||
msgid "Transfer money to another account of this bank:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:897
|
||||
#, c-format
|
||||
msgid "Want to try the raw payto://-format?"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:907
|
||||
#, c-format
|
||||
msgid "Transfer money via the Payto system:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:916
|
||||
#, c-format
|
||||
msgid "payto address"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:926
|
||||
#, c-format
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:956
|
||||
#, fuzzy, c-format
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Confirm withdrawal"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1026
|
||||
#, c-format
|
||||
msgid "Waiting the bank to create the operaion..."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1044
|
||||
#, c-format
|
||||
msgid "This withdrawal was aborted!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1051
|
||||
#, fuzzy, c-format
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Charge Taler wallet"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1052
|
||||
#, c-format
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1054
|
||||
#, c-format
|
||||
msgid "this link"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1060
|
||||
#, c-format
|
||||
msgid "Abort"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1084
|
||||
#, fuzzy, c-format
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Start withdrawal"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1101
|
||||
#, fuzzy, c-format
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Charge Taler wallet"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1105
|
||||
#, fuzzy, c-format
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Amount to withdraw"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1137
|
||||
#, c-format
|
||||
msgid "Please login!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1169
|
||||
#, c-format
|
||||
msgid "Login"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1184
|
||||
#, c-format
|
||||
msgid "Register to the euFin bank!"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1194
|
||||
#, c-format
|
||||
msgid "Registration form"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1232
|
||||
#, c-format
|
||||
msgid "Register"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1272
|
||||
#, c-format
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1273
|
||||
#, c-format
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1274
|
||||
#, c-format
|
||||
msgid "Counterpart"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1275
|
||||
#, c-format
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1343
|
||||
#, c-format
|
||||
msgid "Username or account label '%1$s' not found. Won't login."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1365
|
||||
#, c-format
|
||||
msgid "Wrong credentials given."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1374
|
||||
#, c-format
|
||||
msgid "Account information could not be retrieved."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1394
|
||||
#, c-format
|
||||
msgid "Close wire transfer"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1412
|
||||
#, fuzzy, c-format
|
||||
msgid "Close Taler withdrawal"
|
||||
msgstr "Close Taler withdrawal"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1457
|
||||
#, c-format
|
||||
msgid "Bank account balance:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1469
|
||||
#, c-format
|
||||
msgid "Latest transactions:"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1474
|
||||
#, c-format
|
||||
msgid "Transfer money manually"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1543
|
||||
#, c-format
|
||||
msgid "List of public accounts was not found."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1552
|
||||
#, c-format
|
||||
msgid "List of public accounts could not be retrieved."
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1584
|
||||
#, c-format
|
||||
msgid "History of public accounts"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1643
|
||||
#, c-format
|
||||
msgid "Page has a problem: logged in but backend state is lost."
|
||||
msgstr "Page has a problem: logged in but backend state is lost."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1667
|
||||
#, fuzzy, c-format
|
||||
msgid "Welcome to the euFin bank!"
|
||||
msgstr "Welcome to euFin bank: Taler+IBAN now possible!"
|
||||
|
||||
# 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/>
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Taler Wallet\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-11-23 00:00+0100\n"
|
||||
"PO-Revision-Date: 2022-01-08 09:57+0100\n"
|
||||
"Last-Translator: <translate@taler.net>\n"
|
||||
"Language-Team: English\n"
|
||||
"Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#~ msgid "Page has a problem:"
|
||||
#~ msgstr "Page has a problem:"
|
||||
|
||||
#~ msgid "Close"
|
||||
#~ msgstr "Close"
|
||||
|
||||
#~ msgid "Sign in"
|
||||
#~ msgstr "Sign in"
|
211
packages/demobank-ui/src/i18n/index.tsx
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Translation helpers for React components and template literals.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Imports
|
||||
*/
|
||||
import { ComponentChild, ComponentChildren, h, Fragment, VNode } from 'preact';
|
||||
|
||||
import { useTranslationContext } from '../context/translation';
|
||||
|
||||
export function useTranslator() {
|
||||
const ctx = useTranslationContext();
|
||||
const jed = ctx.handler;
|
||||
return function str(
|
||||
stringSeq: TemplateStringsArray,
|
||||
...values: any[]
|
||||
): string {
|
||||
const s = toI18nString(stringSeq);
|
||||
if (!s) return s;
|
||||
const tr = jed
|
||||
.translate(s)
|
||||
.ifPlural(1, s)
|
||||
.fetch(...values);
|
||||
return tr;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert template strings to a msgid
|
||||
*/
|
||||
function toI18nString(stringSeq: ReadonlyArray<string>): string {
|
||||
let s = '';
|
||||
for (let i = 0; i < stringSeq.length; i++) {
|
||||
s += stringSeq[i];
|
||||
if (i < stringSeq.length - 1)
|
||||
s += `%${i + 1}$s`;
|
||||
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
interface TranslateSwitchProps {
|
||||
target: number;
|
||||
children: ComponentChildren;
|
||||
}
|
||||
|
||||
function stringifyChildren(children: ComponentChildren): string {
|
||||
let n = 1;
|
||||
const ss = (children instanceof Array ? children : [children]).map((c) => {
|
||||
if (typeof c === 'string')
|
||||
return c;
|
||||
|
||||
return `%${n++}$s`;
|
||||
});
|
||||
const s = ss.join('').replace(/ +/g, ' ').trim();
|
||||
return s;
|
||||
}
|
||||
|
||||
interface TranslateProps {
|
||||
children: ComponentChildren;
|
||||
/**
|
||||
* Component that the translated element should be wrapped in.
|
||||
* Defaults to "div".
|
||||
*/
|
||||
wrap?: any;
|
||||
|
||||
/**
|
||||
* Props to give to the wrapped component.
|
||||
*/
|
||||
wrapProps?: any;
|
||||
}
|
||||
|
||||
function getTranslatedChildren(
|
||||
translation: string,
|
||||
children: ComponentChildren,
|
||||
): ComponentChild[] {
|
||||
const tr = translation.split(/%(\d+)\$s/);
|
||||
const childArray = children instanceof Array ? children : [children];
|
||||
// Merge consecutive string children.
|
||||
const placeholderChildren = Array<ComponentChild>();
|
||||
for (let i = 0; i < childArray.length; i++) {
|
||||
const x = childArray[i];
|
||||
if (x === undefined)
|
||||
continue;
|
||||
else if (typeof x === 'string')
|
||||
continue;
|
||||
else
|
||||
placeholderChildren.push(x);
|
||||
|
||||
}
|
||||
const result = Array<ComponentChild>();
|
||||
for (let i = 0; i < tr.length; i++)
|
||||
if (i % 2 == 0)
|
||||
// Text
|
||||
result.push(tr[i]);
|
||||
else {
|
||||
const childIdx = Number.parseInt(tr[i], 10) - 1;
|
||||
result.push(placeholderChildren[childIdx]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate text node children of this component.
|
||||
* If a child component might produce a text node, it must be wrapped
|
||||
* in a another non-text element.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* <Translate>
|
||||
* Hello. Your score is <span><PlayerScore player={player} /></span>
|
||||
* </Translate>
|
||||
* ```
|
||||
*/
|
||||
export function Translate({ children }: TranslateProps): VNode {
|
||||
const s = stringifyChildren(children);
|
||||
const ctx = useTranslationContext();
|
||||
const translation: string = ctx.handler.ngettext(s, s, 1);
|
||||
const result = getTranslatedChildren(translation, children);
|
||||
return <Fragment>{result}</Fragment>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch translation based on singular or plural based on the target prop.
|
||||
* Should only contain TranslateSingular and TransplatePlural as children.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
* <TranslateSwitch target={n}>
|
||||
* <TranslateSingular>I have {n} apple.</TranslateSingular>
|
||||
* <TranslatePlural>I have {n} apples.</TranslatePlural>
|
||||
* </TranslateSwitch>
|
||||
* ```
|
||||
*/
|
||||
export function TranslateSwitch({ children, target }: TranslateSwitchProps) {
|
||||
let singular: VNode<TranslationPluralProps> | undefined;
|
||||
let plural: VNode<TranslationPluralProps> | undefined;
|
||||
// const children = this.props.children;
|
||||
if (children)
|
||||
(children instanceof Array ? children : [children]).forEach(
|
||||
(child: any) => {
|
||||
if (child.type === TranslatePlural)
|
||||
plural = child;
|
||||
|
||||
if (child.type === TranslateSingular)
|
||||
singular = child;
|
||||
|
||||
},
|
||||
);
|
||||
|
||||
if (!singular || !plural) {
|
||||
console.error('translation not found');
|
||||
return h('span', {}, ['translation not found']);
|
||||
}
|
||||
singular.props.target = target;
|
||||
plural.props.target = target;
|
||||
// We're looking up the translation based on the
|
||||
// singular, even if we must use the plural form.
|
||||
return singular;
|
||||
}
|
||||
|
||||
interface TranslationPluralProps {
|
||||
children: ComponentChildren;
|
||||
target: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* See [[TranslateSwitch]].
|
||||
*/
|
||||
export function TranslatePlural({
|
||||
children,
|
||||
target,
|
||||
}: TranslationPluralProps): VNode {
|
||||
const s = stringifyChildren(children);
|
||||
const ctx = useTranslationContext();
|
||||
const translation = ctx.handler.ngettext(s, s, 1);
|
||||
const result = getTranslatedChildren(translation, children);
|
||||
return <Fragment>{result}</Fragment>;
|
||||
}
|
||||
|
||||
/**
|
||||
* See [[TranslateSwitch]].
|
||||
*/
|
||||
export function TranslateSingular({
|
||||
children,
|
||||
target,
|
||||
}: TranslationPluralProps): VNode {
|
||||
const s = stringifyChildren(children);
|
||||
const ctx = useTranslationContext();
|
||||
const translation = ctx.handler.ngettext(s, s, target);
|
||||
const result = getTranslatedChildren(translation, children);
|
||||
return <Fragment>{result}</Fragment>;
|
||||
}
|
258
packages/demobank-ui/src/i18n/it.po
Normal file
@ -0,0 +1,258 @@
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:55
|
||||
#, c-format
|
||||
msgid "days"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:65
|
||||
#, c-format
|
||||
msgid "hours"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:76
|
||||
#, c-format
|
||||
msgid "minutes"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/components/picker/DurationPicker.tsx:87
|
||||
#, c-format
|
||||
msgid "seconds"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:734
|
||||
#, c-format
|
||||
msgid "Clear"
|
||||
msgstr "Cancella"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:761
|
||||
#, c-format
|
||||
msgid "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:782
|
||||
#, c-format
|
||||
msgid "Demo Bank"
|
||||
msgstr "Banca 'demo'"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:837
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:840
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1189
|
||||
#, c-format
|
||||
msgid "Go back"
|
||||
msgstr "Indietro"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:845
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:906
|
||||
#, c-format
|
||||
msgid "Wire transfer"
|
||||
msgstr "Bonifico"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:846
|
||||
#, c-format
|
||||
msgid "Transfer money to another account of this bank:"
|
||||
msgstr "Trasferisci fondi a un altro conto di questa banca:"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:897
|
||||
#, c-format
|
||||
msgid "Want to try the raw payto://-format?"
|
||||
msgstr "Prova il trasferimento tramite il formato Payto!"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:907
|
||||
#, c-format
|
||||
msgid "Transfer money via the Payto system:"
|
||||
msgstr "Effettua un bonifico tramite il sistema Payto:"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:916
|
||||
#, c-format
|
||||
msgid "payto address"
|
||||
msgstr "indirizzo Payto"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:926
|
||||
#, c-format
|
||||
msgid "Confirm"
|
||||
msgstr "Conferma"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:956
|
||||
#, c-format
|
||||
msgid "Confirm Withdrawal"
|
||||
msgstr "Conferma il ritiro"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1026
|
||||
#, c-format
|
||||
msgid "Waiting the bank to create the operaion..."
|
||||
msgstr "La banca sta creando l'operazione..."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1044
|
||||
#, c-format
|
||||
msgid "This withdrawal was aborted!"
|
||||
msgstr "Questo ritiro è stato annullato!"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1051
|
||||
#, c-format
|
||||
msgid "Withdraw to a Taler Wallet"
|
||||
msgstr "Ritira contante nel portafoglio Taler"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1052
|
||||
#, c-format
|
||||
msgid "You can use this QR code to withdraw to your mobile wallet:"
|
||||
msgstr "Usa questo codice QR per ritirare contante nel tuo wallet:"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1054
|
||||
#, c-format
|
||||
msgid "this link"
|
||||
msgstr "questo link"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1060
|
||||
#, c-format
|
||||
msgid "Abort"
|
||||
msgstr "Annulla"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1084
|
||||
#, c-format
|
||||
msgid "Start withdrawal"
|
||||
msgstr "Ritira contante"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1101
|
||||
#, c-format
|
||||
msgid "Withdraw Money into a Taler wallet"
|
||||
msgstr "Ritira contante nel portafoglio Taler"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1105
|
||||
#, c-format
|
||||
msgid "Amount to withdraw"
|
||||
msgstr "Somma da ritirare"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1137
|
||||
#, c-format
|
||||
msgid "Please login!"
|
||||
msgstr "Accedi!"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1169
|
||||
#, c-format
|
||||
msgid "Login"
|
||||
msgstr "Accedi"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1184
|
||||
#, c-format
|
||||
msgid "Register to the euFin bank!"
|
||||
msgstr "Apri un conto in banca euFin!"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1194
|
||||
#, c-format
|
||||
msgid "Registration form"
|
||||
msgstr "Registrazione"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1232
|
||||
#, c-format
|
||||
msgid "Register"
|
||||
msgstr "Registrati"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1272
|
||||
#, c-format
|
||||
msgid "Date"
|
||||
msgstr ""
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1273
|
||||
#, c-format
|
||||
msgid "Amount"
|
||||
msgstr "Somma"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1274
|
||||
#, c-format
|
||||
msgid "Counterpart"
|
||||
msgstr "Controparte"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1275
|
||||
#, c-format
|
||||
msgid "Subject"
|
||||
msgstr "Causale"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1343
|
||||
#, c-format
|
||||
msgid "Username or account label '%1$s' not found. Won't login."
|
||||
msgstr "L'utente '%1$s' non esiste. Login impossibile"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1365
|
||||
#, c-format
|
||||
msgid "Wrong credentials given."
|
||||
msgstr "Credenziali invalide."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1374
|
||||
#, c-format
|
||||
msgid "Account information could not be retrieved."
|
||||
msgstr "Impossibile ricevere le informazioni relative al conto."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1394
|
||||
#, c-format
|
||||
msgid "Close wire transfer"
|
||||
msgstr "Chiudi il bonifico"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1412
|
||||
#, c-format
|
||||
msgid "Close Taler withdrawal"
|
||||
msgstr "Chiudi il ritiro Taler"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1457
|
||||
#, c-format
|
||||
msgid "Bank account balance:"
|
||||
msgstr "Bilancio:"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1469
|
||||
#, c-format
|
||||
msgid "Latest transactions:"
|
||||
msgstr "Ultime transazioni:"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1474
|
||||
#, c-format
|
||||
msgid "Transfer money manually"
|
||||
msgstr "Effettua un bonifico"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1543
|
||||
#, c-format
|
||||
msgid "List of public accounts was not found."
|
||||
msgstr "Lista conti pubblici non trovata."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1552
|
||||
#, c-format
|
||||
msgid "List of public accounts could not be retrieved."
|
||||
msgstr "Lista conti pubblici non pervenuta."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1584
|
||||
#, c-format
|
||||
msgid "History of public accounts"
|
||||
msgstr "Storico dei conti pubblici"
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1643
|
||||
#, c-format
|
||||
msgid "Page has a problem: logged in but backend state is lost."
|
||||
msgstr ""
|
||||
"Stato inconsistente: accesso utente effettuato ma stato con server perso."
|
||||
|
||||
#: /home/job/backoffice/packages/bank/src/pages/home/index.tsx:1667
|
||||
#, fuzzy, c-format
|
||||
msgid "Welcome to the euFin bank!"
|
||||
msgstr "Benvenuti in banca euFin!"
|
||||
|
||||
# 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/>
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Taler Wallet\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-11-23 00:00+0100\n"
|
||||
"PO-Revision-Date: 2022-01-08 10:05+0100\n"
|
||||
"Last-Translator: <translate@taler.net>\n"
|
||||
"Language-Team: Italian\n"
|
||||
"Language: it\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
27
packages/demobank-ui/src/i18n/poheader
Normal file
@ -0,0 +1,27 @@
|
||||
# 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/>
|
||||
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Taler Wallet\n"
|
||||
"Report-Msgid-Bugs-To: taler@gnu.org\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
19
packages/demobank-ui/src/i18n/strings-prelude
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
/*eslint quote-props: ["error", "consistent"]*/
|
||||
export const strings: {[s: string]: any} = {};
|
||||
|
472
packages/demobank-ui/src/i18n/strings.ts
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
/*eslint quote-props: ["error", "consistent"]*/
|
||||
export const strings: {[s: string]: any} = {};
|
||||
|
||||
strings['de'] = {
|
||||
'domain': 'messages',
|
||||
'locale_data': {
|
||||
'messages': {
|
||||
'days': [
|
||||
''
|
||||
],
|
||||
'hours': [
|
||||
''
|
||||
],
|
||||
'minutes': [
|
||||
''
|
||||
],
|
||||
'seconds': [
|
||||
''
|
||||
],
|
||||
'Clear': [
|
||||
''
|
||||
],
|
||||
'Logout': [
|
||||
''
|
||||
],
|
||||
'Demo Bank': [
|
||||
''
|
||||
],
|
||||
'Go back': [
|
||||
''
|
||||
],
|
||||
'Wire transfer': [
|
||||
''
|
||||
],
|
||||
'Transfer money to another account of this bank:': [
|
||||
''
|
||||
],
|
||||
'Want to try the raw payto://-format?': [
|
||||
''
|
||||
],
|
||||
'Transfer money via the Payto system:': [
|
||||
''
|
||||
],
|
||||
'payto address': [
|
||||
''
|
||||
],
|
||||
'Confirm': [
|
||||
''
|
||||
],
|
||||
'Confirm Withdrawal': [
|
||||
''
|
||||
],
|
||||
'Waiting the bank to create the operaion...': [
|
||||
''
|
||||
],
|
||||
'This withdrawal was aborted!': [
|
||||
''
|
||||
],
|
||||
'Withdraw to a Taler Wallet': [
|
||||
''
|
||||
],
|
||||
'You can use this QR code to withdraw to your mobile wallet:': [
|
||||
''
|
||||
],
|
||||
'this link': [
|
||||
''
|
||||
],
|
||||
'Abort': [
|
||||
''
|
||||
],
|
||||
'Start withdrawal': [
|
||||
''
|
||||
],
|
||||
'Withdraw Money into a Taler wallet': [
|
||||
''
|
||||
],
|
||||
'Amount to withdraw': [
|
||||
''
|
||||
],
|
||||
'Please login!': [
|
||||
''
|
||||
],
|
||||
'Login': [
|
||||
''
|
||||
],
|
||||
'Register to the euFin bank!': [
|
||||
''
|
||||
],
|
||||
'Registration form': [
|
||||
''
|
||||
],
|
||||
'Register': [
|
||||
''
|
||||
],
|
||||
'Date': [
|
||||
''
|
||||
],
|
||||
'Amount': [
|
||||
''
|
||||
],
|
||||
'Counterpart': [
|
||||
''
|
||||
],
|
||||
'Subject': [
|
||||
''
|
||||
],
|
||||
'Username or account label \'%1$s\' not found. Won\'t login.': [
|
||||
''
|
||||
],
|
||||
'Wrong credentials given.': [
|
||||
''
|
||||
],
|
||||
'Account information could not be retrieved.': [
|
||||
''
|
||||
],
|
||||
'Close wire transfer': [
|
||||
''
|
||||
],
|
||||
'Close Taler withdrawal': [
|
||||
''
|
||||
],
|
||||
'Bank account balance:': [
|
||||
''
|
||||
],
|
||||
'Latest transactions:': [
|
||||
''
|
||||
],
|
||||
'Transfer money manually': [
|
||||
''
|
||||
],
|
||||
'List of public accounts was not found.': [
|
||||
''
|
||||
],
|
||||
'List of public accounts could not be retrieved.': [
|
||||
''
|
||||
],
|
||||
'History of public accounts': [
|
||||
''
|
||||
],
|
||||
'Page has a problem: logged in but backend state is lost.': [
|
||||
''
|
||||
],
|
||||
'Welcome to the euFin bank!': [
|
||||
''
|
||||
],
|
||||
'': {
|
||||
'domain': 'messages',
|
||||
'plural_forms': 'nplurals=2; plural=(n != 1);',
|
||||
'lang': 'de'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
strings['en'] = {
|
||||
'domain': 'messages',
|
||||
'locale_data': {
|
||||
'messages': {
|
||||
'days': [
|
||||
'days'
|
||||
],
|
||||
'hours': [
|
||||
'hours'
|
||||
],
|
||||
'minutes': [
|
||||
'minutes'
|
||||
],
|
||||
'seconds': [
|
||||
'seconds'
|
||||
],
|
||||
'Clear': [
|
||||
''
|
||||
],
|
||||
'Logout': [
|
||||
''
|
||||
],
|
||||
'Demo Bank': [
|
||||
''
|
||||
],
|
||||
'Go back': [
|
||||
'Go back'
|
||||
],
|
||||
'Wire transfer': [
|
||||
''
|
||||
],
|
||||
'Transfer money to another account of this bank:': [
|
||||
''
|
||||
],
|
||||
'Want to try the raw payto://-format?': [
|
||||
''
|
||||
],
|
||||
'Transfer money via the Payto system:': [
|
||||
''
|
||||
],
|
||||
'payto address': [
|
||||
''
|
||||
],
|
||||
'Confirm': [
|
||||
''
|
||||
],
|
||||
'Confirm Withdrawal': [
|
||||
'Confirm withdrawal'
|
||||
],
|
||||
'Waiting the bank to create the operaion...': [
|
||||
''
|
||||
],
|
||||
'This withdrawal was aborted!': [
|
||||
''
|
||||
],
|
||||
'Withdraw to a Taler Wallet': [
|
||||
'Charge Taler wallet'
|
||||
],
|
||||
'You can use this QR code to withdraw to your mobile wallet:': [
|
||||
''
|
||||
],
|
||||
'this link': [
|
||||
''
|
||||
],
|
||||
'Abort': [
|
||||
''
|
||||
],
|
||||
'Start withdrawal': [
|
||||
'Start withdrawal'
|
||||
],
|
||||
'Withdraw Money into a Taler wallet': [
|
||||
'Charge Taler wallet'
|
||||
],
|
||||
'Amount to withdraw': [
|
||||
'Amount to withdraw'
|
||||
],
|
||||
'Please login!': [
|
||||
''
|
||||
],
|
||||
'Login': [
|
||||
''
|
||||
],
|
||||
'Register to the euFin bank!': [
|
||||
''
|
||||
],
|
||||
'Registration form': [
|
||||
''
|
||||
],
|
||||
'Register': [
|
||||
''
|
||||
],
|
||||
'Date': [
|
||||
''
|
||||
],
|
||||
'Amount': [
|
||||
''
|
||||
],
|
||||
'Counterpart': [
|
||||
''
|
||||
],
|
||||
'Subject': [
|
||||
''
|
||||
],
|
||||
'Username or account label \'%1$s\' not found. Won\'t login.': [
|
||||
''
|
||||
],
|
||||
'Wrong credentials given.': [
|
||||
''
|
||||
],
|
||||
'Account information could not be retrieved.': [
|
||||
''
|
||||
],
|
||||
'Close wire transfer': [
|
||||
''
|
||||
],
|
||||
'Close Taler withdrawal': [
|
||||
'Close Taler withdrawal'
|
||||
],
|
||||
'Bank account balance:': [
|
||||
''
|
||||
],
|
||||
'Latest transactions:': [
|
||||
''
|
||||
],
|
||||
'Transfer money manually': [
|
||||
''
|
||||
],
|
||||
'List of public accounts was not found.': [
|
||||
''
|
||||
],
|
||||
'List of public accounts could not be retrieved.': [
|
||||
''
|
||||
],
|
||||
'History of public accounts': [
|
||||
''
|
||||
],
|
||||
'Page has a problem: logged in but backend state is lost.': [
|
||||
'Page has a problem: logged in but backend state is lost.'
|
||||
],
|
||||
'Welcome to the euFin bank!': [
|
||||
'Welcome to euFin bank: Taler+IBAN now possible!'
|
||||
],
|
||||
'': {
|
||||
'domain': 'messages',
|
||||
'plural_forms': 'nplurals=2; plural=(n != 1);',
|
||||
'lang': 'en'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
strings['it'] = {
|
||||
'domain': 'messages',
|
||||
'locale_data': {
|
||||
'messages': {
|
||||
'days': [
|
||||
''
|
||||
],
|
||||
'hours': [
|
||||
''
|
||||
],
|
||||
'minutes': [
|
||||
''
|
||||
],
|
||||
'seconds': [
|
||||
''
|
||||
],
|
||||
'Clear': [
|
||||
'Cancella'
|
||||
],
|
||||
'Logout': [
|
||||
''
|
||||
],
|
||||
'Demo Bank': [
|
||||
'Banca \'demo\''
|
||||
],
|
||||
'Go back': [
|
||||
'Indietro'
|
||||
],
|
||||
'Wire transfer': [
|
||||
'Bonifico'
|
||||
],
|
||||
'Transfer money to another account of this bank:': [
|
||||
'Trasferisci fondi a un altro conto di questa banca:'
|
||||
],
|
||||
'Want to try the raw payto://-format?': [
|
||||
'Prova il trasferimento tramite il formato Payto!'
|
||||
],
|
||||
'Transfer money via the Payto system:': [
|
||||
'Effettua un bonifico tramite il sistema Payto:'
|
||||
],
|
||||
'payto address': [
|
||||
'indirizzo Payto'
|
||||
],
|
||||
'Confirm': [
|
||||
'Conferma'
|
||||
],
|
||||
'Confirm Withdrawal': [
|
||||
'Conferma il ritiro'
|
||||
],
|
||||
'Waiting the bank to create the operaion...': [
|
||||
'La banca sta creando l\'operazione...'
|
||||
],
|
||||
'This withdrawal was aborted!': [
|
||||
'Questo ritiro è stato annullato!'
|
||||
],
|
||||
'Withdraw to a Taler Wallet': [
|
||||
'Ritira contante nel portafoglio Taler'
|
||||
],
|
||||
'You can use this QR code to withdraw to your mobile wallet:': [
|
||||
'Usa questo codice QR per ritirare contante nel tuo wallet:'
|
||||
],
|
||||
'this link': [
|
||||
'questo link'
|
||||
],
|
||||
'Abort': [
|
||||
'Annulla'
|
||||
],
|
||||
'Start withdrawal': [
|
||||
'Ritira contante'
|
||||
],
|
||||
'Withdraw Money into a Taler wallet': [
|
||||
'Ritira contante nel portafoglio Taler'
|
||||
],
|
||||
'Amount to withdraw': [
|
||||
'Somma da ritirare'
|
||||
],
|
||||
'Please login!': [
|
||||
'Accedi!'
|
||||
],
|
||||
'Login': [
|
||||
'Accedi'
|
||||
],
|
||||
'Register to the euFin bank!': [
|
||||
'Apri un conto in banca euFin!'
|
||||
],
|
||||
'Registration form': [
|
||||
'Registrazione'
|
||||
],
|
||||
'Register': [
|
||||
'Registrati'
|
||||
],
|
||||
'Date': [
|
||||
''
|
||||
],
|
||||
'Amount': [
|
||||
'Somma'
|
||||
],
|
||||
'Counterpart': [
|
||||
'Controparte'
|
||||
],
|
||||
'Subject': [
|
||||
'Causale'
|
||||
],
|
||||
'Username or account label \'%1$s\' not found. Won\'t login.': [
|
||||
'L\'utente \'%1$s\' non esiste. Login impossibile'
|
||||
],
|
||||
'Wrong credentials given.': [
|
||||
'Credenziali invalide.'
|
||||
],
|
||||
'Account information could not be retrieved.': [
|
||||
'Impossibile ricevere le informazioni relative al conto.'
|
||||
],
|
||||
'Close wire transfer': [
|
||||
'Chiudi il bonifico'
|
||||
],
|
||||
'Close Taler withdrawal': [
|
||||
'Chiudi il ritiro Taler'
|
||||
],
|
||||
'Bank account balance:': [
|
||||
'Bilancio:'
|
||||
],
|
||||
'Latest transactions:': [
|
||||
'Ultime transazioni:'
|
||||
],
|
||||
'Transfer money manually': [
|
||||
'Effettua un bonifico'
|
||||
],
|
||||
'List of public accounts was not found.': [
|
||||
'Lista conti pubblici non trovata.'
|
||||
],
|
||||
'List of public accounts could not be retrieved.': [
|
||||
'Lista conti pubblici non pervenuta.'
|
||||
],
|
||||
'History of public accounts': [
|
||||
'Storico dei conti pubblici'
|
||||
],
|
||||
'Page has a problem: logged in but backend state is lost.': [
|
||||
'Stato inconsistente: accesso utente effettuato ma stato con server perso.'
|
||||
],
|
||||
'Welcome to the euFin bank!': [
|
||||
'Benvenuti in banca euFin!'
|
||||
],
|
||||
'': {
|
||||
'domain': 'messages',
|
||||
'plural_forms': 'nplurals=2; plural=(n != 1);',
|
||||
'lang': 'it'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
3
packages/demobank-ui/src/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import App from './components/app';
|
||||
|
||||
export default App;
|
21
packages/demobank-ui/src/manifest.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "taler-bank",
|
||||
"short_name": "taler-bank",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "portrait",
|
||||
"background_color": "#fff",
|
||||
"theme_color": "#673ab8",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/assets/icons/android-chrome-192x192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "/assets/icons/android-chrome-512x512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
]
|
||||
}
|
2018
packages/demobank-ui/src/pages/home/index.tsx
Normal file
16
packages/demobank-ui/src/pages/notfound/index.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { FunctionalComponent, h } from 'preact';
|
||||
import { Link } from 'preact-router/match';
|
||||
|
||||
const Notfound: FunctionalComponent = () => {
|
||||
return (
|
||||
<div>
|
||||
<h1>Error 404</h1>
|
||||
<p>That page doesn't exist.</p>
|
||||
<Link href="/">
|
||||
<h4>Back to Home</h4>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Notfound;
|
0
packages/demobank-ui/src/pages/notfound/style.css
Normal file
38
packages/demobank-ui/src/pages/profile/index.stories.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
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 } from 'preact';
|
||||
import Profile from './index';
|
||||
|
||||
|
||||
export default {
|
||||
title: 'Profile/View',
|
||||
component: Profile,
|
||||
argTypes: {
|
||||
onSelect: { action: 'onSelect' },
|
||||
},
|
||||
};
|
||||
|
||||
export const Empty = (a: any) => <Profile {...a} />;
|
||||
Empty.args = {
|
||||
instances: []
|
||||
}
|
||||
|
42
packages/demobank-ui/src/pages/profile/index.tsx
Normal file
@ -0,0 +1,42 @@
|
||||
import { FunctionalComponent, h } from 'preact';
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
|
||||
interface Props {
|
||||
user: string;
|
||||
}
|
||||
|
||||
const Profile: FunctionalComponent<Props> = (props: Props) => {
|
||||
const { user } = props;
|
||||
const [time, setTime] = useState<number>(Date.now());
|
||||
const [count, setCount] = useState<number>(0);
|
||||
|
||||
// gets called when this route is navigated to
|
||||
useEffect(() => {
|
||||
const timer = window.setInterval(() => setTime(Date.now()), 1000);
|
||||
|
||||
// gets called just before navigating away from the route
|
||||
return (): void => {
|
||||
clearInterval(timer);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// update the current time
|
||||
const increment = (): void => {
|
||||
setCount(count + 1);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Profile: {user}</h1>
|
||||
<p>This is the user profile for a user named {user}.</p>
|
||||
|
||||
<div>Current time: {new Date(time).toLocaleString()}</div>
|
||||
|
||||
<p>
|
||||
<button onClick={increment}>Click Me</button> Clicked {count} times.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Profile;
|
0
packages/demobank-ui/src/pages/profile/style.css
Normal file
70
packages/demobank-ui/src/scss/DurationPicker.scss
Normal file
@ -0,0 +1,70 @@
|
||||
.rdp-picker {
|
||||
display: flex;
|
||||
height: 175px;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.rdp-picker {
|
||||
width: 250px;
|
||||
}
|
||||
}
|
||||
|
||||
.rdp-masked-div {
|
||||
overflow: hidden;
|
||||
height: 175px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.rdp-column-container {
|
||||
flex-grow: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.rdp-column {
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.rdp-reticule {
|
||||
border: 0;
|
||||
border-top: 2px solid rgba(109, 202, 236, 1);
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 80%;
|
||||
margin: 0;
|
||||
z-index: 100;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.rdp-text-overlay {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 35px;
|
||||
font-size: 20px;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.rdp-cell div {
|
||||
font-size: 17px;
|
||||
color: gray;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.rdp-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 35px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.rdp-center {
|
||||
font-size: 25px;
|
||||
}
|
128
packages/demobank-ui/src/scss/_aside.scss
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
html {
|
||||
&.has-aside-left {
|
||||
&.has-aside-expanded {
|
||||
nav.navbar,
|
||||
body {
|
||||
padding-left: $aside-width;
|
||||
}
|
||||
}
|
||||
aside.is-placed-left {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aside.aside.is-expanded {
|
||||
width: $aside-width;
|
||||
|
||||
.menu-list {
|
||||
@include icon-with-update-mark($aside-icon-width);
|
||||
|
||||
span.menu-item-label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
li.is-active {
|
||||
ul {
|
||||
display: block;
|
||||
}
|
||||
background-color: $body-background-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aside.aside {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 40;
|
||||
height: 100vh;
|
||||
padding: 0;
|
||||
box-shadow: $aside-box-shadow;
|
||||
background: $aside-background-color;
|
||||
|
||||
.aside-tools {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
background-color: $aside-tools-background-color;
|
||||
color: $aside-tools-color;
|
||||
line-height: $navbar-height;
|
||||
height: $navbar-height;
|
||||
padding-left: $default-padding * 0.5;
|
||||
flex: 1;
|
||||
|
||||
.icon {
|
||||
margin-right: $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
li {
|
||||
a {
|
||||
&.has-dropdown-icon {
|
||||
position: relative;
|
||||
padding-right: $aside-icon-width;
|
||||
|
||||
.dropdown-icon {
|
||||
position: absolute;
|
||||
top: $size-base * 0.5;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ul {
|
||||
display: none;
|
||||
border-left: 0;
|
||||
background-color: darken($base-color, 2.5%);
|
||||
padding-left: 0;
|
||||
margin: 0 0 $default-padding * 0.5;
|
||||
|
||||
li {
|
||||
a {
|
||||
padding: $default-padding * 0.5 0 $default-padding * 0.5
|
||||
$default-padding * 0.5;
|
||||
font-size: $aside-submenu-font-size;
|
||||
|
||||
&.has-icon {
|
||||
padding-left: 0;
|
||||
}
|
||||
&.is-active {
|
||||
&:not(:hover) {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-label {
|
||||
padding: 0 $default-padding * 0.5;
|
||||
margin-top: $default-padding * 0.5;
|
||||
margin-bottom: $default-padding * 0.5;
|
||||
}
|
||||
}
|
69
packages/demobank-ui/src/scss/_card.scss
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
.card:not(:last-child) {
|
||||
margin-bottom: $default-padding;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: $radius-large;
|
||||
border: $card-border;
|
||||
|
||||
&.has-table {
|
||||
.card-content {
|
||||
padding: 0;
|
||||
}
|
||||
.b-table {
|
||||
border-radius: $radius-large;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-card-widget {
|
||||
.card-content {
|
||||
padding: $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
border-bottom: 1px solid $base-color-light;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
hr {
|
||||
margin-left: $card-content-padding * -1;
|
||||
margin-right: $card-content-padding * -1;
|
||||
}
|
||||
}
|
||||
|
||||
.is-widget-icon {
|
||||
.icon {
|
||||
width: 5rem;
|
||||
height: 5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.is-widget-label {
|
||||
.subtitle {
|
||||
color: $grey;
|
||||
}
|
||||
}
|
||||
}
|
263
packages/demobank-ui/src/scss/_custom-calendar.scss
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
:root {
|
||||
--primary-color: #3298dc;
|
||||
|
||||
--primary-text-color-dark: rgba(0, 0, 0, 0.87);
|
||||
--secondary-text-color-dark: rgba(0, 0, 0, 0.57);
|
||||
--disabled-text-color-dark: rgba(0, 0, 0, 0.13);
|
||||
|
||||
--primary-text-color-light: rgba(255, 255, 255, 0.87);
|
||||
--secondary-text-color-light: rgba(255, 255, 255, 0.57);
|
||||
--disabled-text-color-light: rgba(255, 255, 255, 0.13);
|
||||
|
||||
--font-stack: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
|
||||
--primary-card-color: #fff;
|
||||
--primary-background-color: #f2f2f2;
|
||||
|
||||
--box-shadow-lvl-1: 0 1px 3px rgba(0, 0, 0, 0.12),
|
||||
0 1px 2px rgba(0, 0, 0, 0.24);
|
||||
--box-shadow-lvl-2: 0 3px 6px rgba(0, 0, 0, 0.16),
|
||||
0 3px 6px rgba(0, 0, 0, 0.23);
|
||||
--box-shadow-lvl-3: 0 10px 20px rgba(0, 0, 0, 0.19),
|
||||
0 6px 6px rgba(0, 0, 0, 0.23);
|
||||
--box-shadow-lvl-4: 0 14px 28px rgba(0, 0, 0, 0.25),
|
||||
0 10px 10px rgba(0, 0, 0, 0.22);
|
||||
}
|
||||
|
||||
.home .datePicker div {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.datePicker {
|
||||
text-align: left;
|
||||
background: var(--primary-card-color);
|
||||
border-radius: 3px;
|
||||
z-index: 200;
|
||||
position: fixed;
|
||||
height: auto;
|
||||
max-height: 90vh;
|
||||
width: 90vw;
|
||||
max-width: 448px;
|
||||
transform-origin: top left;
|
||||
transition: transform 0.22s ease-in-out, opacity 0.22s ease-in-out;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
opacity: 0;
|
||||
transform: scale(0) translate(-50%, -50%);
|
||||
user-select: none;
|
||||
|
||||
&.datePicker--opened {
|
||||
opacity: 1;
|
||||
transform: scale(1) translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.datePicker--titles {
|
||||
border-top-left-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
padding: 24px;
|
||||
height: 100px;
|
||||
background: var(--primary-color);
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
cursor: pointer;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: rgba(255, 255, 255, 0.57);
|
||||
font-size: 18px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
nav {
|
||||
padding: 20px;
|
||||
height: 56px;
|
||||
|
||||
h4 {
|
||||
width: calc(100% - 60px);
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
top: -9px;
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
|
||||
i {
|
||||
cursor: pointer;
|
||||
color: var(--secondary-text-color);
|
||||
font-size: 26px;
|
||||
user-select: none;
|
||||
border-radius: 50%;
|
||||
|
||||
&:hover {
|
||||
background: var(--disabled-text-color-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.datePicker--scroll {
|
||||
overflow-y: auto;
|
||||
max-height: calc(90vh - 56px - 100px);
|
||||
}
|
||||
|
||||
.datePicker--calendar {
|
||||
padding: 0 20px;
|
||||
|
||||
.datePicker--dayNames {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
text-align: center;
|
||||
|
||||
// there's probably a better way to do this, but wanted to try out CSS grid
|
||||
grid-template-columns: calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(
|
||||
100% / 7
|
||||
) calc(100% / 7) calc(100% / 7) calc(100% / 7);
|
||||
|
||||
span {
|
||||
color: var(--secondary-text-color-dark);
|
||||
font-size: 14px;
|
||||
line-height: 42px;
|
||||
display: inline-grid;
|
||||
}
|
||||
}
|
||||
|
||||
.datePicker--days {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
text-align: center;
|
||||
grid-template-columns: calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(
|
||||
100% / 7
|
||||
) calc(100% / 7) calc(100% / 7) calc(100% / 7);
|
||||
|
||||
span {
|
||||
color: var(--primary-text-color-dark);
|
||||
line-height: 42px;
|
||||
font-size: 14px;
|
||||
display: inline-grid;
|
||||
transition: color 0.22s;
|
||||
height: 42px;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
border-radius: 50%;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
height: 42px;
|
||||
width: 42px;
|
||||
left: calc(50% - 21px);
|
||||
background: var(--primary-color);
|
||||
border-radius: 50%;
|
||||
transition: transform 0.22s, opacity 0.22s;
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&[disabled="true"] {
|
||||
cursor: unset;
|
||||
}
|
||||
|
||||
&.datePicker--today {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
&.datePicker--selected {
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
|
||||
&:before {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.datePicker--selectYear {
|
||||
padding: 0 20px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
max-height: 362px;
|
||||
|
||||
span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
margin: 20px auto;
|
||||
cursor: pointer;
|
||||
|
||||
&.selected {
|
||||
font-size: 42px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.datePicker--actions {
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
text-align: right;
|
||||
|
||||
button {
|
||||
margin-bottom: 0;
|
||||
font-size: 15px;
|
||||
cursor: pointer;
|
||||
color: var(--primary-text-color);
|
||||
border: none;
|
||||
margin-left: 8px;
|
||||
min-width: 64px;
|
||||
line-height: 36px;
|
||||
background-color: transparent;
|
||||
appearance: none;
|
||||
padding: 0 16px;
|
||||
border-radius: 3px;
|
||||
transition: background-color 0.13s;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
outline: none;
|
||||
background-color: var(--disabled-text-color-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.datePicker--background {
|
||||
z-index: 199;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.52);
|
||||
animation: fadeIn 0.22s forwards;
|
||||
}
|
35
packages/demobank-ui/src/scss/_footer.scss
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
footer.footer {
|
||||
.logo {
|
||||
img {
|
||||
width: auto;
|
||||
height: $footer-logo-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
.footer-copyright {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
71
packages/demobank-ui/src/scss/_form.scss
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
.field {
|
||||
&.has-check {
|
||||
.field-body {
|
||||
margin-top: $default-padding * 0.125;
|
||||
}
|
||||
}
|
||||
.control {
|
||||
.mdi-24px.mdi-set,
|
||||
.mdi-24px.mdi:before {
|
||||
font-size: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
.upload {
|
||||
.upload-draggable {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.input,
|
||||
.textarea,
|
||||
select {
|
||||
box-shadow: none;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.switch input[type="checkbox"] + .check:before {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.switch,
|
||||
.b-checkbox.checkbox {
|
||||
input[type="checkbox"] {
|
||||
&:focus + .check,
|
||||
&:focus:checked + .check {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.b-checkbox.checkbox input[type="checkbox"],
|
||||
.b-radio.radio input[type="radio"] {
|
||||
& + .check {
|
||||
border: $checkbox-border;
|
||||
}
|
||||
}
|
55
packages/demobank-ui/src/scss/_hero-bar.scss
Normal file
@ -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 <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sebastian Javier Marchano (sebasjm)
|
||||
*/
|
||||
|
||||
section.hero.is-hero-bar {
|
||||
background-color: $hero-bar-background;
|
||||
border-bottom: $light-border;
|
||||
|
||||
.hero-body {
|
||||
padding: $default-padding;
|
||||
|
||||
.level-item {
|
||||
&.is-hero-avatar-item {
|
||||
margin-right: $default-padding;
|
||||
}
|
||||
|
||||
> div > .level {
|
||||
margin-bottom: $default-padding * 0.5;
|
||||
}
|
||||
|
||||
.subtitle + p {
|
||||
margin-top: $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
&.is-hero-button {
|
||||
background-color: rgba($white, 0.5);
|
||||
font-weight: 300;
|
||||
@include transition(background-color);
|
||||
|
||||
&:hover {
|
||||
background-color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
51
packages/demobank-ui/src/scss/_loading.scss
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
.lds-ring {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
.lds-ring div {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin: 8px;
|
||||
border: 8px solid black;
|
||||
border-radius: 50%;
|
||||
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
|
||||
border-color: black transparent transparent transparent;
|
||||
}
|
||||
.lds-ring div:nth-child(1) {
|
||||
animation-delay: -0.45s;
|
||||
}
|
||||
.lds-ring div:nth-child(2) {
|
||||
animation-delay: -0.3s;
|
||||
}
|
||||
.lds-ring div:nth-child(3) {
|
||||
animation-delay: -0.15s;
|
||||
}
|
||||
@keyframes lds-ring {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
24
packages/demobank-ui/src/scss/_main-section.scss
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
section.section.is-main-section {
|
||||
padding-top: $default-padding;
|
||||
}
|
50
packages/demobank-ui/src/scss/_misc.scss
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
.is-user-avatar {
|
||||
&.has-max-width {
|
||||
max-width: $size-base * 7;
|
||||
}
|
||||
|
||||
&.is-aligned-center {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
img {
|
||||
margin: 0 auto;
|
||||
border-radius: $radius-rounded;
|
||||
}
|
||||
}
|
||||
|
||||
.icon.has-update-mark {
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
width: $icon-update-mark-size;
|
||||
height: $icon-update-mark-size;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
background-color: $icon-update-mark-color;
|
||||
border-radius: $radius-rounded;
|
||||
}
|
||||
}
|
34
packages/demobank-ui/src/scss/_mixins.scss
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
@mixin transition($t) {
|
||||
transition: $t 250ms ease-in-out 50ms;
|
||||
}
|
||||
|
||||
@mixin icon-with-update-mark($icon-base-width) {
|
||||
.icon {
|
||||
width: $icon-base-width;
|
||||
|
||||
&.has-update-mark:after {
|
||||
right: ($icon-base-width / 2) - 0.85;
|
||||
}
|
||||
}
|
||||
}
|
35
packages/demobank-ui/src/scss/_modal.scss
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
.modal-card {
|
||||
width: $modal-card-width;
|
||||
}
|
||||
|
||||
.modal-card-foot {
|
||||
background-color: $modal-card-foot-background-color;
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
.modal .animation-content .modal-card {
|
||||
width: $modal-card-width-mobile;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
144
packages/demobank-ui/src/scss/_nav-bar.scss
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
nav.navbar {
|
||||
box-shadow: $navbar-box-shadow;
|
||||
|
||||
.navbar-item {
|
||||
&.has-user-avatar {
|
||||
.is-user-avatar {
|
||||
margin-right: $default-padding * 0.5;
|
||||
display: inline-flex;
|
||||
width: $navbar-avatar-size;
|
||||
height: $navbar-avatar-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-divider {
|
||||
border-right: $navbar-divider-border;
|
||||
}
|
||||
|
||||
&.no-left-space {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
&.has-dropdown {
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
|
||||
.navbar-link {
|
||||
padding-right: $navbar-item-h-padding;
|
||||
padding-left: $navbar-item-h-padding;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-control {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.control {
|
||||
.input {
|
||||
color: $navbar-input-color;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
|
||||
&::placeholder {
|
||||
color: $navbar-input-placeholder-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include touch {
|
||||
nav.navbar {
|
||||
display: flex;
|
||||
padding-right: 0;
|
||||
|
||||
.navbar-brand {
|
||||
flex: 1;
|
||||
|
||||
&.is-right {
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-item {
|
||||
&.no-left-space-touch {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-menu {
|
||||
position: absolute;
|
||||
width: 100vw;
|
||||
padding-top: 0;
|
||||
top: $navbar-height;
|
||||
left: 0;
|
||||
|
||||
.navbar-item {
|
||||
.icon:first-child {
|
||||
margin-right: $default-padding * 0.5;
|
||||
}
|
||||
|
||||
&.has-dropdown {
|
||||
> .navbar-link {
|
||||
background-color: $white-ter;
|
||||
.icon:last-child {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.has-user-avatar {
|
||||
> .navbar-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-top: $default-padding * 0.5;
|
||||
padding-bottom: $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
nav.navbar {
|
||||
.navbar-item {
|
||||
padding-right: $navbar-item-h-padding;
|
||||
padding-left: $navbar-item-h-padding;
|
||||
|
||||
&:not(.is-desktop-icon-only) {
|
||||
.icon:first-child {
|
||||
margin-right: $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
&.is-desktop-icon-only {
|
||||
span:not(.icon) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
179
packages/demobank-ui/src/scss/_table.scss
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
table.table {
|
||||
thead {
|
||||
th {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
&.checkbox-cell {
|
||||
.b-checkbox.checkbox:not(.button) {
|
||||
margin-right: 0;
|
||||
width: 20px;
|
||||
|
||||
.control-label {
|
||||
display: none;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
.image {
|
||||
margin: 0 auto;
|
||||
width: $table-avatar-size;
|
||||
height: $table-avatar-size;
|
||||
}
|
||||
|
||||
&.is-progress-col {
|
||||
min-width: 5rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.b-table {
|
||||
.table {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
/* This stylizes buefy's pagination */
|
||||
.table-wrapper {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.table-wrapper + .level {
|
||||
padding: $notification-padding;
|
||||
padding-left: $card-content-padding;
|
||||
padding-right: $card-content-padding;
|
||||
margin: 0;
|
||||
border-top: $base-color-light;
|
||||
background: $notification-background-color;
|
||||
|
||||
.pagination-link {
|
||||
background: $button-background-color;
|
||||
color: $button-color;
|
||||
border-color: $button-border-color;
|
||||
|
||||
&.is-current {
|
||||
border-color: $button-active-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-previous,
|
||||
.pagination-next,
|
||||
.pagination-link {
|
||||
border-color: $button-border-color;
|
||||
color: $base-color;
|
||||
|
||||
&[disabled] {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include mobile {
|
||||
.card {
|
||||
&.has-table {
|
||||
.b-table {
|
||||
.table-wrapper + .level {
|
||||
.level-left + .level-right {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.has-mobile-sort-spaced {
|
||||
.b-table {
|
||||
.field.table-mobile-sort {
|
||||
padding-top: $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.b-table {
|
||||
.field.table-mobile-sort {
|
||||
padding: 0 $default-padding * 0.5;
|
||||
}
|
||||
|
||||
.table-wrapper.has-mobile-cards {
|
||||
tr {
|
||||
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1);
|
||||
margin-bottom: 3px !important;
|
||||
}
|
||||
td {
|
||||
&.is-progress-col {
|
||||
span,
|
||||
progress {
|
||||
display: flex;
|
||||
width: 45%;
|
||||
align-items: center;
|
||||
align-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
&.checkbox-cell,
|
||||
&.is-image-cell {
|
||||
border-bottom: 0 !important;
|
||||
}
|
||||
|
||||
&.checkbox-cell,
|
||||
&.is-actions-cell {
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-no-head-mobile {
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
span {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-progress-col {
|
||||
progress {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-image-cell {
|
||||
.image {
|
||||
width: $table-avatar-size-mobile;
|
||||
height: auto;
|
||||
margin: 0 auto $default-padding * 0.25;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
136
packages/demobank-ui/src/scss/_theme-default.scss
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
/* We'll need some initial vars to use here */
|
||||
@import "node_modules/bulma/sass/utilities/initial-variables";
|
||||
|
||||
/* Base: Size */
|
||||
$size-base: 1rem;
|
||||
$default-padding: $size-base * 1.5;
|
||||
|
||||
/* Default font */
|
||||
$family-sans-serif: "Nunito", sans-serif;
|
||||
|
||||
/* Base color */
|
||||
$base-color: #2e323a;
|
||||
$base-color-light: rgba(24, 28, 33, 0.06);
|
||||
|
||||
/* General overrides */
|
||||
$primary: $turquoise;
|
||||
$body-background-color: #f8f8f8;
|
||||
$link: $blue;
|
||||
$link-visited: $purple;
|
||||
$light-border: 1px solid $base-color-light;
|
||||
$hr-height: 1px;
|
||||
|
||||
/* NavBar: specifics */
|
||||
$navbar-input-color: $grey-darker;
|
||||
$navbar-input-placeholder-color: $grey-lighter;
|
||||
$navbar-box-shadow: 0 1px 0 rgba(24, 28, 33, 0.04);
|
||||
$navbar-divider-border: 1px solid rgba($grey-lighter, 0.25);
|
||||
$navbar-item-h-padding: $default-padding * 0.75;
|
||||
$navbar-avatar-size: 1.75rem;
|
||||
|
||||
/* Aside: Bulma override */
|
||||
$menu-item-radius: 0;
|
||||
$menu-list-link-padding: $size-base * 0.5 0;
|
||||
$menu-label-color: lighten($base-color, 25%);
|
||||
$menu-item-color: lighten($base-color, 30%);
|
||||
$menu-item-hover-color: $white;
|
||||
$menu-item-hover-background-color: darken($base-color, 3.5%);
|
||||
$menu-item-active-color: $white;
|
||||
$menu-item-active-background-color: darken($base-color, 2.5%);
|
||||
|
||||
/* Aside: specifics */
|
||||
$aside-width: $size-base * 14;
|
||||
$aside-mobile-width: $size-base * 15;
|
||||
$aside-icon-width: $size-base * 3;
|
||||
$aside-submenu-font-size: $size-base * 0.95;
|
||||
$aside-box-shadow: none;
|
||||
$aside-background-color: $base-color;
|
||||
$aside-tools-background-color: darken($aside-background-color, 10%);
|
||||
$aside-tools-color: $white;
|
||||
|
||||
/* Title Bar: specifics */
|
||||
$title-bar-color: $grey;
|
||||
$title-bar-active-color: $black-ter;
|
||||
|
||||
/* Hero Bar: specifics */
|
||||
$hero-bar-background: $white;
|
||||
|
||||
/* Card: Bulma override */
|
||||
$card-shadow: none;
|
||||
$card-header-shadow: none;
|
||||
|
||||
/* Card: specifics */
|
||||
$card-border: 1px solid $base-color-light;
|
||||
$card-header-border-bottom-color: $base-color-light;
|
||||
|
||||
/* Table: Bulma override */
|
||||
$table-cell-border: 1px solid $white-bis;
|
||||
|
||||
/* Table: specifics */
|
||||
$table-avatar-size: $size-base * 1.5;
|
||||
$table-avatar-size-mobile: 25vw;
|
||||
|
||||
/* Form */
|
||||
$checkbox-border: 1px solid $base-color;
|
||||
|
||||
/* Modal card: Bulma override */
|
||||
$modal-card-head-background-color: $white-ter;
|
||||
$modal-card-title-size: $size-base;
|
||||
$modal-card-body-padding: $default-padding 20px;
|
||||
$modal-card-head-border-bottom: 1px solid $white-ter;
|
||||
$modal-card-foot-border-top: 0;
|
||||
|
||||
/* Modal card: specifics */
|
||||
$modal-card-width: 80vw;
|
||||
$modal-card-width-mobile: 90vw;
|
||||
$modal-card-foot-background-color: $white-ter;
|
||||
|
||||
/* Notification: Bulma override */
|
||||
$notification-padding: $default-padding * 0.75 $default-padding;
|
||||
|
||||
/* Footer: Bulma override */
|
||||
$footer-background-color: $white;
|
||||
$footer-padding: $default-padding * 0.33 $default-padding;
|
||||
|
||||
/* Footer: specifics */
|
||||
$footer-logo-height: $size-base * 2;
|
||||
|
||||
/* Progress: Bulma override */
|
||||
$progress-bar-background-color: $grey-lighter;
|
||||
|
||||
/* Icon: specifics */
|
||||
$icon-update-mark-size: $size-base * 0.5;
|
||||
$icon-update-mark-color: $yellow;
|
||||
|
||||
$input-disabled-border-color: $grey-lighter;
|
||||
$table-row-hover-background-color: hsl(0, 0%, 80%);
|
||||
|
||||
.menu-list {
|
||||
div {
|
||||
border-radius: $menu-item-radius;
|
||||
color: $menu-item-color;
|
||||
display: block;
|
||||
padding: $menu-list-link-padding;
|
||||
}
|
||||
}
|
24
packages/demobank-ui/src/scss/_tiles.scss
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
.is-tiles-wrapper {
|
||||
margin-bottom: $default-padding;
|
||||
}
|
50
packages/demobank-ui/src/scss/_title-bar.scss
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
section.section.is-title-bar {
|
||||
padding: $default-padding;
|
||||
border-bottom: $light-border;
|
||||
|
||||
ul {
|
||||
li {
|
||||
display: inline-block;
|
||||
padding: 0 $default-padding * 0.5 0 0;
|
||||
font-size: $default-padding;
|
||||
color: $title-bar-color;
|
||||
|
||||
&:after {
|
||||
display: inline-block;
|
||||
content: "/";
|
||||
padding-left: $default-padding * 0.5;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
font-weight: 900;
|
||||
color: $title-bar-active-color;
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
264
packages/demobank-ui/src/scss/bank.scss
Normal file
@ -0,0 +1,264 @@
|
||||
.navcontainer:not(.default-navcontainer) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.abort-button {
|
||||
margin-left: 2px;
|
||||
border: 2px solid rgb(0, 120, 231);
|
||||
color: rgb(0, 120, 231);
|
||||
font-size: 87%;
|
||||
margin-top: 1px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
div.pages-list {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.login-div,
|
||||
.register-div {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a.page-number {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
a.current-page-number {
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.cancelled {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-outer-spin-button,
|
||||
input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* This CSS code styles the tab */
|
||||
.tab {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.logout {
|
||||
float: right;
|
||||
border: 20px;
|
||||
margin-right: 15px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.tab button {
|
||||
background-color: lightgray;
|
||||
color: black;
|
||||
float: left;
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
padding: 18px 19px;
|
||||
border: 2px solid #c1c1c1;
|
||||
transition: 0.5s;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tab button:hover {
|
||||
background-color: yellow;
|
||||
border: 2px solid #c1c1c1;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tab button.active {
|
||||
background-color: orange;
|
||||
border: 2px solid #c1c1c1;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tabcontent {
|
||||
display: none;
|
||||
padding: 8px 16px;
|
||||
border: 2px solid #c1c1c1;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.tabcontent.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
#transfer-fields {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#id_amount {
|
||||
width: 6em;
|
||||
display: inline-block;
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Amount without the currency,
|
||||
* placed left to a .currency-indicator.
|
||||
*/
|
||||
#main .amount {
|
||||
width: 6em;
|
||||
display: inline-block;
|
||||
border-radius: 4px 0px 0px 4px;
|
||||
}
|
||||
|
||||
input {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.large-amount {
|
||||
font-weight: bold;
|
||||
font-size: x-large;
|
||||
}
|
||||
|
||||
.currency {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
/*
|
||||
* Currency indicator to the right of input fields,
|
||||
* with non-rounded corners to the left.
|
||||
*/
|
||||
#main .currency-indicator {
|
||||
color: black;
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#main .fieldlabel {
|
||||
display: block;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#main .fieldbox {
|
||||
margin-right: 1em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#logout-button {
|
||||
display: block;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.register-form > .pure-form,
|
||||
.login-form > .pure-form {
|
||||
background: #4a4a4a;
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 16px 16px;
|
||||
border-radius: 8px;
|
||||
width: max-content;
|
||||
.formFieldLabel {
|
||||
margin: 2px 2px;
|
||||
}
|
||||
input[type="text"],
|
||||
input[type="password"] {
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: #6a6a6a;
|
||||
color: #fefefe;
|
||||
box-shadow: none;
|
||||
}
|
||||
input[placeholder="Password"][type="password"] {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.btn-register,
|
||||
.btn-login {
|
||||
float: left;
|
||||
}
|
||||
.btn-cancel {
|
||||
float: right;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.challenge-div {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.challenge-form > .pure-form {
|
||||
background: #4a4a4a;
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 16px 16px;
|
||||
border-radius: 8px;
|
||||
width: max-content;
|
||||
.formFieldLabel {
|
||||
margin: 2px 2px;
|
||||
}
|
||||
input[type="text"] {
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: #6a6a6a;
|
||||
color: #fefefe;
|
||||
box-shadow: none;
|
||||
}
|
||||
.btn-confirm {
|
||||
float: left;
|
||||
}
|
||||
.btn-cancel {
|
||||
float: right;
|
||||
}
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.wire-transfer-form > .pure-form,
|
||||
.payto-form > .pure-form,
|
||||
.reserve-form > .pure-form {
|
||||
background: #4a4a4a;
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 16px 16px;
|
||||
border-radius: 8px;
|
||||
width: max-content;
|
||||
.formFieldLabel {
|
||||
margin: 2px 2px;
|
||||
}
|
||||
input[type="text"] {
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: #6a6a6a;
|
||||
color: #fefefe;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
html {
|
||||
background: #ffffff;
|
||||
color: #2a2a2a;
|
||||
}
|
||||
|
||||
.hint {
|
||||
scale: 0.7;
|
||||
}
|
31
packages/demobank-ui/src/scss/colors-bank.scss
Normal file
@ -0,0 +1,31 @@
|
||||
nav,
|
||||
nav a,
|
||||
nav span,
|
||||
.navcontainer,
|
||||
nav button,
|
||||
.demobar,
|
||||
.navbtn {
|
||||
color: white;
|
||||
background: #a00000;
|
||||
}
|
||||
|
||||
nav a.active,
|
||||
nav button,
|
||||
nav span.active,
|
||||
.navbtn.active {
|
||||
background-color: #7a0606;
|
||||
}
|
||||
|
||||
nav a.active:hover,
|
||||
nav span.active:hover,
|
||||
.navbtn.active:hover,
|
||||
nav button:hover,
|
||||
nav a:hover,
|
||||
nav span:hover,
|
||||
.navbtn:hover {
|
||||
background: #df3d3d;
|
||||
}
|
||||
|
||||
nav a.navbtn.langbtn:focus {
|
||||
background-color: #df3d3d;
|
||||
}
|
157
packages/demobank-ui/src/scss/demo.scss
Normal file
@ -0,0 +1,157 @@
|
||||
@charset "UTF-8";
|
||||
/*
|
||||
Style common to all demo pages.
|
||||
|
||||
Colors:
|
||||
- #1e2739 (dark blue)
|
||||
- #0042b2 (default blue)
|
||||
- #3daee9 (highlight blue)
|
||||
*/
|
||||
|
||||
.demobar h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.demobar > p {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.demobar a,
|
||||
.demobar a:visited {
|
||||
color: inherit;
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.tt {
|
||||
font-family: "Lucida Console", Monaco, monospace;
|
||||
}
|
||||
|
||||
.informational-ok {
|
||||
background: lightgreen;
|
||||
border-radius: 1em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.informational-fail {
|
||||
background: lightpink;
|
||||
border-radius: 1em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 2em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.demobar {
|
||||
overflow-x: auto;
|
||||
background-color: #0042b2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.navcontainer {
|
||||
background: #0042b2;
|
||||
margin-bottom: 50px;
|
||||
width: 100%;
|
||||
color: white;
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
width: 100vw;
|
||||
backdrop-filter: blur(10px);
|
||||
opacity: 1;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
nav {
|
||||
left: 1vw;
|
||||
position: relative;
|
||||
background: #0042b2;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
nav a,
|
||||
nav button,
|
||||
nav span,
|
||||
.navbtn {
|
||||
border: none;
|
||||
color: white;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
background: #0042b2;
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
nav a,
|
||||
nav button,
|
||||
nav span,
|
||||
.navbtn {
|
||||
padding: 15px 32px;
|
||||
}
|
||||
|
||||
nav a:hover,
|
||||
nav span:hover,
|
||||
.navbtn:hover {
|
||||
background: #3daee9;
|
||||
}
|
||||
|
||||
nav a.active,
|
||||
nav span.active,
|
||||
.navbtn.active {
|
||||
background-color: #1e2739;
|
||||
}
|
||||
|
||||
nav a.active:hover,
|
||||
nav button.active:hover,
|
||||
nav span.active:hover,
|
||||
.navbtn.active:hover {
|
||||
background: #3daee9;
|
||||
}
|
||||
|
||||
nav a,
|
||||
nav span,
|
||||
.navbtn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
nav .right {
|
||||
float: right;
|
||||
margin-right: 5vw;
|
||||
}
|
||||
nav .hide div.nav {
|
||||
display: none;
|
||||
}
|
||||
// nav .right div.nav:hover {
|
||||
// display: block;
|
||||
// }
|
||||
|
||||
// nav .right:hover div.nav {
|
||||
// display: block;
|
||||
// }
|
||||
|
||||
.langbtn {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.skip {
|
||||
position: absolute;
|
||||
left: -10000px;
|
||||
top: auto;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.skip:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
BIN
packages/demobank-ui/src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf
Normal file
22
packages/demobank-ui/src/scss/fonts/nunito.css
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
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/>
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nunito';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(./XRXV3I6Li01BKofINeaE.ttf) format('truetype');
|
||||
}
|
3
packages/demobank-ui/src/scss/icons/materialdesignicons-4.9.95.min.css
vendored
Normal file
29
packages/demobank-ui/src/scss/libs/_all.scss
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
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 "node_modules/bulma-radio/bulma-radio";
|
||||
// @import "node_modules/bulma-responsive-tables/bulma-responsive-tables";
|
||||
@import "node_modules/bulma-checkbox/bulma-checkbox";
|
||||
// @import "node_modules/bulma-switch-control/bulma-switch-control";
|
||||
// @import "node_modules/bulma-upload-control/bulma-upload-control";
|
||||
|
||||
/* Bulma */
|
||||
@import "node_modules/bulma/bulma";
|
4
packages/demobank-ui/src/scss/main.scss
Normal file
@ -0,0 +1,4 @@
|
||||
@import "pure";
|
||||
@import "bank";
|
||||
@import "demo";
|
||||
@import "colors-bank";
|