mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
feat(frontend): migration setup (#3342)
* frontend - moved to vue 2.7 and vite * frontend - moved to vue 3 * frontend - login page updates * fix(frontend): WiP migration * fix(frontend): WiP migration * fix(frontend): WiP migration * fix(frontend): WiP migration * fix(frontend): WiP migration * fix(frontend): fix eslint/stylelint issues * fix(frontend): fix eslint/stylelint issues * feature(frontend): update node in docker frontend * feature(frontend): move send types out of Send file * feature(frontend): add entry in package json to fix eslint issue * feature(frontend): eslint fix * replace docker-compose with docker compose * update docker-compose test file * feature(frontend): Creation fixes * feature(frontend): Add missing updates for apollo scripts. --------- Co-authored-by: einhornimmond <silas@einhornimmond.de>
This commit is contained in:
parent
fb047b89b5
commit
cdaca99b04
4
.github/workflows/test_backend.yml
vendored
4
.github/workflows/test_backend.yml
vendored
@ -44,14 +44,14 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Backend | docker-compose mariadb
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
|
||||
- name: Sleep for 30 seconds
|
||||
run: sleep 30s
|
||||
shell: bash
|
||||
|
||||
- name: Backend | docker-compose database
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
|
||||
- name: Backend | Unit tests
|
||||
run: cd database && yarn && yarn build && cd ../backend && yarn && yarn test
|
||||
|
||||
6
.github/workflows/test_database.yml
vendored
6
.github/workflows/test_database.yml
vendored
@ -43,13 +43,13 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Database | docker-compose
|
||||
run: docker-compose -f docker-compose.yml up --detach mariadb
|
||||
run: docker compose -f docker-compose.yml up --detach mariadb
|
||||
|
||||
- name: Database | up
|
||||
run: docker-compose -f docker-compose.yml run -T database yarn up
|
||||
run: docker compose -f docker-compose.yml run -T database yarn up
|
||||
|
||||
- name: Database | reset
|
||||
run: docker-compose -f docker-compose.yml run -T database yarn reset
|
||||
run: docker compose -f docker-compose.yml run -T database yarn reset
|
||||
|
||||
lint:
|
||||
if: needs.files-changed.outputs.database == 'true'
|
||||
|
||||
8
.github/workflows/test_dht_node.yml
vendored
8
.github/workflows/test_dht_node.yml
vendored
@ -71,15 +71,15 @@ jobs:
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/dht-node.tar
|
||||
|
||||
- name: docker-compose mariadb
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
- name: docker compose mariadb
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
|
||||
- name: Sleep for 30 seconds
|
||||
run: sleep 30s
|
||||
shell: bash
|
||||
|
||||
- name: docker-compose database
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
- name: docker compose database
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
|
||||
- name: Sleep for 30 seconds
|
||||
run: sleep 30s
|
||||
|
||||
4
.github/workflows/test_dlt_connector.yml
vendored
4
.github/workflows/test_dlt_connector.yml
vendored
@ -61,8 +61,8 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: DLT-Connector | docker-compose mariadb
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
- name: DLT-Connector | docker compose mariadb
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
|
||||
- name: Sleep for 30 seconds
|
||||
run: sleep 30s
|
||||
|
||||
10
.github/workflows/test_e2e.yml
vendored
10
.github/workflows/test_e2e.yml
vendored
@ -11,17 +11,17 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Boot up test system | docker-compose mariadb
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach mariadb
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach mariadb
|
||||
|
||||
- name: Boot up test system | docker-compose database
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
|
||||
- name: Boot up test system | docker-compose backend
|
||||
run: |
|
||||
cd backend
|
||||
cp .env.test_e2e .env
|
||||
cd ..
|
||||
docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps backend
|
||||
docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps backend
|
||||
|
||||
- name: Sleep for 10 seconds
|
||||
run: sleep 10s
|
||||
@ -35,10 +35,10 @@ jobs:
|
||||
yarn && yarn seed
|
||||
|
||||
- name: Boot up test system | docker-compose frontends
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps frontend admin nginx
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps frontend admin nginx
|
||||
|
||||
- name: Boot up test system | docker-compose mailserver
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mailserver
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mailserver
|
||||
|
||||
- name: End-to-end tests | prepare
|
||||
run: |
|
||||
|
||||
8
.github/workflows/test_federation.yml
vendored
8
.github/workflows/test_federation.yml
vendored
@ -70,15 +70,15 @@ jobs:
|
||||
- name: Load Docker Image
|
||||
run: docker load < /tmp/federation.tar
|
||||
|
||||
- name: docker-compose mariadb
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
- name: docker compose mariadb
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb
|
||||
|
||||
- name: Sleep for 30 seconds
|
||||
run: sleep 30s
|
||||
shell: bash
|
||||
|
||||
- name: docker-compose database
|
||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
- name: docker compose database
|
||||
run: docker compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps database
|
||||
|
||||
- name: Sleep for 30 seconds
|
||||
run: sleep 30s
|
||||
|
||||
@ -95,6 +95,9 @@ services:
|
||||
#########################################################
|
||||
mariadb:
|
||||
image: gradido/mariadb:test
|
||||
environment:
|
||||
- MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1
|
||||
- MARIADB_USER=root
|
||||
networks:
|
||||
- internal-net
|
||||
- external-net
|
||||
|
||||
@ -4,15 +4,17 @@ module.exports = {
|
||||
browser: true,
|
||||
node: true,
|
||||
jest: true,
|
||||
'vue/setup-compiler-macros': true,
|
||||
},
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
ecmaVersion: 2020,
|
||||
},
|
||||
extends: [
|
||||
'standard',
|
||||
'plugin:vue/essential',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'plugin:prettier/recommended',
|
||||
'plugin:@intlify/vue-i18n/recommended',
|
||||
'prettier',
|
||||
],
|
||||
// required to lint *.vue files
|
||||
plugins: ['vue', 'prettier', 'jest'],
|
||||
@ -30,14 +32,26 @@ module.exports = {
|
||||
rules: {
|
||||
'no-console': ['error'],
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-useless-escape': 0,
|
||||
'no-unused-vars': 0, // TODO remove at the end of migration and fix
|
||||
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
|
||||
'vue/no-static-inline-styles': [
|
||||
'error',
|
||||
{
|
||||
allowBinding: false,
|
||||
},
|
||||
],
|
||||
// 'vue/no-static-inline-styles': [
|
||||
// 'error',
|
||||
// {
|
||||
// allowBinding: false,
|
||||
// },
|
||||
// ],
|
||||
'vue/multi-word-component-names': 0,
|
||||
'vue/no-v-html': 0,
|
||||
'vue/no-export-in-script-setup': 0, // TODO remove at the end of migration and fix
|
||||
'vue/prop-name-casing': 0, // TODO remove at the end of migration and fix
|
||||
'vue/require-explicit-emits': 0, // TODO remove at the end of migration and fix
|
||||
'vue/no-static-inline-styles': 0, // TODO remove at the end of migration and fix
|
||||
'vue/v-on-event-hyphenation': 0, // TODO remove at the end of migration and fix
|
||||
'vue/require-default-prop': 0, // TODO remove at the end of migration and fix
|
||||
'vue/no-computed-properties-in-data': 0, // TODO remove at the end of migration and fix
|
||||
'@intlify/vue-i18n/no-dynamic-keys': 'error',
|
||||
'@intlify/vue-i18n/no-missing-keys': 0, // TODO remove at the end of migration and fix
|
||||
'@intlify/vue-i18n/no-unused-keys': [
|
||||
'error',
|
||||
{
|
||||
@ -75,7 +89,7 @@ module.exports = {
|
||||
localeDir: './src/locales/{en,de}.json',
|
||||
// Specify the version of `vue-i18n` you are using.
|
||||
// If not specified, the message will be parsed twice.
|
||||
messageSyntaxVersion: '^8.22.4',
|
||||
messageSyntaxVersion: '^9.13.1',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
2
frontend/.gitignore
vendored
2
frontend/.gitignore
vendored
@ -24,3 +24,5 @@ package-lock.json
|
||||
coverage/
|
||||
|
||||
*~
|
||||
|
||||
components.d.ts
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
// to edit target browsers: use "browserslist" field in package.json
|
||||
autoprefixer: {}
|
||||
}
|
||||
};
|
||||
@ -1,7 +1,7 @@
|
||||
##################################################################################
|
||||
# BASE ###########################################################################
|
||||
##################################################################################
|
||||
FROM node:16-alpine3.14 as base
|
||||
FROM node:18.20-alpine3.20 as base
|
||||
|
||||
# ENVs (available in production aswell, can be overwritten by commandline or env file)
|
||||
## DOCKER_WORKDIR would be a classical ARG, but that is not multi layer persistent - shame
|
||||
@ -98,13 +98,13 @@ COPY --from=build ${DOCKER_WORKDIR}/run ./run
|
||||
CMD /bin/sh -c "yarn run start"
|
||||
|
||||
|
||||
|
||||
|
||||
## add `/usr/src/app/node_modules/.bin` to $PATH
|
||||
#ENV PATH /usr/src/app/node_modules/.bin:$PATH
|
||||
#
|
||||
#
|
||||
## install and cache app dependencies
|
||||
#COPY package.json /usr/src/app/package.json
|
||||
#RUN npm install
|
||||
#RUN npm install -g @vue/cli
|
||||
## start app
|
||||
#CMD ["npm", "run", "serve"]
|
||||
#CMD ["npm", "run", "serve"]
|
||||
|
||||
@ -11,7 +11,7 @@ module.exports = function (api) {
|
||||
],
|
||||
]
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
if (import.meta.env.NODE_ENV === 'test') {
|
||||
plugins.push('transform-require-context')
|
||||
}
|
||||
|
||||
|
||||
69
frontend/index.html
Normal file
69
frontend/index.html
Normal file
@ -0,0 +1,69 @@
|
||||
<!--
|
||||
|
||||
=========================================================
|
||||
* Gradido Konto - v1.6.1
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.gradido.net
|
||||
* Copyright 2021 Gradido-Akademie - (https://www.gradido.net)
|
||||
|
||||
* Coded by www.gradido.net
|
||||
|
||||
=========================================================
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="title" lang="de" content="VITE test">
|
||||
<meta name="title" lang="en" content="VITE test">
|
||||
<meta name="description" lang="de" content="VITE test">
|
||||
<meta name="description" lang="en" content="VITE test">
|
||||
<meta name="keywords" lang="de" content="VITE test">
|
||||
<meta name="keywords" lang="en" content="VITE test">
|
||||
<meta name="author" content="VITE test">
|
||||
<meta name="url" content="VITE test">
|
||||
<meta name="identifier-URL" content="VITE test">
|
||||
<!-- <meta name="title" lang="de" content="<%= htmlWebpackPlugin.options.meta.title_de %>">-->
|
||||
<!-- <meta name="title" lang="en" content="<%= htmlWebpackPlugin.options.meta.title_en %>">-->
|
||||
<!-- <meta name="description" lang="de" content="<%= htmlWebpackPlugin.options.meta.description_de %>">-->
|
||||
<!-- <meta name="description" lang="en" content="<%= htmlWebpackPlugin.options.meta.description_en %>">-->
|
||||
<!-- <meta name="keywords" lang="de" content="<%= htmlWebpackPlugin.options.meta.keywords_de %>">-->
|
||||
<!-- <meta name="keywords" lang="en" content="<%= htmlWebpackPlugin.options.meta.keywords_en %>">-->
|
||||
<!-- <meta name="author" content="<%= htmlWebpackPlugin.options.meta.author %>">-->
|
||||
<!-- <meta name="url" content="<%= htmlWebpackPlugin.options.meta.url %>">-->
|
||||
<!-- <meta name="identifier-URL" content="<%= htmlWebpackPlugin.options.meta.url %>">-->
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="index,follow">
|
||||
<link rel='canonical' href='VITE test'>
|
||||
<!-- <link rel='canonical' href='<%= htmlWebpackPlugin.options.meta.url %>'>-->
|
||||
<link rel="icon" type="image/png" sizes="96x96" href="/favicon.png">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
|
||||
|
||||
<!-- <meta property="og:title" content="<%= htmlWebpackPlugin.options.meta.title_de %>" />-->
|
||||
<!-- <meta property="og:description" content="<%= htmlWebpackPlugin.options.meta.description_de %>" />-->
|
||||
<!-- <meta property="og:type" content="Website" />-->
|
||||
<!-- <meta property="og:url" content="<%= htmlWebpackPlugin.options.meta.url %>" />-->
|
||||
<!-- <meta property="og:image" content="<%= htmlWebpackPlugin.options.meta.url %>/img/gradido-wallet-650-400.jpg" />-->
|
||||
|
||||
<!-- <meta lang="de" name="twitter:title" content="<%= htmlWebpackPlugin.options.meta.title_de %>">-->
|
||||
<!-- <meta lang="en" name="twitter:title" content="<%= htmlWebpackPlugin.options.meta.title_en %>">-->
|
||||
<!-- <meta lang="de" name="twitter:description" content="<%= htmlWebpackPlugin.options.meta.description_de %>">-->
|
||||
<!-- <meta lang="en" name="twitter:description" content="<%= htmlWebpackPlugin.options.meta.description_en %>">-->
|
||||
<!-- <meta name="twitter:image" content="<%= htmlWebpackPlugin.options.meta.url %>/img/gradido-wallet-650-400.jpg">-->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
@ -4,95 +4,101 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "node run/server.js",
|
||||
"serve": "vue-cli-service serve --open",
|
||||
"build": "vue-cli-service build",
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"postbuild": "find build -type f -regex '.*\\.\\(html\\|js\\|css\\|svg\\|json\\)' -exec gzip -9 -k {} +",
|
||||
"dev": "yarn run serve",
|
||||
"analyse-bundle": "yarn build && webpack-bundle-analyzer build/webpack.stats.json",
|
||||
"lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
|
||||
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
|
||||
"test": "cross-env TZ=UTC jest",
|
||||
"test": "echo Tests are temporarly disabled for migration time",
|
||||
"locales": "scripts/sort.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.13.13",
|
||||
"@babel/node": "^7.13.13",
|
||||
"@babel/preset-env": "^7.13.12",
|
||||
"@vue/cli-plugin-unit-jest": "^4.5.12",
|
||||
"@vee-validate/i18n": "^4.13.2",
|
||||
"@vee-validate/rules": "^4.13.2",
|
||||
"@vee-validate/yup": "^4.13.2",
|
||||
"@vitejs/plugin-vue": "3.2.0",
|
||||
"@vue/apollo-composable": "^4.0.2",
|
||||
"@vue/apollo-option": "^4.0.0",
|
||||
"@vue/compat": "^3.4.31",
|
||||
"@vue/test-utils": "^1.1.3",
|
||||
"apollo-boost": "^0.4.9",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-jest": "^27.3.1",
|
||||
"babel-preset-vue": "^2.0.2",
|
||||
"bootstrap": "^4.5.3",
|
||||
"bootstrap-vue": "^2.21.2",
|
||||
"bootstrap": "^5.3.3",
|
||||
"bootstrap-vue-next": "^0.23.3",
|
||||
"clipboard-polyfill": "^4.0.0-rc1",
|
||||
"date-fns": "^2.29.3",
|
||||
"es6-promise": "^4.1.1",
|
||||
"eslint": "^7.25.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-config-standard": "^16.0.2",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"eslint-plugin-jest": "^24.3.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-vue": "^7.8.0",
|
||||
"express": "^4.17.1",
|
||||
"flatpickr": "^4.5.7",
|
||||
"flush-promises": "^1.0.2",
|
||||
"graphql": "^15.5.1",
|
||||
"graphql": "^16.9.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-canvas-mock": "^2.5.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"portal-vue": "^2.1.7",
|
||||
"prettier": "^2.2.1",
|
||||
"portal-vue": "^3.0.0",
|
||||
"qrcanvas-vue": "2.1.1",
|
||||
"regenerator-runtime": "^0.13.7",
|
||||
"uuid": "^9.0.0",
|
||||
"vee-validate": "^3.4.5",
|
||||
"vue": "2.6.12",
|
||||
"vue-apollo": "^3.0.7",
|
||||
"vee-validate": "^4.13.2",
|
||||
"vite": "3.2.10",
|
||||
"vite-plugin-commonjs": "^0.10.1",
|
||||
"vue": "3.4.31",
|
||||
"vue-apollo": "^3.1.2",
|
||||
"vue-avatar": "^2.3.3",
|
||||
"vue-flatpickr-component": "^8.1.2",
|
||||
"vue-focus": "^2.1.0",
|
||||
"vue-i18n": "^8.22.4",
|
||||
"vue-i18n": "^9.13.1",
|
||||
"vue-jest": "^3.0.7",
|
||||
"vue-loading-overlay": "^3.4.2",
|
||||
"vue-router": "^3.0.6",
|
||||
"vue-router": "^4.4.0",
|
||||
"vue-timer-hook": "^1.0.84",
|
||||
"vue-timers": "^2.0.4",
|
||||
"vue2-transitions": "^0.2.3",
|
||||
"vuex": "^3.6.0",
|
||||
"vuex-persistedstate": "^4.0.0-beta.3"
|
||||
"vuex": "^4.1.0",
|
||||
"vuex-persistedstate": "^4.1.0",
|
||||
"yup": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@apollo/client": "^3.7.4",
|
||||
"@apollo/client": "^3.10.8",
|
||||
"@iconify-json/bi": "^1.1.23",
|
||||
"@intlify/eslint-plugin-vue-i18n": "^1.4.0",
|
||||
"@vue/cli-plugin-babel": "^3.7.0",
|
||||
"@vue/cli-plugin-eslint": "^3.7.0",
|
||||
"@vue/cli-service": "^3.7.0",
|
||||
"@vue/compiler-sfc": "^3.4.35",
|
||||
"@vue/eslint-config-prettier": "^4.0.1",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-plugin-component": "^1.1.0",
|
||||
"babel-plugin-transform-require-context": "^0.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"dotenv-webpack": "^7.0.3",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-prettier": "8.10.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-loader": "^4.0.2",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"eslint-plugin-jest": "^25.2.2",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-prettier": "5.2.1",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-vue": "8.7.1",
|
||||
"mock-apollo-client": "^1.2.1",
|
||||
"postcss": "^8.4.8",
|
||||
"postcss-html": "^1.3.0",
|
||||
"postcss-scss": "^4.0.3",
|
||||
"sass": "1.32.13",
|
||||
"sass-loader": "^10",
|
||||
"stats-webpack-plugin": "^0.7.0",
|
||||
"stylelint": "^14.5.3",
|
||||
"stylelint-config-recommended-vue": "^1.3.0",
|
||||
"stylelint-config-standard-scss": "^3.0.0",
|
||||
"vue-cli-plugin-i18n": "^1.0.1",
|
||||
"vue-html-webpack-plugin": "^3.2.2",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"webpack-bundle-analyzer": "^4.5.0"
|
||||
"prettier": "^3.3.3",
|
||||
"stylelint": "16.7.0",
|
||||
"stylelint-config-recommended-vue": "1.5.0",
|
||||
"stylelint-config-standard-scss": "13.1.0",
|
||||
"unplugin-icons": "^0.19.1",
|
||||
"unplugin-vue-components": "^0.27.3",
|
||||
"vue-html-webpack-plugin": "^3.2.2"
|
||||
},
|
||||
"postcss": {
|
||||
"plugins": {
|
||||
@ -111,5 +117,10 @@
|
||||
"ignore": [
|
||||
"**/*.spec.js"
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"strip-ansi": "6.0.1",
|
||||
"string-width": "4.2.2",
|
||||
"wrap-ansi": "7.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ const path = require('path')
|
||||
|
||||
// Host & Port
|
||||
const hostname = '127.0.0.1'
|
||||
const port = process.env.PORT || 3000
|
||||
const port = import.meta.env.PORT || 3000
|
||||
|
||||
// Express Server
|
||||
const app = express()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div id="app" ref="app" :class="darkMode ? 'dark-mode' : ''">
|
||||
<div :class="$route.meta.requiresAuth ? 'appContent' : ''">
|
||||
<BToastOrchestrator />
|
||||
<div :class="$route.meta.requiresAuth ? 'app-content' : ''">
|
||||
<component :is="$route.meta.requiresAuth ? 'DashboardLayout' : 'AuthLayout'" />
|
||||
<div class="goldrand position-fixed fixed-bottom zindex1000"></div>
|
||||
</div>
|
||||
@ -13,43 +14,47 @@ import AuthLayout from '@/layouts/AuthLayout'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
DashboardLayout,
|
||||
AuthLayout,
|
||||
},
|
||||
computed: {
|
||||
darkMode() {
|
||||
return this.$store.state.darkMode
|
||||
},
|
||||
},
|
||||
components: {
|
||||
DashboardLayout,
|
||||
AuthLayout,
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'WorkSans', sans-serif !important;
|
||||
src: url(./assets/scss/fonts/WorkSans-VariableFont_wght.ttf) format('truetype');
|
||||
font-family: WorkSans, sans-serif !important;
|
||||
src: url('./assets/scss/fonts/WorkSans-VariableFont_wght.ttf') format('truetype');
|
||||
}
|
||||
|
||||
#app {
|
||||
font-size: 1rem;
|
||||
font-family: 'WorkSans', sans-serif !important;
|
||||
font-family: WorkSans, sans-serif !important;
|
||||
}
|
||||
.appContent {
|
||||
|
||||
.app-content {
|
||||
min-width: 330px;
|
||||
max-width: 1320px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
.appBoxShadow {
|
||||
-webkit-box-shadow: 20pt 20pt 50pt 0 #3838384f;
|
||||
|
||||
.app-box-shadow {
|
||||
box-shadow: 20pt 20pt 50pt 0 #3838384f;
|
||||
}
|
||||
@media screen and (max-width: 500px) {
|
||||
|
||||
@media screen and (width <= 500px) {
|
||||
#app {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1024px) {
|
||||
|
||||
@media screen and (width <= 1024px) {
|
||||
#app {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
@ -59,11 +64,11 @@ export default {
|
||||
.goldrand {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(197, 141, 56, 1) 6%,
|
||||
rgba(243, 205, 124, 1) 30%,
|
||||
rgba(219, 176, 86, 1) 54%,
|
||||
rgba(238, 192, 95, 1) 63%,
|
||||
rgba(204, 157, 61, 1) 88%
|
||||
rgb(197 141 56 / 100%) 6%,
|
||||
rgb(243 205 124 / 100%) 30%,
|
||||
rgb(219 176 86 / 100%) 54%,
|
||||
rgb(238 192 95 / 100%) 63%,
|
||||
rgb(204 157 61 / 100%) 88%
|
||||
);
|
||||
height: 13px;
|
||||
}
|
||||
@ -77,6 +82,7 @@ export default {
|
||||
height: 50px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.dropdown-toggle::after {
|
||||
float: right;
|
||||
top: 50%;
|
||||
|
||||
@ -978,4 +978,5 @@ $btn-border-radius-sm: $input-border-radius !default;
|
||||
|
||||
// Import Bootstrap variable defaults
|
||||
|
||||
@import "~bootstrap/scss/variables";
|
||||
@import "bootstrap/scss/variables";
|
||||
@import "gradido-custom/functions";
|
||||
|
||||
@ -13,8 +13,8 @@ $box-shadow-sm: 0 0 0.5rem rgba($gray-600, 0.075) !default;
|
||||
$box-shadow: 0 0 2rem 0 rgba($gray-600, 0.15) !default;
|
||||
$box-shadow-lg: 0 0 3rem rgba($gray-600, 0.175) !default;
|
||||
$component-active-color: $white !default;
|
||||
$component-active-bg: theme-color("primary") !default;
|
||||
$component-active-border-color: theme-color("primary") !default;
|
||||
$component-active-bg: $primary !default;
|
||||
$component-active-border-color: $primary !default;
|
||||
$component-hover-color: $gray-300 !default;
|
||||
$component-hover-bg: $gray-300 !default;
|
||||
$component-hover-border-color: $gray-300 !default;
|
||||
|
||||
@ -23,7 +23,7 @@ $custom-control-indicator-checked-border-color: $component-active-border-color !
|
||||
$custom-control-indicator-checked-box-shadow: $custom-control-indicator-box-shadow !default;
|
||||
|
||||
// $custom-control-indicator-checked-disabled-bg: rgb(theme-color("primary") 0.5) !default;
|
||||
$custom-control-indicator-checked-disabled-bg: theme-color("primary") !default;
|
||||
$custom-control-indicator-checked-disabled-bg: $primary !default;
|
||||
$custom-control-indicator-disabled-bg: $gray-200 !default;
|
||||
$custom-control-label-disabled-color: $gray-600 !default;
|
||||
|
||||
|
||||
@ -2,4 +2,4 @@
|
||||
|
||||
$custom-toggle-width: 50px !default;
|
||||
$custom-toggle-slider-bg: $gray-200 !default;
|
||||
$custom-toggle-checked-bg: theme-color("primary") !default;
|
||||
$custom-toggle-checked-bg: $primary !default;
|
||||
|
||||
@ -12,9 +12,9 @@ $datepicker-disabled-cell-color: $gray-300 !default;
|
||||
$datepicker-disabled-old-new-color: $gray-500 !default;
|
||||
$datepicker-header-cell-border-radius: $border-radius !default;
|
||||
$datepicker-active-color: $white !default;
|
||||
$datepicker-active-background: theme-color("primary") !default;
|
||||
$datepicker-active-background: $primary !default;
|
||||
$datepicker-active-box-shadow: none !default;
|
||||
$datepicker-range-background: theme-color("primary") !default;
|
||||
$datepicker-range-background: $primary !default;
|
||||
$datepicker-range-cell-focused-background: color.adjust($datepicker-range-background, $lightness: -5%);
|
||||
$datepicker-range-color: $white !default;
|
||||
$datepicker-range-highlighted-bg: $gray-200 !default;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
$footer-padding-y: 2.5rem;
|
||||
$footer-padding-x: 0;
|
||||
$footer-link-font-size: 0.85rem !default;
|
||||
$footer-bg: theme-color("secondary") !default;
|
||||
$footer-bg: $secondary !default;
|
||||
$footer-color: $gray-600 !default;
|
||||
$footer-link-color: $gray-600 !default;
|
||||
$footer-link-hover-color: $gray-700 !default;
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
@use "sass:color";
|
||||
|
||||
$form-feedback-valid-bg: color.adjust($success, $lightness: 15%) !default;
|
||||
$form-feedback-valid-color: theme-color("success") !default;
|
||||
$form-feedback-valid-color: $success !default;
|
||||
$form-feedback-invalid-bg: color.adjust($warning, $lightness: 15%) !default;
|
||||
$form-feedback-invalid-color: theme-color("warning") !default;
|
||||
$form-feedback-invalid-color: $warning !default;
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
@function theme-color($key: "primary") {
|
||||
@return #172b4d;
|
||||
}
|
||||
@ -4,17 +4,17 @@
|
||||
$nav-link-padding-y: 0.25rem !default;
|
||||
$nav-link-padding-x: 0.75rem !default;
|
||||
$nav-link-color: $gray-700 !default;
|
||||
$nav-link-hover-color: theme-color("primary") !default;
|
||||
$nav-link-hover-color: $primary !default;
|
||||
$nav-link-disabled-color: $gray-600 !default;
|
||||
$nav-pills-padding-y: 0.75rem !default;
|
||||
$nav-pills-padding-x: 1rem !default;
|
||||
$nav-pills-space-x: 1rem !default;
|
||||
$nav-pills-bg: $white !default;
|
||||
$nav-pills-border-width: 1px !default;
|
||||
$nav-pills-border-color: theme-color("primary") !default;
|
||||
$nav-pills-border-color: $primary !default;
|
||||
$nav-pills-border-radius: $border-radius !default;
|
||||
$nav-pills-link-color: theme-color("primary") !default;
|
||||
$nav-pills-link-hover-color: color.adjust(theme-color("primary"), $lightness: -5%) !default;
|
||||
$nav-pills-link-active-color: color-yiq(theme-color("primary")) !default;
|
||||
$nav-pills-link-active-bg: theme-color("primary") !default;
|
||||
$nav-pills-link-color: $primary !default;
|
||||
$nav-pills-link-hover-color: color.adjust($primary, $lightness: -5%) !default;
|
||||
$nav-pills-link-active-color: color-yiq($primary) !default;
|
||||
$nav-pills-link-active-bg: $primary !default;
|
||||
$nav-pills-box-shadow: $btn-box-shadow !default;
|
||||
|
||||
@ -8,7 +8,7 @@ $noui-target-box-shadow: inset 0 1px 2px rgb(90 97 105 / 10%) !default;
|
||||
$noui-slider-connect-bg: $primary !default;
|
||||
$noui-slider-connect-disabled-bg: #b2b2b2 !default;
|
||||
$noui-handle-width: 15px !default;
|
||||
$noui-handle-bg: theme-color("primary") !default;
|
||||
$noui-handle-bg: $primary !default;
|
||||
$noui-handle-border: 0 !default;
|
||||
$noui-handle-border-radius: 100% !default;
|
||||
$noui-origin-border-radius: 2px !default;
|
||||
|
||||
@ -17,10 +17,10 @@ $table-head-font-weight: $font-weight-bold !default;
|
||||
$table-head-text-transform: uppercase !default;
|
||||
$table-head-letter-spacing: 1px !default;
|
||||
$table-body-font-size: 0.8125rem !default;
|
||||
$table-dark-bg: theme-color("default") !default;
|
||||
$table-dark-bg: $default !default;
|
||||
$table-dark-accent-bg: rgba($white, 0.05) !default;
|
||||
$table-dark-hover-bg: rgba($white, 0.075) !default;
|
||||
$table-dark-border-color: color.adjust(theme-color("default"), $lightness: 7%) !default;
|
||||
$table-dark-border-color: color.adjust($default, $lightness: 7%) !default;
|
||||
$table-dark-color: $body-bg !default;
|
||||
$table-dark-head-bg: color.adjust(theme-color("default"), $lightness: 4%) !default;
|
||||
$table-dark-head-color: color.adjust(theme-color("default"), $lightness: 35%) !default;
|
||||
$table-dark-head-bg: color.adjust($default, $lightness: 4%) !default;
|
||||
$table-dark-head-color: color.adjust($default, $lightness: 35%) !default;
|
||||
|
||||
@ -11,7 +11,7 @@ body {
|
||||
|
||||
.bg-gradient {
|
||||
background: rgb(4 112 6);
|
||||
background: linear-gradient(90deg, rgb(4 112 6 / 100%) 22%, rgb(197 141 56 / 100%) 98%);
|
||||
background: linear-gradient(90deg, rgb(4 112 6 / 100%) 22%, rgb(197 141 56 / 100%) 98%) !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@ -64,18 +64,18 @@ a:hover,
|
||||
}
|
||||
|
||||
.btn-gradido {
|
||||
display: inline-block;
|
||||
padding: 0.6em 3em;
|
||||
display: inline-block !important;
|
||||
padding: 0.6em 3em !important;
|
||||
letter-spacing: 0.05em;
|
||||
color: #fff;
|
||||
transition: all 0.5s ease;
|
||||
color: #fff !important;
|
||||
transition: all 0.5s ease !important;
|
||||
background: rgb(249 205 105);
|
||||
background: linear-gradient(135deg, rgb(249 205 105 / 100%) 2%, rgb(197 141 56 / 100%) 55%);
|
||||
box-shadow: rgb(0 0 0 / 40%) 0 30px 90px;
|
||||
border-radius: 26px;
|
||||
padding-right: 50px;
|
||||
padding-left: 50px;
|
||||
border-style: none;
|
||||
border-radius: 26px !important;
|
||||
padding-right: 50px !important;
|
||||
padding-left: 50px !important;
|
||||
border-style: none !important;
|
||||
}
|
||||
|
||||
.btn-gradido:hover {
|
||||
@ -88,17 +88,17 @@ a:hover,
|
||||
}
|
||||
|
||||
.btn-gradido-disable {
|
||||
padding: 0.6em 3em;
|
||||
padding: 0.6em 3em !important;
|
||||
letter-spacing: 0.05em;
|
||||
color: #fff;
|
||||
transition: all 0.5s ease;
|
||||
color: #fff !important;
|
||||
transition: all 0.5s ease !important;
|
||||
background: rgb(97 97 97);
|
||||
background: linear-gradient(135deg, rgb(180 180 180 / 100%) 46%, rgb(180 180 180 / 100%) 99%);
|
||||
box-shadow: rgb(0 0 0 / 40%) 0 30px 90px;
|
||||
border-radius: 26px;
|
||||
padding-right: 50px;
|
||||
padding-left: 50px;
|
||||
border-style: none;
|
||||
border-radius: 26px !important;
|
||||
padding-right: 50px !important;
|
||||
padding-left: 50px !important;
|
||||
border-style: none !important;
|
||||
}
|
||||
|
||||
.btn-gradido-disable:hover {
|
||||
@ -328,3 +328,8 @@ a:hover,
|
||||
box-shadow: 0 0 0 0 rgb(204 169 44 / 0%);
|
||||
}
|
||||
}
|
||||
|
||||
.transparent-button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@ -1,55 +1,60 @@
|
||||
// Bootstrap (4.5.3) functions
|
||||
|
||||
@import "~bootstrap/scss/functions";
|
||||
@import "custom/variables";
|
||||
@import "bootstrap/scss/functions";
|
||||
@import "bootstrap/scss/variables";
|
||||
|
||||
// @import "~bootstrap/scss/variables"; wird am
|
||||
// ende der custom/variables angehangen
|
||||
|
||||
// Bootstrap (4.5.3) mixins
|
||||
@import "~bootstrap/scss/mixins";
|
||||
@import "bootstrap/scss/maps";
|
||||
@import "bootstrap/scss/mixins";
|
||||
|
||||
// Bootstrap (4.5.3) components
|
||||
|
||||
@import "~bootstrap/scss/alert";
|
||||
@import "~bootstrap/scss/badge";
|
||||
@import "~bootstrap/scss/dropdown";
|
||||
@import "~bootstrap/scss/button-group";
|
||||
@import "~bootstrap/scss/buttons";
|
||||
@import "~bootstrap/scss/card";
|
||||
@import "~bootstrap/scss/carousel";
|
||||
@import "~bootstrap/scss/close";
|
||||
@import "~bootstrap/scss/code";
|
||||
@import "~bootstrap/scss/custom-forms";
|
||||
@import "bootstrap/scss/alert";
|
||||
@import "bootstrap/scss/badge";
|
||||
@import "bootstrap/scss/dropdown";
|
||||
@import "bootstrap/scss/button-group";
|
||||
@import "bootstrap/scss/buttons";
|
||||
@import "bootstrap/scss/card";
|
||||
@import "bootstrap/scss/carousel";
|
||||
@import "bootstrap/scss/close";
|
||||
|
||||
// @import "bootstrap/scss/code";
|
||||
// @import "bootstrap/scss/custom-forms";
|
||||
|
||||
// @import "~bootstrap/scss/dropdown";
|
||||
@import "~bootstrap/scss/forms";
|
||||
@import "bootstrap/scss/forms";
|
||||
|
||||
// @import "~bootstrap/scss/functions";
|
||||
@import "~bootstrap/scss/grid";
|
||||
@import "~bootstrap/scss/input-group";
|
||||
@import "~bootstrap/scss/list-group";
|
||||
@import "bootstrap/scss/grid";
|
||||
|
||||
// @import "bootstrap/scss/input-group";
|
||||
@import "bootstrap/scss/list-group";
|
||||
|
||||
// @import "~bootstrap/scss/mixins";
|
||||
@import "~bootstrap/scss/modal";
|
||||
@import "~bootstrap/scss/nav";
|
||||
@import "~bootstrap/scss/navbar";
|
||||
@import "~bootstrap/scss/pagination";
|
||||
@import "~bootstrap/scss/print";
|
||||
@import "~bootstrap/scss/progress";
|
||||
@import "~bootstrap/scss/reboot";
|
||||
@import "~bootstrap/scss/tables";
|
||||
@import "~bootstrap/scss/toasts";
|
||||
@import "~bootstrap/scss/tooltip";
|
||||
@import "~bootstrap/scss/transitions";
|
||||
@import "~bootstrap/scss/type";
|
||||
@import "~bootstrap/scss/utilities";
|
||||
@import "~bootstrap/scss/variables";
|
||||
@import "~bootstrap/scss/bootstrap-grid";
|
||||
@import "~bootstrap/scss/bootstrap-reboot";
|
||||
@import "~bootstrap/scss/bootstrap";
|
||||
@import "bootstrap/scss/modal";
|
||||
@import "bootstrap/scss/nav";
|
||||
@import "bootstrap/scss/navbar";
|
||||
@import "bootstrap/scss/pagination";
|
||||
|
||||
// @import "bootstrap/scss/print";
|
||||
@import "bootstrap/scss/progress";
|
||||
@import "bootstrap/scss/reboot";
|
||||
@import "bootstrap/scss/tables";
|
||||
@import "bootstrap/scss/toasts";
|
||||
@import "bootstrap/scss/tooltip";
|
||||
@import "bootstrap/scss/transitions";
|
||||
@import "bootstrap/scss/type";
|
||||
@import "bootstrap/scss/utilities";
|
||||
|
||||
// @import "bootstrap/scss/variables";
|
||||
@import "bootstrap/scss/bootstrap-grid";
|
||||
@import "bootstrap/scss/bootstrap-reboot";
|
||||
@import "bootstrap/scss/bootstrap";
|
||||
|
||||
// Bootstrap-vue (2.21.1) scss
|
||||
@import "~bootstrap-vue/src/index";
|
||||
@import "custom/variables";
|
||||
@import "gradido-template";
|
||||
@import "gradido-template-dark";
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-carousel :interval="13000">
|
||||
<b-carousel-slide img-src="/img/template/Foto_01_2400_small.jpg">
|
||||
<BCarousel :interval="13000" ride="carousel">
|
||||
<BCarouselSlide img-src="/img/template/Foto_01_2400_small.jpg">
|
||||
<div class="caption-first-text">{{ $t('auth.left.gratitude') }}</div>
|
||||
<div class="caption-second-text">{{ $t('auth.left.oneGratitude') }}</div>
|
||||
</b-carousel-slide>
|
||||
<b-carousel-slide img-src="/img/template/Foto_02_2400_small.jpg">
|
||||
</BCarouselSlide>
|
||||
<BCarouselSlide img-src="/img/template/Foto_02_2400_small.jpg">
|
||||
<div class="caption-first-text">{{ $t('auth.left.dignity') }}</div>
|
||||
<div class="caption-second-text">{{ $t('auth.left.oneDignity') }}</div>
|
||||
</b-carousel-slide>
|
||||
<b-carousel-slide img-src="/img/template/Foto_03_2400_small.jpg">
|
||||
</BCarouselSlide>
|
||||
<BCarouselSlide img-src="/img/template/Foto_03_2400_small.jpg">
|
||||
<div class="caption-first-text">{{ $t('auth.left.donation') }}</div>
|
||||
<div class="caption-second-text">{{ $t('auth.left.oneDonation') }}</div>
|
||||
</b-carousel-slide>
|
||||
</b-carousel>
|
||||
</BCarouselSlide>
|
||||
</BCarousel>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -27,7 +27,7 @@ export default {
|
||||
.carousel-caption {
|
||||
color: #fff;
|
||||
top: 317px;
|
||||
text-shadow: 2px 2px 8px #000000;
|
||||
text-shadow: 2px 2px 8px #000;
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
||||
@ -48,10 +48,7 @@ export default {
|
||||
.carousel-inner {
|
||||
height: 100%;
|
||||
border-radius: 0% 49% 49% 0% / 0% 51% 49% 0%;
|
||||
-webkit-border-radius: 0% 49% 49% 0% / 0% 51% 49% 0%;
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
transform: translate3d(0, 0, 0);
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,34 +1,37 @@
|
||||
<template>
|
||||
<footer class="footer">
|
||||
<b-row class="mt-lg-7 mt-md-6 mt-4">
|
||||
<b-col class="col-12 col-md-12 col-lg-6">
|
||||
<BRow class="mt-lg-7 mt-md-6 mt-4">
|
||||
<BCol class="col-12 col-md-12 col-lg-6">
|
||||
<div
|
||||
class="d-flex justify-content-center justify-content-md-center justify-content-lg-start ml-3"
|
||||
>
|
||||
<b-nav class="nav-footer">
|
||||
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
|
||||
<BNav class="nav-footer">
|
||||
<BNavItem :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
|
||||
{{ $t('footer.imprint') }}
|
||||
</b-nav-item>
|
||||
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
|
||||
</BNavItem>
|
||||
<BNavItem :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
|
||||
{{ $t('footer.privacy_policy') }}
|
||||
</b-nav-item>
|
||||
</b-nav>
|
||||
</BNavItem>
|
||||
</BNav>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col class="col-12 col-md-12 col-lg-6 mt-4 mb-4 mt-lg-0 mb-lg-0">
|
||||
</BCol>
|
||||
<BCol class="col-12 col-md-12 col-lg-6 mt-4 mb-4 mt-lg-0 mb-lg-0">
|
||||
<div class="text-center ml-3 ml-lg-0 text-lg-right pt-1">
|
||||
{{ $t('followUs') }}
|
||||
<b-link href="https://www.facebook.com/groups/Gradido/" target="_blank">
|
||||
<b-icon-facebook class="ml-3 mr-3 c-grey" font-scale="1"></b-icon-facebook>
|
||||
</b-link>
|
||||
<b-link href="https://twitter.com/gradido" target="_blank">
|
||||
<b-icon-twitter class="mr-3 c-grey" font-scale="1"></b-icon-twitter>
|
||||
</b-link>
|
||||
<b-link href="https://www.youtube.com/c/GradidoNet" target="_blank">
|
||||
<b-icon-youtube class="mr-3 c-grey" font-scale="1"></b-icon-youtube>
|
||||
</b-link>
|
||||
<BLink href="https://www.facebook.com/groups/Gradido/" target="_blank">
|
||||
<!-- <b-icon-facebook class="ml-3 mr-3 c-grey" font-scale="1"></b-icon-facebook>-->
|
||||
<IBiFacebook class="ml-3 mr-3 c-grey" />
|
||||
</BLink>
|
||||
<BLink href="https://twitter.com/gradido" target="_blank">
|
||||
<!-- <b-icon-twitter class="mr-3 c-grey" font-scale="1"></b-icon-twitter>-->
|
||||
<IBiTwitterX class="mr-3 c-grey" font-scale="1" />
|
||||
</BLink>
|
||||
<BLink href="https://www.youtube.com/c/GradidoNet" target="_blank">
|
||||
<!-- <b-icon-youtube class="mr-3 c-grey" font-scale="1"></b-icon-youtube>-->
|
||||
<IBiYoutube class="mr-3 c-grey" font-scale="1" />
|
||||
</BLink>
|
||||
|
||||
<b-link href="https://t.me/Gradido" target="_blank">
|
||||
<BLink href="https://t.me/Gradido" target="_blank">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
@ -41,10 +44,10 @@
|
||||
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133.958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.05-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.817-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.088.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.236.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.763.166-2.984 1.09z"
|
||||
/>
|
||||
</svg>
|
||||
</b-link>
|
||||
</BLink>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
|
||||
@ -1,60 +1,58 @@
|
||||
<template>
|
||||
<div class="auth-header position-sticky">
|
||||
<b-navbar :toggleable="false" class="pr-4">
|
||||
<b-navbar-brand class="d-none d-lg-block">
|
||||
<b-img
|
||||
class="position-absolute ml--3 mt-lg--2 mt-3 p-2 zindex1000"
|
||||
:src="logo"
|
||||
width="200"
|
||||
alt="Logo"
|
||||
/>
|
||||
<b-img
|
||||
class="mt--3 ml--3"
|
||||
:src="background_header"
|
||||
width="230"
|
||||
alt="Background Image"
|
||||
></b-img>
|
||||
</b-navbar-brand>
|
||||
<b-img class="sheet-img position-absolute d-block d-lg-none zindex1000" :src="sheet"></b-img>
|
||||
<b-collapse id="nav-collapse" is-nav class="ml-5">
|
||||
<b-navbar-nav class="ml-auto d-none d-lg-flex" right>
|
||||
<b-nav-item :to="register" class="authNavbar ml-lg-5">{{ $t('signup') }}</b-nav-item>
|
||||
<BNavbar :toggleable="false" :container="false" class="d-flex">
|
||||
<BNavbarBrand class="d-none d-lg-block">
|
||||
<BImg class="position-absolute ml--3 mt-lg--2 p-2" :src="logo" width="200" alt="Logo" />
|
||||
<BImg class="mt--3 ml--3" :src="backgroundHeader" width="230" alt="Background Image"></BImg>
|
||||
</BNavbarBrand>
|
||||
<BImg class="sheet-img position-absolute d-block d-lg-none zindex1000" :src="sheet"></BImg>
|
||||
<BCollapse id="nav-collapse" is-nav>
|
||||
<BNavbarNav class="ml-auto d-none d-lg-flex" right>
|
||||
<BNavItem :to="register()" class="auth-navbar ml-lg-5">{{ $t('signup') }}</BNavItem>
|
||||
<span class="d-none d-lg-block mt-1">{{ $t('math.pipe') }}</span>
|
||||
<b-nav-item :to="login" class="authNavbar">{{ $t('signin') }}</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-collapse>
|
||||
</b-navbar>
|
||||
<BNavItem :to="login()" class="auth-navbar">{{ $t('signin') }}</BNavItem>
|
||||
</BNavbarNav>
|
||||
</BCollapse>
|
||||
</BNavbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { authLinks } from '@/mixins/authLinks'
|
||||
<script setup>
|
||||
import { useAuthLinks } from '@/composables/useAuthLinks'
|
||||
|
||||
export default {
|
||||
name: 'AuthNavbar',
|
||||
mixins: [authLinks],
|
||||
data() {
|
||||
return {
|
||||
background_header: '/img/template/gradido_background_header.png',
|
||||
logo: '/img/brand/gradido-logo.png',
|
||||
sheet: '/img/template/Blaetter.png',
|
||||
}
|
||||
},
|
||||
}
|
||||
const { login, register } = useAuthLinks()
|
||||
|
||||
const backgroundHeader = '/img/template/gradido_background_header.png'
|
||||
const logo = '/img/brand/gradido-logo.png'
|
||||
const sheet = '/img/template/Blaetter.png'
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.authNavbar > .nav-link {
|
||||
<style scoped lang="scss">
|
||||
.auth-navbar {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
|
||||
> * {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.auth-navbar > :deep(.nav-link) {
|
||||
color: #0e79bc !important;
|
||||
}
|
||||
|
||||
.authNavbar > .router-link-exact-active {
|
||||
.auth-navbar > :deep(.router-link-exact-active) {
|
||||
color: #383838 !important;
|
||||
}
|
||||
|
||||
.auth-header {
|
||||
font-family: 'Open Sans', sans-serif !important;
|
||||
height: 150px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
:deep(#nav-collapse) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.sheet-img {
|
||||
@ -63,18 +61,19 @@ export default {
|
||||
max-width: 64%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
@media screen and (width <= 1024px) {
|
||||
.auth-header {
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
@media screen and (width <= 768px) {
|
||||
.auth-header {
|
||||
height: 70px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 450px) {
|
||||
|
||||
@media screen and (width <= 450px) {
|
||||
.sheet-img {
|
||||
top: -15px;
|
||||
right: 0%;
|
||||
|
||||
@ -1,26 +1,23 @@
|
||||
<template>
|
||||
<div class="navbar-small">
|
||||
<b-navbar class="navi">
|
||||
<b-navbar-nav>
|
||||
<b-nav-item :to="register" class="authNavbar">{{ $t('signup') }}</b-nav-item>
|
||||
<BNavbar class="navi">
|
||||
<BNavbarNav>
|
||||
<BNavItem :to="register()" class="auth-navbar">{{ $t('signup') }}</BNavItem>
|
||||
<span class="mt-1">{{ $t('math.pipe') }}</span>
|
||||
<b-nav-item :to="login" class="authNavbar">{{ $t('signin') }}</b-nav-item>
|
||||
</b-navbar-nav>
|
||||
</b-navbar>
|
||||
<BNavItem :to="login()" class="auth-navbar">{{ $t('signin') }}</BNavItem>
|
||||
</BNavbarNav>
|
||||
</BNavbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { authLinks } from '@/mixins/authLinks'
|
||||
<script setup>
|
||||
import { useAuthLinks } from '@/composables/useAuthLinks'
|
||||
|
||||
export default {
|
||||
name: 'AuthNavbarSmall',
|
||||
mixins: [authLinks],
|
||||
}
|
||||
const { login, register } = useAuthLinks()
|
||||
</script>
|
||||
<style scoped>
|
||||
.navi {
|
||||
margin-left: 0px;
|
||||
padding-left: 0px;
|
||||
margin-left: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -5,14 +5,15 @@
|
||||
<label>{{ $t('gdd_per_link.copy-link') }}</label>
|
||||
<div
|
||||
class="pointer text-center bg-secondary gradido-border-radius p-3"
|
||||
@click="copyLink"
|
||||
data-test="copyLink"
|
||||
@click="copyLink"
|
||||
>
|
||||
{{ link }}
|
||||
<div>
|
||||
<b-button class="p-4">
|
||||
<b-icon icon="link45deg"></b-icon>
|
||||
</b-button>
|
||||
<BButton class="p-4">
|
||||
<IBiLink45deg />
|
||||
<!-- <b-icon icon="link45deg"></b-icon>-->
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -25,9 +26,10 @@
|
||||
>
|
||||
{{ linkText }}
|
||||
<div>
|
||||
<b-button class="p-4">
|
||||
<b-icon icon="link45deg"></b-icon>
|
||||
</b-button>
|
||||
<BButton class="p-4">
|
||||
<IBiLink45deg />
|
||||
<!-- <b-icon icon="link45deg"></b-icon>-->
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -38,13 +40,19 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { copyLinks } from '../mixins/copyLinks'
|
||||
export default {
|
||||
name: 'ClipboardCopy',
|
||||
mixins: [copyLinks],
|
||||
}
|
||||
<script setup>
|
||||
import { useCopyLinks } from '@/composables/useCopyLinks'
|
||||
|
||||
const props = defineProps({
|
||||
link: { type: String, required: true },
|
||||
amount: { type: String, required: true },
|
||||
memo: { type: String, required: true },
|
||||
validUntil: { type: String, required: true },
|
||||
})
|
||||
|
||||
const { copyLink, copyLinkWithText, linkText, canCopyLink } = useCopyLinks({ ...props })
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.svg {
|
||||
filter: brightness(0) invert(1);
|
||||
|
||||
@ -1,92 +1,172 @@
|
||||
<template>
|
||||
<div class="community-switch">
|
||||
<div v-if="!validCommunityIdentifier">
|
||||
<b-dropdown no-flip :text="value.name">
|
||||
<b-dropdown-item
|
||||
<BDropdown no-flip :text="modelValue?.name">
|
||||
<BDropdownItem
|
||||
v-for="community in communities"
|
||||
@click.prevent="updateCommunity(community)"
|
||||
:key="community.id"
|
||||
:title="community.description"
|
||||
:active="value.uuid === community.uuid"
|
||||
:active="modelValue?.uuid === community.uuid"
|
||||
@click.prevent="updateCommunity(community)"
|
||||
>
|
||||
{{ community.name }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</BDropdownItem>
|
||||
</BDropdown>
|
||||
</div>
|
||||
<div v-else class="mb-4 mt-2">
|
||||
<b-row>
|
||||
<b-col class="font-weight-bold" :title="value.description">{{ value.name }}</b-col>
|
||||
</b-row>
|
||||
<BRow>
|
||||
<BCol class="font-weight-bold" :title="modelValue.description">{{ modelValue.name }}</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { selectCommunities } from '@/graphql/queries'
|
||||
<!--<script>-->
|
||||
<!--import { selectCommunities } from '@/graphql/queries'-->
|
||||
|
||||
export default {
|
||||
name: 'CommunitySwitch',
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
communities: [],
|
||||
validCommunityIdentifier: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateCommunity(community) {
|
||||
this.$emit('input', community)
|
||||
},
|
||||
setDefaultCommunity() {
|
||||
// when we already get an identifier via url we choose this if the community exist
|
||||
if (this.communityIdentifier && this.communities.length >= 1) {
|
||||
const foundCommunity = this.communities.find((community) => {
|
||||
if (
|
||||
community.uuid === this.communityIdentifier ||
|
||||
community.name === this.communityIdentifier
|
||||
) {
|
||||
this.validCommunityIdentifier = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
if (foundCommunity) {
|
||||
this.updateCommunity(foundCommunity)
|
||||
return
|
||||
}
|
||||
this.toastError('invalid community identifier in url')
|
||||
}
|
||||
if (this.validCommunityIdentifier && !this.communityIdentifier) {
|
||||
this.validCommunityIdentifier = false
|
||||
}
|
||||
// set default community, the only one which isn't foreign
|
||||
// we assume it is only one entry with foreign = false
|
||||
if (this.value.uuid === '' && this.communities.length) {
|
||||
const foundCommunity = this.communities.find((community) => !community.foreign)
|
||||
if (foundCommunity) {
|
||||
this.updateCommunity(foundCommunity)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
communities: {
|
||||
query: selectCommunities,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
communityIdentifier() {
|
||||
return this.$route.params && this.$route.params.communityIdentifier
|
||||
},
|
||||
},
|
||||
updated() {
|
||||
this.setDefaultCommunity()
|
||||
},
|
||||
mounted() {
|
||||
this.setDefaultCommunity()
|
||||
<!--export default {-->
|
||||
<!-- name: 'CommunitySwitch',-->
|
||||
<!-- props: {-->
|
||||
<!-- value: {-->
|
||||
<!-- type: Object,-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- communities: [],-->
|
||||
<!-- validCommunityIdentifier: false,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- updateCommunity(community) {-->
|
||||
<!-- this.$emit('input', community)-->
|
||||
<!-- },-->
|
||||
<!-- setDefaultCommunity() {-->
|
||||
<!-- // when we already get an identifier via url we choose this if the community exist-->
|
||||
<!-- if (this.communityIdentifier && this.communities.length >= 1) {-->
|
||||
<!-- const foundCommunity = this.communities.find((community) => {-->
|
||||
<!-- if (-->
|
||||
<!-- community.uuid === this.communityIdentifier ||-->
|
||||
<!-- community.name === this.communityIdentifier-->
|
||||
<!-- ) {-->
|
||||
<!-- this.validCommunityIdentifier = true-->
|
||||
<!-- return true-->
|
||||
<!-- }-->
|
||||
<!-- return false-->
|
||||
<!-- })-->
|
||||
<!-- if (foundCommunity) {-->
|
||||
<!-- this.updateCommunity(foundCommunity)-->
|
||||
<!-- return-->
|
||||
<!-- }-->
|
||||
<!-- this.toastError('invalid community identifier in url')-->
|
||||
<!-- }-->
|
||||
<!-- if (this.validCommunityIdentifier && !this.communityIdentifier) {-->
|
||||
<!-- this.validCommunityIdentifier = false-->
|
||||
<!-- }-->
|
||||
<!-- // set default community, the only one which isn't foreign-->
|
||||
<!-- // we assume it is only one entry with foreign = false-->
|
||||
<!-- if (this.value.uuid === '' && this.communities.length) {-->
|
||||
<!-- const foundCommunity = this.communities.find((community) => !community.foreign)-->
|
||||
<!-- if (foundCommunity) {-->
|
||||
<!-- this.updateCommunity(foundCommunity)-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- apollo: {-->
|
||||
<!-- communities: {-->
|
||||
<!-- query: selectCommunities,-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- communityIdentifier() {-->
|
||||
<!-- return this.$route.params && this.$route.params.communityIdentifier-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- updated() {-->
|
||||
<!-- this.setDefaultCommunity()-->
|
||||
<!-- },-->
|
||||
<!-- mounted() {-->
|
||||
<!-- this.setDefaultCommunity()-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted, onUpdated } from 'vue'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { selectCommunities } from '@/graphql/queries'
|
||||
import { useAppToast } from '@/composables/useToast'
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const route = useRoute()
|
||||
const { toastError } = useAppToast()
|
||||
|
||||
const communities = ref([])
|
||||
const validCommunityIdentifier = ref(false)
|
||||
|
||||
const { result } = useQuery(selectCommunities)
|
||||
|
||||
watch(result, (data) => {
|
||||
if (data) {
|
||||
communities.value = data.communities
|
||||
setDefaultCommunity()
|
||||
}
|
||||
})
|
||||
|
||||
const communityIdentifier = computed(() => route.params.communityIdentifier)
|
||||
|
||||
function updateCommunity(community) {
|
||||
emit('update:modelValue', community)
|
||||
}
|
||||
|
||||
function setDefaultCommunity() {
|
||||
if (communityIdentifier.value && communities.value.length >= 1) {
|
||||
const foundCommunity = communities.value.find((community) => {
|
||||
if (
|
||||
community.uuid === communityIdentifier.value ||
|
||||
community.name === communityIdentifier.value
|
||||
) {
|
||||
validCommunityIdentifier.value = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
if (foundCommunity) {
|
||||
updateCommunity(foundCommunity)
|
||||
return
|
||||
}
|
||||
toastError('invalid community identifier in url')
|
||||
}
|
||||
|
||||
if (validCommunityIdentifier.value && !communityIdentifier.value) {
|
||||
validCommunityIdentifier.value = false
|
||||
}
|
||||
|
||||
if (props.modelValue?.uuid === '' && communities.value.length) {
|
||||
const foundCommunity = communities.value.find((community) => !community.foreign)
|
||||
if (foundCommunity) {
|
||||
updateCommunity(foundCommunity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(setDefaultCommunity)
|
||||
onUpdated(setDefaultCommunity)
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.community-switch {
|
||||
:deep(button) {
|
||||
background-color: $secondary;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<footer class="footer m-4 p-4 bg-transparent">
|
||||
<b-row align-v="center" class="mt-4 justify-content-lg-between">
|
||||
<b-col>
|
||||
<BRow align-v="center" class="mt-4 justify-content-lg-between">
|
||||
<BCol>
|
||||
<div class="copyright text-center text-lg-center text-muted">
|
||||
{{ $t('footer.copyright.year', { year }) }}
|
||||
<a
|
||||
@ -23,18 +23,18 @@
|
||||
{{ $t('footer.short_hash', { shortHash }) }}
|
||||
</a>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row align-v="center" class="justify-content-lg-between">
|
||||
<b-col>
|
||||
<b-nav class="nav-footer justify-content-center">
|
||||
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow align-v="center" class="justify-content-lg-between">
|
||||
<BCol>
|
||||
<BNav class="nav-footer justify-content-center">
|
||||
<BNavItem :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
|
||||
{{ $t('footer.imprint') }}
|
||||
</b-nav-item>
|
||||
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
|
||||
</BNavItem>
|
||||
<BNavItem :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
|
||||
{{ $t('footer.privacy_policy') }}
|
||||
</b-nav-item>
|
||||
<b-nav-item
|
||||
</BNavItem>
|
||||
<BNavItem
|
||||
:href="
|
||||
$i18n.locale === 'de'
|
||||
? 'https://docs.google.com/document/d/1jZp-DiiMPI9ZPNXmjsvOQ1BtnfDFfx8BX7CDmA8KKjY/edit?usp=sharing'
|
||||
@ -43,13 +43,13 @@
|
||||
target="_blank"
|
||||
>
|
||||
{{ $t('footer.whitepaper') }}
|
||||
</b-nav-item>
|
||||
<b-nav-item :href="`mailto:${supportEmail}`" target="_blank">
|
||||
</BNavItem>
|
||||
<BNavItem :href="`mailto:${supportEmail}`" target="_blank">
|
||||
{{ $t('navigation.support') }}
|
||||
</b-nav-item>
|
||||
</b-nav>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BNavItem>
|
||||
</BNav>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</footer>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -2,77 +2,81 @@
|
||||
<div class="contribution-messages-formular">
|
||||
<small class="pl-2 pt-3">{{ $t('form.reply') }}</small>
|
||||
<div>
|
||||
<b-form @submit.prevent="onSubmit" @reset="onReset">
|
||||
<b-form-textarea
|
||||
<BForm @submit.prevent="onSubmit" @reset="onReset">
|
||||
<BFormTextarea
|
||||
id="textarea"
|
||||
v-model="form.text"
|
||||
:model-value="form.text"
|
||||
:placeholder="$t('form.memo')"
|
||||
rows="3"
|
||||
></b-form-textarea>
|
||||
<b-row class="mt-4 mb-4">
|
||||
<b-col>
|
||||
<b-button type="reset" variant="secondary">{{ $t('form.cancel') }}</b-button>
|
||||
</b-col>
|
||||
<b-col class="text-right">
|
||||
<b-button type="submit" variant="gradido" :disabled="disabled">
|
||||
@update:model-value="form.text = $event"
|
||||
></BFormTextarea>
|
||||
<BRow class="mt-4 mb-4">
|
||||
<BCol>
|
||||
<BButton type="reset" variant="secondary">{{ $t('form.cancel') }}</BButton>
|
||||
</BCol>
|
||||
<BCol class="text-right">
|
||||
<BButton type="submit" variant="gradido" :disabled="disabled">
|
||||
{{ $t('form.reply') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form>
|
||||
</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BForm>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { createContributionMessage } from '../../graphql/mutations.js'
|
||||
|
||||
export default {
|
||||
name: 'ContributionMessagesFormular',
|
||||
props: {
|
||||
contributionId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
text: '',
|
||||
},
|
||||
isSubmitting: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
this.isSubmitting = true
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: createContributionMessage,
|
||||
variables: {
|
||||
contributionId: this.contributionId,
|
||||
message: this.form.text,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
this.$emit('get-list-contribution-messages', false)
|
||||
this.$emit('update-status', this.contributionId)
|
||||
this.form.text = ''
|
||||
this.toastSuccess(this.$t('message.reply'))
|
||||
this.isSubmitting = false
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
this.isSubmitting = false
|
||||
})
|
||||
},
|
||||
onReset() {
|
||||
this.form.text = ''
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
disabled() {
|
||||
return this.form.text === '' || this.isSubmitting
|
||||
},
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { createContributionMessage } from '@/graphql/mutations.js'
|
||||
import { useAppToast } from '@/composables/useToast'
|
||||
|
||||
const props = defineProps({
|
||||
contributionId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['get-list-contribution-messages', 'update-status'])
|
||||
|
||||
const { t } = useI18n()
|
||||
const { toastSuccess, toastError } = useAppToast()
|
||||
|
||||
const { mutate: createContributionMessageMutation } = useMutation(createContributionMessage)
|
||||
|
||||
const form = ref({
|
||||
text: '',
|
||||
})
|
||||
|
||||
const isSubmitting = ref(false)
|
||||
|
||||
const disabled = computed(() => {
|
||||
return form.value.text === '' || isSubmitting.value
|
||||
})
|
||||
|
||||
async function onSubmit() {
|
||||
isSubmitting.value = true
|
||||
|
||||
try {
|
||||
await createContributionMessageMutation({
|
||||
contributionId: props.contributionId,
|
||||
message: form.value.text,
|
||||
})
|
||||
|
||||
emit('get-list-contribution-messages', false)
|
||||
emit('update-status', props.contributionId)
|
||||
form.value.text = ''
|
||||
toastSuccess(t('message.reply'))
|
||||
} catch (error) {
|
||||
toastError(error.message)
|
||||
} finally {
|
||||
isSubmitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function onReset() {
|
||||
form.value.text = ''
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
<template>
|
||||
<div class="contribution-messages-list">
|
||||
<div>
|
||||
<div v-for="message in messages" v-bind:key="message.id" class="mt-3">
|
||||
<div v-for="message in messages" :key="message.id" class="mt-3">
|
||||
<contribution-messages-list-item :message="message" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<contribution-messages-formular
|
||||
v-if="['PENDING', 'IN_PROGRESS'].includes(status)"
|
||||
:contributionId="contributionId"
|
||||
v-on="$listeners"
|
||||
:contribution-id="contributionId"
|
||||
v-bind="$attrs"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-b-toggle="'collapse' + String(contributionId)" class="text-center pointer clearboth">
|
||||
<b-button variant="outline-primary" block class="mb-3">
|
||||
<b-icon icon="arrow-up-short"></b-icon>
|
||||
<BButton variant="outline-primary" block class="mb-3">
|
||||
<IBiArrowUpShort />
|
||||
{{ $t('form.close') }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,43 +1,43 @@
|
||||
<template>
|
||||
<div class="contribution-messages-list-item">
|
||||
<div v-if="message.type === 'HISTORY'">
|
||||
<b-row class="mb-3 border border-197 p-1">
|
||||
<b-col cols="10">
|
||||
<BRow class="mb-3 border border-197 p-1">
|
||||
<BCol cols="10">
|
||||
<small>{{ $d(new Date(message.createdAt), 'short') }}</small>
|
||||
<div class="font-weight-bold" data-test="username" v-if="isNotModerator">
|
||||
<div v-if="isNotModerator" class="font-weight-bold" data-test="username">
|
||||
{{ storeName.username }} {{ $t('contribution.isEdited') }}
|
||||
</div>
|
||||
<div class="font-weight-bold" data-test="moderator-name" v-else>
|
||||
<div v-else class="font-weight-bold" data-test="moderator-name">
|
||||
{{ $t('community.moderator') }} {{ $t('contribution.isEdited') }}
|
||||
</div>
|
||||
<div class="small">
|
||||
{{ $t('contribution.oldContribution') }}
|
||||
</div>
|
||||
<parse-message v-bind="message" data-test="message" class="p-2"></parse-message>
|
||||
</b-col>
|
||||
<b-col cols="2">
|
||||
</BCol>
|
||||
<BCol cols="2">
|
||||
<avatar :username="storeName.username" :initials="storeName.initials"></avatar>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
<div v-else-if="isNotModerator" class="text-right pr-4 pr-lg-0 is-not-moderator">
|
||||
<b-row class="mb-3">
|
||||
<b-col cols="10">
|
||||
<BRow class="mb-3">
|
||||
<BCol cols="10">
|
||||
<div class="font-weight-bold" data-test="username">{{ storeName.username }}</div>
|
||||
<div class="small" data-test="date">{{ $d(new Date(message.createdAt), 'short') }}</div>
|
||||
<parse-message v-bind="message" data-test="message"></parse-message>
|
||||
</b-col>
|
||||
<b-col cols="2">
|
||||
</BCol>
|
||||
<BCol cols="2">
|
||||
<avatar :username="storeName.username" :initials="storeName.initials"></avatar>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
<div v-else>
|
||||
<b-row class="mb-3 bg-f5 p-2 is-moderator">
|
||||
<b-col cols="2">
|
||||
<BRow class="mb-3 bg-f5 p-2 is-moderator">
|
||||
<BCol cols="2">
|
||||
<avatar :username="moderationName.username" :initials="moderationName.initials"></avatar>
|
||||
</b-col>
|
||||
<b-col cols="10">
|
||||
</BCol>
|
||||
<BCol cols="10">
|
||||
<div class="font-weight-bold">
|
||||
<span data-test="username">{{ moderationName.username }}</span>
|
||||
<span class="ml-2 text-success small" data-test="moderator">
|
||||
@ -47,8 +47,8 @@
|
||||
|
||||
<div class="small" data-test="date">{{ $d(new Date(message.createdAt), 'short') }}</div>
|
||||
<parse-message v-bind="message" data-test="message"></parse-message>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<div class="mt-1">
|
||||
<span v-for="({ type, text }, index) in parsedMessage" :key="index">
|
||||
<b-link v-if="type === 'link'" :href="text" target="_blank">{{ text }}</b-link>
|
||||
<span v-else-if="type === 'date'">
|
||||
<span v-for="({ type: messageType, text }, index) in parsedMessage" :key="index">
|
||||
<b-link v-if="messageType === 'link'" :href="text" target="_blank">{{ text }}</b-link>
|
||||
<span v-else-if="messageType === 'date'">
|
||||
{{ $d(new Date(text), 'short') }}
|
||||
<br />
|
||||
</span>
|
||||
<span v-else-if="type === 'amount'">
|
||||
<span v-else-if="messageType === 'amount'">
|
||||
<br />
|
||||
{{ text | GDD }}
|
||||
{{ $filters.GDD(text) }}
|
||||
</span>
|
||||
<span v-else>{{ text }}</span>
|
||||
</span>
|
||||
@ -16,7 +16,8 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const LINK_REGEX_PATTERN = /(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*))/i
|
||||
const LINK_REGEX_PATTERN =
|
||||
/(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*))/i
|
||||
|
||||
export default {
|
||||
name: 'ParseMessage',
|
||||
@ -27,7 +28,7 @@ export default {
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
reuired: true,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
@ -1,26 +1,29 @@
|
||||
<template>
|
||||
<div class="contribution-form">
|
||||
<b-form
|
||||
<BForm
|
||||
ref="form"
|
||||
class="form-style p-3 bg-white app-box-shadow gradido-border-radius"
|
||||
@submit.prevent="submit"
|
||||
class="form-style p-3 bg-white appBoxShadow gradido-border-radius"
|
||||
>
|
||||
<label>{{ $t('contribution.selectDate') }}</label>
|
||||
<b-form-datepicker
|
||||
<BFormInput
|
||||
id="contribution-date"
|
||||
v-model="form.date"
|
||||
:model-value="date"
|
||||
:state="dataFieldMeta.valid"
|
||||
:locale="$i18n.locale"
|
||||
:max="maximalDate"
|
||||
:max="getMaximalDate"
|
||||
:min="minimalDate"
|
||||
class="mb-4 bg-248"
|
||||
reset-value=""
|
||||
:label-no-date-selected="$t('contribution.noDateSelected')"
|
||||
required
|
||||
:no-flip="true"
|
||||
type="date"
|
||||
@update:model-value="date = $event"
|
||||
>
|
||||
<template #nav-prev-year><span></span></template>
|
||||
<template #nav-next-year><span></span></template>
|
||||
</b-form-datepicker>
|
||||
</BFormInput>
|
||||
|
||||
<div v-if="showMessage" class="p-3" data-test="contribtion-message">
|
||||
{{ noOpenCreation }}
|
||||
@ -28,50 +31,46 @@
|
||||
<div v-else>
|
||||
<input-textarea
|
||||
id="contribution-memo"
|
||||
v-model="form.memo"
|
||||
:name="$t('form.message')"
|
||||
name="memo"
|
||||
:label="$t('contribution.activity')"
|
||||
:placeholder="$t('contribution.yourActivity')"
|
||||
:rules="{ required: true, min: 5, max: 255 }"
|
||||
/>
|
||||
<input-hour
|
||||
v-model="form.hours"
|
||||
:name="$t('form.hours')"
|
||||
name="hours"
|
||||
:label="$t('form.hours')"
|
||||
placeholder="0.25"
|
||||
:rules="{
|
||||
required: true,
|
||||
min: 0.25,
|
||||
max: validMaxTime,
|
||||
gddCreationTime: [0.25, validMaxTime],
|
||||
gddCreationTime: { min: 0.25, max: validMaxTime },
|
||||
}"
|
||||
:validMaxTime="validMaxTime"
|
||||
@updateAmount="updateAmount"
|
||||
></input-hour>
|
||||
:valid-max-time="validMaxTime"
|
||||
/>
|
||||
<input-amount
|
||||
id="contribution-amount"
|
||||
v-model="form.amount"
|
||||
:name="$t('form.amount')"
|
||||
name="amount"
|
||||
:label="$t('form.amount')"
|
||||
placeholder="20"
|
||||
:rules="{ required: true, gddSendAmount: [20, validMaxGDD] }"
|
||||
:rules="{ required: true, gddSendAmount: { min: 20, max: validMaxGDD } }"
|
||||
typ="ContributionForm"
|
||||
></input-amount>
|
||||
/>
|
||||
|
||||
<b-row class="mt-5">
|
||||
<b-col cols="12" lg="6">
|
||||
<b-button
|
||||
<BRow class="mt-5">
|
||||
<BCol cols="12" lg="6">
|
||||
<BButton
|
||||
block
|
||||
type="reset"
|
||||
variant="secondary"
|
||||
@click="reset"
|
||||
data-test="button-cancel"
|
||||
@click="fullFormReset"
|
||||
>
|
||||
{{ $t('form.cancel') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col cols="12" lg="6" class="text-right mt-4 mt-lg-0">
|
||||
<b-button
|
||||
</BButton>
|
||||
</BCol>
|
||||
<BCol cols="12" lg="6" class="text-right mt-4 mt-lg-0">
|
||||
<BButton
|
||||
block
|
||||
type="submit"
|
||||
variant="gradido"
|
||||
@ -79,109 +78,137 @@
|
||||
data-test="button-submit"
|
||||
>
|
||||
{{ form.id ? $t('form.change') : $t('contribution.submit') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</b-form>
|
||||
</BForm>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import InputHour from '@/components/Inputs/InputHour'
|
||||
import InputAmount from '@/components/Inputs/InputAmount'
|
||||
import InputTextarea from '@/components/Inputs/InputTextarea'
|
||||
import { useField, useForm } from 'vee-validate'
|
||||
|
||||
export default {
|
||||
name: 'ContributionForm',
|
||||
components: {
|
||||
InputHour,
|
||||
InputAmount,
|
||||
InputTextarea,
|
||||
const props = defineProps({
|
||||
modelValue: { type: Object, required: true },
|
||||
isThisMonth: { type: Boolean, required: true },
|
||||
minimalDate: { type: Date, required: true },
|
||||
maxGddLastMonth: { type: Number, required: true },
|
||||
maxGddThisMonth: { type: Number, required: true },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update-contribution', 'set-contribution'])
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const form = ref({ ...props.modelValue })
|
||||
|
||||
const {
|
||||
values: formValues,
|
||||
meta: formMeta,
|
||||
resetForm,
|
||||
defineField,
|
||||
setFieldValue,
|
||||
} = useForm({
|
||||
initialValues: {
|
||||
date: props.modelValue.date,
|
||||
memo: props.modelValue.memo,
|
||||
hours: props.modelValue.hours,
|
||||
amount: props.modelValue.amount,
|
||||
},
|
||||
props: {
|
||||
value: { type: Object, required: true },
|
||||
isThisMonth: { type: Boolean, required: true },
|
||||
minimalDate: { type: Date, required: true },
|
||||
maxGddLastMonth: { type: Number, required: true },
|
||||
maxGddThisMonth: { type: Number, required: true },
|
||||
})
|
||||
|
||||
const [date, dateProps] = defineField('date')
|
||||
|
||||
const { meta: dataFieldMeta } = useField('date', 'required')
|
||||
|
||||
const showMessage = computed(() => {
|
||||
if (props.maxGddThisMonth <= 0 && props.maxGddLastMonth <= 0) return true
|
||||
if (props.modelValue.date)
|
||||
return (
|
||||
(props.isThisMonth && props.maxGddThisMonth <= 0) ||
|
||||
(!props.isThisMonth && props.maxGddLastMonth <= 0)
|
||||
)
|
||||
return false
|
||||
})
|
||||
|
||||
const disabled = computed(() => {
|
||||
return (
|
||||
!formMeta.value.valid ||
|
||||
(props.isThisMonth && parseInt(form.value.amount) > parseInt(props.maxGddThisMonth)) ||
|
||||
(!props.isThisMonth && parseInt(form.value.amount) > parseInt(props.maxGddLastMonth))
|
||||
)
|
||||
})
|
||||
|
||||
const validMaxGDD = computed(() => {
|
||||
return Number(props.isThisMonth ? props.maxGddThisMonth : props.maxGddLastMonth)
|
||||
})
|
||||
|
||||
const validMaxTime = computed(() => {
|
||||
return Number(validMaxGDD.value / 20)
|
||||
})
|
||||
|
||||
const noOpenCreation = computed(() => {
|
||||
if (props.maxGddThisMonth <= 0 && props.maxGddLastMonth <= 0) {
|
||||
return t('contribution.noOpenCreation.allMonth')
|
||||
}
|
||||
if (props.isThisMonth && props.maxGddThisMonth <= 0) {
|
||||
return t('contribution.noOpenCreation.thisMonth')
|
||||
}
|
||||
if (!props.isThisMonth && props.maxGddLastMonth <= 0) {
|
||||
return t('contribution.noOpenCreation.lastMonth')
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
const getMaximalDate = computed(() => {
|
||||
return new Date().toISOString().slice(0, 10)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => formValues.hours,
|
||||
() => {
|
||||
updateAmount(formValues.hours)
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
minlength: 5,
|
||||
maxlength: 255,
|
||||
maximalDate: new Date(),
|
||||
form: this.value, // includes 'id' and time
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateAmount(hours) {
|
||||
this.form.amount = (hours * 20).toFixed(2).toString()
|
||||
)
|
||||
|
||||
function updateAmount(hours) {
|
||||
setFieldValue('amount', (hours * 20).toFixed(2).toString())
|
||||
}
|
||||
|
||||
function submit() {
|
||||
const dataToSave = { ...formValues }
|
||||
let emitOption = 'set-contribution'
|
||||
if (props.modelValue.id) {
|
||||
dataToSave.id = props.modelValue.id
|
||||
emitOption = 'update-contribution'
|
||||
}
|
||||
emit(emitOption, dataToSave)
|
||||
fullFormReset()
|
||||
}
|
||||
|
||||
function fullFormReset() {
|
||||
resetForm({
|
||||
values: {
|
||||
id: null,
|
||||
date: '',
|
||||
memo: '',
|
||||
hours: 0,
|
||||
amount: '',
|
||||
},
|
||||
submit() {
|
||||
this.$emit(this.form.id ? 'update-contribution' : 'set-contribution', { ...this.form })
|
||||
this.reset()
|
||||
},
|
||||
reset() {
|
||||
this.$refs.form.reset()
|
||||
this.form.id = null
|
||||
this.form.date = ''
|
||||
this.form.memo = ''
|
||||
this.form.hours = 0
|
||||
this.form.amount = ''
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
showMessage() {
|
||||
if (this.maxGddThisMonth <= 0 && this.maxGddLastMonth <= 0) return true
|
||||
if (this.form.date)
|
||||
return (
|
||||
(this.isThisMonth && this.maxGddThisMonth <= 0) ||
|
||||
(!this.isThisMonth && this.maxGddLastMonth <= 0)
|
||||
)
|
||||
return false
|
||||
},
|
||||
disabled() {
|
||||
return (
|
||||
this.form.date === '' ||
|
||||
this.form.memo.length < this.minlength ||
|
||||
this.form.memo.length > this.maxlength ||
|
||||
this.form.amount === '' ||
|
||||
parseInt(this.form.amount) <= 0 ||
|
||||
parseInt(this.form.amount) > 1000 ||
|
||||
(this.isThisMonth && parseInt(this.form.amount) > parseInt(this.maxGddThisMonth)) ||
|
||||
(!this.isThisMonth && parseInt(this.form.amount) > parseInt(this.maxGddLastMonth))
|
||||
)
|
||||
},
|
||||
validMaxGDD() {
|
||||
return Number(this.isThisMonth ? this.maxGddThisMonth : this.maxGddLastMonth)
|
||||
},
|
||||
validMaxTime() {
|
||||
return Number(this.validMaxGDD / 20)
|
||||
},
|
||||
noOpenCreation() {
|
||||
if (this.maxGddThisMonth <= 0 && this.maxGddLastMonth <= 0) {
|
||||
return this.$t('contribution.noOpenCreation.allMonth')
|
||||
}
|
||||
if (this.isThisMonth && this.maxGddThisMonth <= 0) {
|
||||
return this.$t('contribution.noOpenCreation.thisMonth')
|
||||
}
|
||||
if (!this.isThisMonth && this.maxGddLastMonth <= 0) {
|
||||
return this.$t('contribution.noOpenCreation.lastMonth')
|
||||
}
|
||||
return ''
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
return (this.form = this.value)
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.form-style {
|
||||
min-height: 410px;
|
||||
}
|
||||
|
||||
span.errors {
|
||||
color: red;
|
||||
}
|
||||
|
||||
@ -31,8 +31,7 @@ describe('ContributionList', () => {
|
||||
{
|
||||
id: 2,
|
||||
date: '05/04/2022',
|
||||
memo:
|
||||
'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.',
|
||||
memo: 'Ich habe 50 Stunden den Nachbarkindern bei ihren Hausaufgaben geholfen und Nachhilfeunterricht gegeben.',
|
||||
amount: '1000',
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,40 +1,40 @@
|
||||
<template>
|
||||
<div class="contribution-list">
|
||||
<div class="mb-3" v-for="item in items" :key="item.id + 'a'">
|
||||
<div v-for="item in items" :key="item.id + 'a'" class="mb-3">
|
||||
<contribution-list-item
|
||||
v-if="item.status === 'IN_PROGRESS'"
|
||||
v-bind="item"
|
||||
@closeAllOpenCollapse="$emit('closeAllOpenCollapse')"
|
||||
:contributionId="item.id"
|
||||
:allContribution="allContribution"
|
||||
:contribution-id="item.id"
|
||||
:all-contribution="allContribution"
|
||||
@close-all-open-collapse="$emit('close-all-open-collapse')"
|
||||
@update-contribution-form="updateContributionForm"
|
||||
@delete-contribution="deleteContribution"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3" v-for="item2 in items" :key="item2.id">
|
||||
<div v-for="item2 in items" :key="item2.id" class="mb-3">
|
||||
<contribution-list-item
|
||||
v-if="item2.status !== 'IN_PROGRESS'"
|
||||
v-bind="item2"
|
||||
@closeAllOpenCollapse="$emit('closeAllOpenCollapse')"
|
||||
:contributionId="item2.id"
|
||||
:allContribution="allContribution"
|
||||
:contribution-id="item2.id"
|
||||
:all-contribution="allContribution"
|
||||
@close-all-open-collapse="$emit('close-all-open-collapse')"
|
||||
@update-contribution-form="updateContributionForm"
|
||||
@delete-contribution="deleteContribution"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</div>
|
||||
<b-pagination
|
||||
<BPagination
|
||||
v-if="isPaginationVisible"
|
||||
v-model="currentPage"
|
||||
class="mt-3"
|
||||
pills
|
||||
size="lg"
|
||||
v-model="currentPage"
|
||||
:per-page="pageSize"
|
||||
:total-rows="contributionCount"
|
||||
align="center"
|
||||
:hide-ellipsis="true"
|
||||
></b-pagination>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -71,6 +71,16 @@ export default {
|
||||
messages: [],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isPaginationVisible() {
|
||||
return this.showPagination && this.pageSize < this.contributionCount
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
currentPage() {
|
||||
this.updateListContributions()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateListContributions() {
|
||||
this.$emit('update-list-contributions', {
|
||||
@ -89,15 +99,5 @@ export default {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isPaginationVisible() {
|
||||
return this.showPagination && this.pageSize < this.contributionCount
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
currentPage() {
|
||||
this.updateListContributions()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="contribution-list-item bg-white appBoxShadow gradido-border-radius pt-3 px-3"
|
||||
class="contribution-list-item bg-white app-box-shadow gradido-border-radius pt-3 px-3"
|
||||
:class="status === 'IN_PROGRESS' && !allContribution ? 'pulse border border-205' : ''"
|
||||
>
|
||||
<b-row>
|
||||
<b-col cols="3" lg="2" md="2">
|
||||
<BRow>
|
||||
<BCol cols="3" lg="2" md="2">
|
||||
<avatar
|
||||
v-if="firstName"
|
||||
:username="username.username"
|
||||
@ -13,19 +13,30 @@
|
||||
color="#fff"
|
||||
class="font-weight-bold"
|
||||
></avatar>
|
||||
<b-avatar v-else :icon="icon" :variant="variant" size="3em"></b-avatar>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<BAvatar v-else rounded="lg" :variant="variant" size="4em">
|
||||
<IBiTrash v-if="deletedAt" />
|
||||
<IBiXCircle v-else-if="deniedAt" />
|
||||
<IBiCheck v-else-if="confirmedAt" />
|
||||
<IBiQuestion v-else-if="status === 'IN_PROGRESS'" />
|
||||
<IBiBellFill v-else style="width: 36px; height: 36px" />
|
||||
</BAvatar>
|
||||
</BCol>
|
||||
<BCol>
|
||||
<div v-if="firstName" class="mr-3 font-weight-bold">
|
||||
{{ firstName }} {{ lastName }}
|
||||
<b-icon :icon="icon" :variant="variant"></b-icon>
|
||||
<IBiTrash v-if="deletedAt" />
|
||||
<IBiXCircle v-else-if="deniedAt" />
|
||||
<IBiCheck v-else-if="confirmedAt" />
|
||||
<IBiQuestion v-else-if="status === 'IN_PROGRESS'" />
|
||||
<IBiBellFill v-else />
|
||||
<!-- <b-icon :icon="icon" :variant="variant"></b-icon>-->
|
||||
</div>
|
||||
<div class="small">
|
||||
{{ $d(new Date(contributionDate), 'short') }}
|
||||
</div>
|
||||
<div class="mt-3 font-weight-bold">{{ $t('contributionText') }}</div>
|
||||
<div class="mb-3 text-break word-break">{{ memo }}</div>
|
||||
<div class="mt-2 mb-2 small" v-if="updatedBy > 0">
|
||||
<div v-if="updatedBy > 0" class="mt-2 mb-2 small">
|
||||
{{ $t('moderatorChangedMemo') }}
|
||||
</div>
|
||||
<div
|
||||
@ -35,42 +46,43 @@
|
||||
>
|
||||
{{ $t('contribution.alert.answerQuestion') }}
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="9" lg="3" offset="3" offset-md="0" offset-lg="0">
|
||||
</BCol>
|
||||
<BCol cols="9" lg="3" offset="3" offset-md="0" offset-lg="0">
|
||||
<div class="small">
|
||||
{{ $t('creation') }} {{ $t('(') }}{{ amount / 20 }} {{ $t('h') }}{{ $t(')') }}
|
||||
</div>
|
||||
<div v-if="status === 'DENIED' && allContribution" class="font-weight-bold">
|
||||
<b-icon icon="x-circle" variant="danger"></b-icon>
|
||||
<!-- <b-icon icon="x-circle" variant="danger"></b-icon>-->
|
||||
<IBiXCircle />
|
||||
{{ $t('contribution.alert.denied') }}
|
||||
</div>
|
||||
<div v-if="status === 'DELETED'" class="small">
|
||||
{{ $t('contribution.deleted') }}
|
||||
</div>
|
||||
<div v-else class="font-weight-bold">{{ amount | GDD }}</div>
|
||||
</b-col>
|
||||
<b-col cols="12" md="1" lg="1" class="text-right align-items-center">
|
||||
<div v-else class="font-weight-bold">{{ $filters.GDD(amount) }}</div>
|
||||
</BCol>
|
||||
<BCol cols="12" md="1" lg="1" class="text-right align-items-center">
|
||||
<div v-if="messagesCount > 0 && !moderatorId" @click="visible = !visible">
|
||||
<collapse-icon class="text-right" :visible="visible" />
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow
|
||||
v-if="(!['CONFIRMED', 'DELETED'].includes(status) && !allContribution) || messagesCount > 0"
|
||||
class="p-2"
|
||||
>
|
||||
<b-col cols="3" class="mr-auto text-center">
|
||||
<BCol cols="3" class="mr-auto text-center">
|
||||
<div
|
||||
v-if="!['CONFIRMED', 'DELETED'].includes(status) && !allContribution && !moderatorId"
|
||||
class="test-delete-contribution pointer mr-3"
|
||||
@click="deleteContribution({ id })"
|
||||
>
|
||||
<b-icon icon="trash"></b-icon>
|
||||
<IBiTrash />
|
||||
|
||||
<div>{{ $t('delete') }}</div>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="3" class="text-center">
|
||||
</BCol>
|
||||
<BCol cols="3" class="text-center">
|
||||
<div
|
||||
v-if="!['CONFIRMED', 'DELETED'].includes(status) && !allContribution && !moderatorId"
|
||||
class="test-edit-contribution pointer mr-3"
|
||||
@ -83,183 +95,187 @@
|
||||
})
|
||||
"
|
||||
>
|
||||
<b-icon icon="pencil"></b-icon>
|
||||
<IBiPencil />
|
||||
<div>{{ $t('edit') }}</div>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="6" class="text-center">
|
||||
</BCol>
|
||||
<BCol cols="6" class="text-center">
|
||||
<div v-if="messagesCount > 0 && !moderatorId" class="pointer" @click="visible = !visible">
|
||||
<b-icon icon="chat-dots"></b-icon>
|
||||
<IBiChatDots />
|
||||
<div>{{ $t('moderatorChat') }}</div>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<div v-else class="pb-3"></div>
|
||||
<b-collapse :id="collapsId" class="mt-2" v-model="visible">
|
||||
<BCollapse :id="collapseId" :model-value="visible" class="mt-2">
|
||||
<contribution-messages-list
|
||||
:messages="messages_get"
|
||||
:messages="messagesGet"
|
||||
:status="status"
|
||||
:contributionId="contributionId"
|
||||
:contribution-id="contributionId"
|
||||
@get-list-contribution-messages="getListContributionMessages"
|
||||
@update-status="updateStatus"
|
||||
/>
|
||||
</b-collapse>
|
||||
</BCollapse>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import Avatar from 'vue-avatar'
|
||||
import CollapseIcon from '../TransactionRows/CollapseIcon'
|
||||
import ContributionMessagesList from '@/components/ContributionMessages/ContributionMessagesList'
|
||||
import { listContributionMessages } from '../../graphql/queries.js'
|
||||
import { listContributionMessages } from '@/graphql/queries'
|
||||
import { useAppToast } from '@/composables/useToast'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
|
||||
export default {
|
||||
name: 'ContributionListItem',
|
||||
components: {
|
||||
Avatar,
|
||||
CollapseIcon,
|
||||
ContributionMessagesList,
|
||||
const props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
type: Number,
|
||||
},
|
||||
amount: {
|
||||
type: String,
|
||||
},
|
||||
memo: {
|
||||
type: String,
|
||||
},
|
||||
firstName: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
lastName: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
createdAt: {
|
||||
type: String,
|
||||
},
|
||||
contributionDate: {
|
||||
type: String,
|
||||
},
|
||||
deletedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
confirmedBy: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
confirmedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
deniedBy: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
deniedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
updatedBy: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
messagesCount: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
contributionId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
allContribution: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
moderatorId: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
amount: {
|
||||
type: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inProcess: true,
|
||||
messages_get: [],
|
||||
visible: false,
|
||||
memo: {
|
||||
type: String,
|
||||
},
|
||||
firstName: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
lastName: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
createdAt: {
|
||||
type: String,
|
||||
},
|
||||
contributionDate: {
|
||||
type: String,
|
||||
},
|
||||
deletedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
confirmedBy: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
confirmedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
deniedBy: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
deniedAt: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
updatedBy: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
messagesCount: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
contributionId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
allContribution: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
moderatorId: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
})
|
||||
|
||||
const { toastError, toastSuccess } = useAppToast()
|
||||
const { t } = useI18n()
|
||||
|
||||
const inProcess = ref(true)
|
||||
const messagesGet = ref([])
|
||||
const visible = ref(false)
|
||||
|
||||
const variant = computed(() => {
|
||||
if (props.deletedAt) return 'danger'
|
||||
if (props.deniedAt) return 'warning'
|
||||
if (props.confirmedAt) return 'success'
|
||||
if (props.status === 'IN_PROGRESS') return '205'
|
||||
return 'primary'
|
||||
})
|
||||
|
||||
const date = computed(() => props.createdAt)
|
||||
|
||||
const collapseId = computed(() => 'collapse' + String(props.id))
|
||||
|
||||
const username = computed(() => ({
|
||||
username: `${props.firstName} ${props.lastName}`,
|
||||
initials: `${props.firstName[0]}${props.lastName[0]}`,
|
||||
}))
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
() => {
|
||||
if (visible.value) getListContributionMessages()
|
||||
},
|
||||
)
|
||||
|
||||
function deleteContribution(item) {
|
||||
if (window.confirm(t('contribution.delete'))) {
|
||||
emit('delete-contribution', item)
|
||||
}
|
||||
}
|
||||
|
||||
const { onResult, result, loading, error, refetch } = useQuery(listContributionMessages, {
|
||||
contributionId: props.contributionId,
|
||||
})
|
||||
|
||||
function getListContributionMessages(closeCollapse = true) {
|
||||
if (closeCollapse) {
|
||||
emit('close-all-open-collapse')
|
||||
}
|
||||
refetch({
|
||||
contributionId: props.contributionId,
|
||||
}).catch((err) => {
|
||||
toastError(err.message)
|
||||
})
|
||||
}
|
||||
|
||||
onResult((resultValue) => {
|
||||
if (resultValue.data) {
|
||||
messagesGet.value.length = 0
|
||||
resultValue.data.listContributionMessages.messages.forEach((message) => {
|
||||
messagesGet.value.push(message)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
watch(
|
||||
() => visible.value,
|
||||
() => {
|
||||
if (visible.value) {
|
||||
getListContributionMessages()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
icon() {
|
||||
if (this.deletedAt) return 'trash'
|
||||
if (this.deniedAt) return 'x-circle'
|
||||
if (this.confirmedAt) return 'check'
|
||||
if (this.status === 'IN_PROGRESS') return 'question'
|
||||
return 'bell-fill'
|
||||
},
|
||||
variant() {
|
||||
if (this.deletedAt) return 'danger'
|
||||
if (this.deniedAt) return 'warning'
|
||||
if (this.confirmedAt) return 'success'
|
||||
if (this.status === 'IN_PROGRESS') return '205'
|
||||
return 'primary'
|
||||
},
|
||||
date() {
|
||||
return this.createdAt
|
||||
},
|
||||
collapsId() {
|
||||
return 'collapse' + String(this.id)
|
||||
},
|
||||
username() {
|
||||
return {
|
||||
username: `${this.firstName} ${this.lastName}`,
|
||||
initials: `${this.firstName[0]}${this.lastName[0]}`,
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
deleteContribution(item) {
|
||||
this.$bvModal.msgBoxConfirm(this.$t('contribution.delete')).then(async (value) => {
|
||||
if (value) this.$emit('delete-contribution', item)
|
||||
})
|
||||
},
|
||||
getListContributionMessages(closeCollapse = true) {
|
||||
if (closeCollapse) {
|
||||
this.$emit('closeAllOpenCollapse')
|
||||
}
|
||||
this.$apollo
|
||||
.query({
|
||||
query: listContributionMessages,
|
||||
variables: {
|
||||
contributionId: this.contributionId,
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
})
|
||||
.then((result) => {
|
||||
this.messages_get = result.data.listContributionMessages.messages
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
updateStatus(id) {
|
||||
this.$emit('update-status', id)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
visible() {
|
||||
if (this.visible) this.getListContributionMessages()
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
function updateStatus(id) {
|
||||
emit('update-status', id)
|
||||
}
|
||||
|
||||
const emit = defineEmits(['delete-contribution', 'close-all-open-collapse', 'update-status'])
|
||||
</script>
|
||||
|
||||
@ -37,7 +37,7 @@ describe('OpenCreationsAmount', () => {
|
||||
})
|
||||
|
||||
it('renders the component', () => {
|
||||
expect(wrapper.find('div.appBoxShadow').exists()).toBe(true)
|
||||
expect(wrapper.find('div.app-box-shadow').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders two dates', () => {
|
||||
|
||||
@ -1,34 +1,34 @@
|
||||
<template>
|
||||
<div class="bg-white appBoxShadow gradido-border-radius p-3">
|
||||
<div class="bg-white app-box-shadow gradido-border-radius p-3">
|
||||
<div class="pl-3">
|
||||
<b-row class="small">
|
||||
<b-col>{{ $t('time.months') }}</b-col>
|
||||
<b-col class="d-none d-md-inline">{{ $t('status') }}</b-col>
|
||||
<b-col class="d-none d-md-inline text-center">{{ $t('submitted') }}</b-col>
|
||||
<b-col class="text-center">{{ $t('openHours') }}</b-col>
|
||||
</b-row>
|
||||
<BRow class="small">
|
||||
<BCol>{{ $t('time.months') }}</BCol>
|
||||
<BCol class="d-none d-md-inline">{{ $t('status') }}</BCol>
|
||||
<BCol class="d-none d-md-inline text-center">{{ $t('submitted') }}</BCol>
|
||||
<BCol class="text-center">{{ $t('openHours') }}</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row class="font-weight-bold pt-3">
|
||||
<b-col>{{ $d(new Date(minimalDate), 'monthAndYear') }}</b-col>
|
||||
<b-col class="d-none d-md-inline">
|
||||
<BRow class="font-weight-bold pt-3">
|
||||
<BCol>{{ $d(new Date(minimalDate), 'monthAndYear') }}</BCol>
|
||||
<BCol class="d-none d-md-inline">
|
||||
{{ maxGddLastMonth > 0 ? $t('contribution.submit') : $t('maxReached') }}
|
||||
</b-col>
|
||||
<b-col class="d-none d-md-inline text-197 text-center">
|
||||
</BCol>
|
||||
<BCol class="d-none d-md-inline text-197 text-center">
|
||||
{{ hoursSubmittedLastMonth }} {{ $t('h') }}
|
||||
</b-col>
|
||||
<b-col class="text-4 text-center">{{ hoursAvailableLastMonth }} {{ $t('h') }}</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol class="text-4 text-center">{{ hoursAvailableLastMonth }} {{ $t('h') }}</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row class="font-weight-bold">
|
||||
<b-col>{{ $d(new Date(), 'monthAndYear') }}</b-col>
|
||||
<b-col class="d-none d-md-inline">
|
||||
<BRow class="font-weight-bold">
|
||||
<BCol>{{ $d(new Date(), 'monthAndYear') }}</BCol>
|
||||
<BCol class="d-none d-md-inline">
|
||||
{{ maxGddThisMonth > 0 ? $t('contribution.submit') : $t('maxReached') }}
|
||||
</b-col>
|
||||
<b-col class="d-none d-md-inline text-197 text-center">
|
||||
</BCol>
|
||||
<BCol class="d-none d-md-inline text-197 text-center">
|
||||
{{ hoursSubmittedThisMonth }} {{ $t('h') }}
|
||||
</b-col>
|
||||
<b-col class="text-4 text-center">{{ hoursAvailableThisMonth }} {{ $t('h') }}</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol class="text-4 text-center">{{ hoursAvailableThisMonth }} {{ $t('h') }}</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -11,17 +11,18 @@
|
||||
@reset-transaction-link-list="resetTransactionLinkList"
|
||||
/>
|
||||
<div class="mb-3">
|
||||
<b-button
|
||||
class="test-button-load-more"
|
||||
<BButton
|
||||
v-if="!pending && transactionLinks.length < transactionLinkCount"
|
||||
class="test-button-load-more"
|
||||
block
|
||||
variant="outline-primary"
|
||||
@click="loadMoreLinks"
|
||||
>
|
||||
{{ buttonText }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
<div class="text-center">
|
||||
<b-icon v-if="pending" icon="three-dots" animation="cylon" font-scale="4"></b-icon>
|
||||
<!-- <b-icon v-if="pending" icon="three-dots" animation="cylon" font-scale="4"></b-icon>-->
|
||||
<IBiThreeDots v-if="pending" animation="cylon" font-scale="4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -46,6 +47,14 @@ export default {
|
||||
pageSize: { type: Number, default: 5 },
|
||||
pending: { type: Boolean, default: false },
|
||||
},
|
||||
computed: {
|
||||
buttonText() {
|
||||
const i = this.transactionLinkCount - this.transactionLinks.length
|
||||
if (i === 1) return this.$t('link-load', 0)
|
||||
if (i <= this.pageSize) return this.$t('link-load', 1, { n: i })
|
||||
return this.$t('link-load', 2, { n: this.pageSize })
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resetTransactionLinkList() {
|
||||
this.$emit('input', 0)
|
||||
@ -54,13 +63,5 @@ export default {
|
||||
this.$emit('input', this.value + 1)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
buttonText() {
|
||||
const i = this.transactionLinkCount - this.transactionLinks.length
|
||||
if (i === 1) return this.$tc('link-load', 0)
|
||||
if (i <= this.pageSize) return this.$tc('link-load', 1, { n: i })
|
||||
return this.$tc('link-load', 2, { n: this.pageSize })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'DecayInformation-StartBlock',
|
||||
name: 'DecayInformationStartBlock',
|
||||
props: {
|
||||
memo: {
|
||||
type: String,
|
||||
|
||||
@ -1,31 +1,32 @@
|
||||
<template>
|
||||
<div class="decayinformation-decay">
|
||||
<div class="mb-3">
|
||||
<b-icon icon="droplet-half" class="mr-2" />
|
||||
<!-- <b-icon icon="droplet-half" class="mr-2" />-->
|
||||
<IBiDropletHalf class="mr-2" />
|
||||
<b>{{ $t('decay.calculation_decay') }}</b>
|
||||
</div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-row>
|
||||
<b-col cols="12" lg="4" md="4">
|
||||
<BRow>
|
||||
<BCol>
|
||||
<BRow>
|
||||
<BCol cols="12" lg="4" md="4">
|
||||
<div>{{ $t('decay.decay') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0">
|
||||
</BCol>
|
||||
<BCol offset="1" offset-md="0" offset-lg="0">
|
||||
<div>
|
||||
{{ previousBalance | GDD }}
|
||||
{{ $filters.GDD(previousBalance) }}
|
||||
{{ decay === '0' ? $t('math.minus') : '' }}
|
||||
{{ decay | GDD }} {{ $t('math.equal') }}
|
||||
<b>{{ balance | GDD }}</b>
|
||||
{{ $filters.GDD(decay) }} {{ $t('math.equal') }}
|
||||
<b>{{ $filters.GDD(balance) }}</b>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'DecayInformation-Decay',
|
||||
name: 'DecayInformationDecay',
|
||||
props: {
|
||||
balance: {
|
||||
type: String,
|
||||
|
||||
@ -1,75 +1,75 @@
|
||||
<template>
|
||||
<div class="decayinformation-startblock">
|
||||
<b-row>
|
||||
<b-col cols="12">
|
||||
<BRow>
|
||||
<BCol cols="12">
|
||||
<div class="text-center pb-3">
|
||||
<b-icon icon="droplet-half" class="mr-2" />
|
||||
<b>{{ $t('decay.Starting_block_decay') }}</b>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col offset="1" cols="11">
|
||||
<b-row>
|
||||
<b-col cols="5">
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol offset="1" cols="11">
|
||||
<BRow>
|
||||
<BCol cols="5">
|
||||
<div class="text-right">
|
||||
<div>{{ $t('decay.decay_introduced') }}</div>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="5">
|
||||
</BCol>
|
||||
<BCol cols="5">
|
||||
<div>
|
||||
<span v-if="decay.start">
|
||||
{{ $d(new Date(decay.start), 'long') }}
|
||||
</span>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<duration-row :decayStart="decay.start" :decayEnd="decay.end" />
|
||||
</BCol>
|
||||
</BRow>
|
||||
<duration-row :decay-start="decay.start" :decay-end="decay.end" />
|
||||
|
||||
<!-- Decay-->
|
||||
<b-row>
|
||||
<b-col cols="5" class="text-right">{{ $t('decay.decay') }}</b-col>
|
||||
<b-col cols="7">{{ decay.decay | GDD }}</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<BRow>
|
||||
<BCol cols="5" class="text-right">{{ $t('decay.decay') }}</BCol>
|
||||
<BCol cols="7">{{ $filters.GDD(decay.decay) }}</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<hr class="mt-3 mb-3" />
|
||||
|
||||
<b-row>
|
||||
<b-col class="text-center pb-3">
|
||||
<BRow>
|
||||
<BCol class="text-center pb-3">
|
||||
<b>{{ $t('decay.calculation_total') }}</b>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<!-- Type-->
|
||||
<b-row>
|
||||
<b-col offset="1" cols="11">
|
||||
<b-row>
|
||||
<BRow>
|
||||
<BCol offset="1" cols="11">
|
||||
<BRow>
|
||||
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
|
||||
<b-col cols="5" class="text-right">{{ $t(`decay.types.${typeId.toLowerCase()}`) }}</b-col>
|
||||
<b-col cols="7">{{ amount | GDD }}</b-col>
|
||||
</b-row>
|
||||
<BCol cols="5" class="text-right">{{ $t(`decay.types.${typeId.toLowerCase()}`) }}</BCol>
|
||||
<BCol cols="7">{{ $filters.GDD(amount) }}</BCol>
|
||||
</BRow>
|
||||
<!-- Decay-->
|
||||
<b-row>
|
||||
<b-col cols="5" class="text-right">{{ $t('decay.decay') }}</b-col>
|
||||
<b-col cols="7">{{ decay.decay | GDD }}</b-col>
|
||||
</b-row>
|
||||
<BRow>
|
||||
<BCol cols="5" class="text-right">{{ $t('decay.decay') }}</BCol>
|
||||
<BCol cols="7">{{ $filters.GDD(decay.decay) }}</BCol>
|
||||
</BRow>
|
||||
<!-- Total-->
|
||||
<b-row>
|
||||
<b-col cols="5" class="text-right">{{ $t('decay.total') }}</b-col>
|
||||
<b-col cols="7">
|
||||
<b>{{ (Number(amount) + Number(decay.decay)) | GDD }}</b>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<BRow>
|
||||
<BCol cols="5" class="text-right">{{ $t('decay.total') }}</BCol>
|
||||
<BCol cols="7">
|
||||
<b>{{ $filters.GDD(Number(amount) + Number(decay.decay)) }}</b>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import DurationRow from '@/components/TransactionRows/DurationRow'
|
||||
|
||||
export default {
|
||||
name: 'DecayInformation-StartBlock',
|
||||
name: 'DecayInformationStartBlock',
|
||||
components: {
|
||||
DurationRow,
|
||||
},
|
||||
|
||||
@ -5,77 +5,77 @@
|
||||
<div class="">{{ memo }}</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<b-icon icon="droplet-half" class="mr-2" />
|
||||
<IBiDropletHalf class="mr-2" />
|
||||
<b>{{ $t('decay.calculation_decay') }}</b>
|
||||
</div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-row>
|
||||
<b-col cols="6" lg="4" md="6" sm="6">
|
||||
<BRow>
|
||||
<BCol>
|
||||
<BRow>
|
||||
<BCol cols="6" lg="4" md="6" sm="6">
|
||||
<div>{{ $t('decay.last_transaction') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
</BCol>
|
||||
<BCol offset="0" class="text-right mr-0">
|
||||
<div>
|
||||
<span>
|
||||
{{ $d(new Date(decay.start), 'long') }}
|
||||
</span>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<duration-row :decayStart="decay.start" :decayEnd="decay.end" />
|
||||
</BCol>
|
||||
</BRow>
|
||||
<duration-row :decay-start="decay.start" :decay-end="decay.end" />
|
||||
|
||||
<!-- Previous Balance -->
|
||||
<b-row class="mt-2">
|
||||
<b-col cols="6" lg="4" md="6" sm="6">
|
||||
<BRow class="mt-2">
|
||||
<BCol cols="6" lg="4" md="6" sm="6">
|
||||
<div>{{ $t('decay.old_balance') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
{{ previousBalance | GDD }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol offset="0" class="text-right mr-0">
|
||||
{{ $filters.GDD(previousBalance) }}
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<!-- Decay-->
|
||||
<b-row class="mt-0">
|
||||
<b-col cols="6" lg="3" md="6" sm="6">
|
||||
<BRow class="mt-0">
|
||||
<BCol cols="6" lg="3" md="6" sm="6">
|
||||
<div>{{ $t('decay.decay') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
{{ decay.decay | GDD }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol offset="0" class="text-right mr-0">
|
||||
{{ $filters.GDD(decay.decay) }}
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<!-- Type-->
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-row class="mb-2">
|
||||
<BRow>
|
||||
<BCol>
|
||||
<BRow class="mb-2">
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-dynamic-keys-->
|
||||
<b-col cols="6" lg="3" md="6" sm="6">
|
||||
<BCol cols="6" lg="3" md="6" sm="6">
|
||||
{{ $t(`decay.types.${typeId.toLowerCase()}`) }}
|
||||
</b-col>
|
||||
</BCol>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-dynamic-keys-->
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
{{ amount | GDD }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
<BCol offset="0" class="text-right mr-0">
|
||||
{{ $filters.GDD(amount) }}
|
||||
</BCol>
|
||||
</BRow>
|
||||
<!-- Total-->
|
||||
<b-row class="border-top pt-2">
|
||||
<b-col cols="6" lg="3" md="6" sm="6">
|
||||
<BRow class="border-top pt-2">
|
||||
<BCol cols="6" lg="3" md="6" sm="6">
|
||||
<div>{{ $t('decay.new_balance') }}</div>
|
||||
</b-col>
|
||||
<b-col offset="0" class="text-right mr-0">
|
||||
<b>{{ balance | GDD }}</b>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol offset="0" class="text-right mr-0">
|
||||
<b>{{ $filters.GDD(balance) }}</b>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import DurationRow from '@/components/TransactionRows/DurationRow'
|
||||
|
||||
export default {
|
||||
name: 'DecayInformation-Long',
|
||||
name: 'DecayInformationLong',
|
||||
components: {
|
||||
DurationRow,
|
||||
},
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="decayinformation-short">
|
||||
<span v-if="decay">{{ decay | GDD }}</span>
|
||||
<span v-if="decay">{{ $filters.GDD(decay) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'DecayInformation-Short',
|
||||
name: 'DecayInformationShort',
|
||||
props: {
|
||||
decay: {
|
||||
type: String,
|
||||
|
||||
@ -5,16 +5,16 @@
|
||||
v-else-if="isStartBlock"
|
||||
:amount="amount"
|
||||
:decay="decay"
|
||||
:typeId="typeId"
|
||||
:type-id="typeId"
|
||||
/>
|
||||
<decay-information-long
|
||||
v-else
|
||||
:amount="amount"
|
||||
:decay="decay"
|
||||
:typeId="typeId"
|
||||
:type-id="typeId"
|
||||
:memo="memo"
|
||||
:balance="balance"
|
||||
:previousBalance="previousBalance"
|
||||
:previous-balance="previousBalance"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,48 +1,48 @@
|
||||
<template>
|
||||
<div class="transaction-confirm-link">
|
||||
<div class="bg-white appBoxShadow gradido-border-radius p-3">
|
||||
<div class="bg-white app-box-shadow gradido-border-radius p-3">
|
||||
<div class="h3 mb-4">{{ $t('gdd_per_link.header') }}</div>
|
||||
<b-row class="mt-5">
|
||||
<b-col offset="2">
|
||||
<BRow class="mt-5">
|
||||
<BCol offset="2">
|
||||
<div class="mt-3 h5">{{ $t('form.memo') }}</div>
|
||||
<div>{{ memo }}</div>
|
||||
</b-col>
|
||||
<b-col cols="3">
|
||||
</BCol>
|
||||
<BCol cols="3">
|
||||
<div class="small">{{ $t('send_gdd') }}</div>
|
||||
<div>{{ amount | GDD }}</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<div>{{ $filters.GDD(amount) }}</div>
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row class="mt-5 pr-3 text-color-gdd-yellow h3">
|
||||
<b-col cols="2" class="text-right">
|
||||
<BRow class="mt-5 pr-3 text-color-gdd-yellow h3">
|
||||
<BCol cols="2" class="text-right">
|
||||
<b-icon class="text-color-gdd-yellow" icon="droplet-half"></b-icon>
|
||||
</b-col>
|
||||
<b-col>{{ $t('advanced-calculation') }}</b-col>
|
||||
</b-row>
|
||||
<b-row class="pr-3" offset="2">
|
||||
<b-col offset="2">{{ $t('form.current_balance') }}</b-col>
|
||||
<b-col>{{ balance | GDD }}</b-col>
|
||||
</b-row>
|
||||
<b-row class="pr-3">
|
||||
<b-col offset="2">
|
||||
</BCol>
|
||||
<BCol>{{ $t('advanced-calculation') }}</BCol>
|
||||
</BRow>
|
||||
<BRow class="pr-3" offset="2">
|
||||
<BCol offset="2">{{ $t('form.current_balance') }}</BCol>
|
||||
<BCol>{{ $filters.GDD(balance) }}</BCol>
|
||||
</BRow>
|
||||
<BRow class="pr-3">
|
||||
<BCol offset="2">
|
||||
<strong>{{ $t('form.your_amount') }}</strong>
|
||||
</b-col>
|
||||
<b-col class="borderbottom">
|
||||
<strong>{{ (amount * -1) | GDD }}</strong>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row class="pr-3">
|
||||
<b-col offset="2">{{ $t('form.new_balance') }}</b-col>
|
||||
<b-col>{{ (balance - amount) | GDD }}</b-col>
|
||||
</b-row>
|
||||
<b-row class="mt-5">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<b-button block @click="$emit('on-back')" class="mb-3 mb-md-0 mb-lg-0">
|
||||
</BCol>
|
||||
<BCol class="borderbottom">
|
||||
<strong>{{ $filters.GDD(amount * -1) }}</strong>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow class="pr-3">
|
||||
<BCol offset="2">{{ $t('form.new_balance') }}</BCol>
|
||||
<BCol>{{ $filters.GDD(balance - amount) }}</BCol>
|
||||
</BRow>
|
||||
<BRow class="mt-5">
|
||||
<BCol cols="12" md="6" lg="6">
|
||||
<BButton block class="mb-3 mb-md-0 mb-lg-0" @click="$emit('on-back')">
|
||||
{{ $t('back') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-lg-right">
|
||||
<b-button
|
||||
</BButton>
|
||||
</BCol>
|
||||
<BCol cols="12" md="6" lg="6" class="text-lg-right">
|
||||
<BButton
|
||||
block
|
||||
class="send-button"
|
||||
variant="gradido"
|
||||
@ -50,9 +50,9 @@
|
||||
@click="$emit('send-transaction')"
|
||||
>
|
||||
{{ $t('form.generate_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -83,8 +83,9 @@ export default {
|
||||
.gray-background {
|
||||
background-color: #ecebe6a3 !important;
|
||||
}
|
||||
|
||||
.borderbottom {
|
||||
border-bottom: 1px solid rgb(70, 65, 65);
|
||||
border-bottom: 1px solid rgb(70 65 65);
|
||||
border-bottom-style: double;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,72 +1,73 @@
|
||||
<template>
|
||||
<div class="transaction-confirm-send">
|
||||
<div class="bg-white appBoxShadow gradido-border-radius p-3">
|
||||
<div class="bg-white app-box-shadow gradido-border-radius p-3">
|
||||
<div class="h3 mb-4">{{ $t('form.send_check') }}</div>
|
||||
<b-row class="mt-5">
|
||||
<b-col cols="12">
|
||||
<b-row class="mt-3">
|
||||
<b-col class="h5">{{ $t('form.recipientCommunity') }}</b-col>
|
||||
<b-col>{{ targetCommunity.name }}</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col class="h5">{{ $t('form.recipient') }}</b-col>
|
||||
<b-col>{{ userName ? userName : identifier }}</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col class="h5">{{ $t('form.amount') }}</b-col>
|
||||
<b-col>{{ amount | GDD }}</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col class="h5">{{ $t('form.memo') }}</b-col>
|
||||
<b-col>{{ memo }}</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<BRow class="mt-5">
|
||||
<BCol cols="12">
|
||||
<BRow class="mt-3">
|
||||
<BCol class="h5">{{ $t('form.recipientCommunity') }}</BCol>
|
||||
<BCol>{{ targetCommunity.name }}</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol class="h5">{{ $t('form.recipient') }}</BCol>
|
||||
<BCol>{{ userName ? userName : identifier }}</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol class="h5">{{ $t('form.amount') }}</BCol>
|
||||
<BCol>{{ $filters.GDD(amount) }}</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol class="h5">{{ $t('form.memo') }}</BCol>
|
||||
<BCol>{{ memo }}</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row class="mt-5 text-color-gdd-yellow h3">
|
||||
<b-col cols="2" class="text-right">
|
||||
<b-icon class="text-color-gdd-yellow" icon="droplet-half"></b-icon>
|
||||
</b-col>
|
||||
<b-col>{{ $t('advanced-calculation') }}</b-col>
|
||||
</b-row>
|
||||
<b-row class="pr-3" offset="2">
|
||||
<b-col offset="2">{{ $t('form.current_balance') }}</b-col>
|
||||
<b-col>{{ balance | GDD }}</b-col>
|
||||
</b-row>
|
||||
<b-row class="pr-3">
|
||||
<b-col offset="2">
|
||||
<BRow class="mt-5 text-color-gdd-yellow h3">
|
||||
<BCol cols="2" class="text-right">
|
||||
<!-- <b-icon class="text-color-gdd-yellow" icon="droplet-half"></b-icon>-->
|
||||
<IBiDropletHalf />
|
||||
</BCol>
|
||||
<BCol>{{ $t('advanced-calculation') }}</BCol>
|
||||
</BRow>
|
||||
<BRow class="pr-3" offset="2">
|
||||
<BCol offset="2">{{ $t('form.current_balance') }}</BCol>
|
||||
<BCol>{{ $filters.GDD(balance) }}</BCol>
|
||||
</BRow>
|
||||
<BRow class="pr-3">
|
||||
<BCol offset="2">
|
||||
<strong>{{ $t('form.your_amount') }}</strong>
|
||||
</b-col>
|
||||
<b-col class="borderbottom">
|
||||
<strong>{{ (amount * -1) | GDD }}</strong>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row class="pr-3">
|
||||
<b-col offset="2">{{ $t('form.new_balance') }}</b-col>
|
||||
<b-col>{{ (balance - amount) | GDD }}</b-col>
|
||||
</b-row>
|
||||
<b-row class="mt-5">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<b-button block @click="$emit('on-back')" class="mb-3 mb-md-0 mb-lg-0">
|
||||
</BCol>
|
||||
<BCol class="borderbottom">
|
||||
<strong>{{ $filters.GDD(amount * -1) }}</strong>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow class="pr-3">
|
||||
<BCol offset="2">{{ $t('form.new_balance') }}</BCol>
|
||||
<BCol>{{ $filters.GDD(balance - amount) }}</BCol>
|
||||
</BRow>
|
||||
<BRow class="mt-5">
|
||||
<BCol cols="12" md="6" lg="6">
|
||||
<BButton block class="mb-3 mb-md-0 mb-lg-0" @click="$emit('on-back')">
|
||||
{{ $t('back') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-lg-right">
|
||||
<b-button
|
||||
</BButton>
|
||||
</BCol>
|
||||
<BCol cols="12" md="6" lg="6" class="text-lg-right">
|
||||
<BButton
|
||||
block
|
||||
variant="gradido"
|
||||
:disabled="disabled"
|
||||
@click="$emit('send-transaction'), (disabled = true)"
|
||||
>
|
||||
{{ $t('form.send_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { COMMUNITY_NAME } from '@/config'
|
||||
import CONFIG from '@/config'
|
||||
|
||||
export default {
|
||||
name: 'TransactionConfirmationSend',
|
||||
@ -79,7 +80,7 @@ export default {
|
||||
targetCommunity: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return { uuid: '', name: COMMUNITY_NAME }
|
||||
return { uuid: '', name: CONFIG.COMMUNITY_NAME }
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -94,8 +95,9 @@ export default {
|
||||
.gray-background {
|
||||
background-color: #ecebe6a3 !important;
|
||||
}
|
||||
|
||||
.borderbottom {
|
||||
border-bottom: 1px solid rgb(70, 65, 65);
|
||||
border-bottom: 1px solid rgb(70 65 65);
|
||||
border-bottom-style: double;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import TransactionForm from './TransactionForm'
|
||||
import flushPromises from 'flush-promises'
|
||||
import { SEND_TYPES } from '@/pages/Send'
|
||||
import { SEND_TYPES } from '@/utils/sendTypes'
|
||||
import { createMockClient } from 'mock-apollo-client'
|
||||
import VueApollo from 'vue-apollo'
|
||||
import { user, selectCommunities as selectCommunitiesQuery } from '@/graphql/queries'
|
||||
|
||||
@ -1,276 +1,379 @@
|
||||
<template>
|
||||
<div class="transaction-form">
|
||||
<b-row>
|
||||
<b-col cols="12">
|
||||
<b-card class="appBoxShadow gradido-border-radius" body-class="p-4">
|
||||
<validation-observer v-slot="{ handleSubmit }" ref="formValidator">
|
||||
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)" @reset="onReset">
|
||||
<b-form-radio-group v-model="radioSelected">
|
||||
<b-row class="mb-4">
|
||||
<b-col cols="12" lg="6">
|
||||
<b-row class="bg-248 gradido-border-radius pt-lg-2 mr-lg-2">
|
||||
<b-col cols="10" @click="radioSelected = sendTypes.send" class="pointer">
|
||||
{{ $t('send_gdd') }}
|
||||
</b-col>
|
||||
<b-col cols="2">
|
||||
<b-form-radio
|
||||
name="shipping"
|
||||
size="lg"
|
||||
:value="sendTypes.send"
|
||||
stacked
|
||||
class="custom-radio-button pointer"
|
||||
></b-form-radio>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
<b-col>
|
||||
<b-row class="bg-248 gradido-border-radius pt-lg-2 ml-lg-2 mt-2 mt-lg-0">
|
||||
<b-col cols="10" @click="radioSelected = sendTypes.link" class="pointer">
|
||||
{{ $t('send_per_link') }}
|
||||
</b-col>
|
||||
<b-col cols="2" class="pointer">
|
||||
<b-form-radio
|
||||
name="shipping"
|
||||
:value="sendTypes.link"
|
||||
size="lg"
|
||||
class="custom-radio-button"
|
||||
></b-form-radio>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form-radio-group>
|
||||
<div class="mt-4 mb-4" v-if="radioSelected === sendTypes.link">
|
||||
<h2 class="alert-heading">{{ $t('gdd_per_link.header') }}</h2>
|
||||
<div>
|
||||
{{ $t('gdd_per_link.choose-amount') }}
|
||||
</div>
|
||||
<BRow>
|
||||
<BCol cols="12">
|
||||
<BCard class="app-box-shadow gradido-border-radius" body-class="p-4">
|
||||
<BForm role="form" @submit.prevent="onSubmit" @reset="onReset">
|
||||
<BFormRadioGroup
|
||||
name="shipping"
|
||||
:model-value="radioSelected"
|
||||
@update:model-value="radioSelected = $event"
|
||||
>
|
||||
<BRow class="mb-4">
|
||||
<BCol cols="12" lg="6">
|
||||
<BRow class="bg-248 gradido-border-radius pt-lg-2 mr-lg-2">
|
||||
<BFormRadio
|
||||
name="shipping"
|
||||
size="sm"
|
||||
reverse
|
||||
:value="SEND_TYPES.send"
|
||||
class="custom-radio-button pointer"
|
||||
>
|
||||
{{ $t('send_gdd') }}
|
||||
</BFormRadio>
|
||||
</BRow>
|
||||
</BCol>
|
||||
<BCol>
|
||||
<BRow class="bg-248 gradido-border-radius pt-lg-2 ml-lg-2 mt-2 mt-lg-0">
|
||||
<BFormRadio
|
||||
name="shipping"
|
||||
:value="SEND_TYPES.link"
|
||||
size="sm"
|
||||
reverse
|
||||
class="custom-radio-button"
|
||||
>
|
||||
{{ $t('send_per_link') }}
|
||||
</BFormRadio>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BFormRadioGroup>
|
||||
<div v-if="radioSelected === SEND_TYPES.link" class="mt-4 mb-4">
|
||||
<h2 class="alert-heading">{{ $t('gdd_per_link.header') }}</h2>
|
||||
<div>
|
||||
{{ $t('gdd_per_link.choose-amount') }}
|
||||
</div>
|
||||
<b-row>
|
||||
<b-col>
|
||||
<b-row>
|
||||
<b-col class="mb-4" cols="12" v-if="radioSelected === sendTypes.send">
|
||||
<b-row>
|
||||
<b-col>{{ $t('form.recipientCommunity') }}</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col class="font-weight-bold">
|
||||
<community-switch
|
||||
v-model="form.targetCommunity"
|
||||
:disabled="isBalanceDisabled"
|
||||
/>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
<b-col cols="12" v-if="radioSelected === sendTypes.send">
|
||||
<div v-if="!userIdentifier">
|
||||
<input-identifier
|
||||
:name="$t('form.recipient')"
|
||||
:label="$t('form.recipient')"
|
||||
:placeholder="$t('form.identifier')"
|
||||
v-model="form.identifier"
|
||||
</div>
|
||||
<BRow>
|
||||
<BCol>
|
||||
<BRow>
|
||||
<BCol v-if="radioSelected === SEND_TYPES.send" class="mb-4" cols="12">
|
||||
<BRow>
|
||||
<BCol>{{ $t('form.recipientCommunity') }}</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol class="font-weight-bold">
|
||||
<community-switch
|
||||
:disabled="isBalanceDisabled"
|
||||
@onValidation="onValidation"
|
||||
:model-value="targetCommunity"
|
||||
@update:model-value="targetCommunity = $event"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="mb-4">
|
||||
<b-row>
|
||||
<b-col>{{ $t('form.recipient') }}</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col class="font-weight-bold">{{ userName }}</b-col>
|
||||
</b-row>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="12" lg="6">
|
||||
<input-amount
|
||||
v-model="form.amount"
|
||||
:name="$t('form.amount')"
|
||||
:label="$t('form.amount')"
|
||||
:placeholder="'0.01'"
|
||||
:rules="{ required: true, gddSendAmount: [0.01, balance] }"
|
||||
typ="TransactionForm"
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
<BCol v-if="radioSelected === SEND_TYPES.send" cols="12">
|
||||
<div v-if="!userIdentifier">
|
||||
<input-identifier
|
||||
name="identifier"
|
||||
:label="$t('form.recipient')"
|
||||
:placeholder="$t('form.identifier')"
|
||||
:disabled="isBalanceDisabled"
|
||||
></input-amount>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="mb-4">
|
||||
<BRow>
|
||||
<BCol>{{ $t('form.recipient') }}</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol class="font-weight-bold">{{ userName }}</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</BCol>
|
||||
<BCol cols="12" lg="6">
|
||||
<input-amount
|
||||
name="amount"
|
||||
:label="$t('form.amount')"
|
||||
:placeholder="'0.01'"
|
||||
:rules="{ required: true, gddSendAmount: { min: 0.01, max: balance } }"
|
||||
:disabled="isBalanceDisabled"
|
||||
></input-amount>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row>
|
||||
<b-col>
|
||||
<input-textarea
|
||||
v-model="form.memo"
|
||||
:name="$t('form.message')"
|
||||
:label="$t('form.message')"
|
||||
:placeholder="$t('form.message')"
|
||||
:rules="{ required: true, min: 5, max: 255 }"
|
||||
:disabled="isBalanceDisabled"
|
||||
/>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<div v-if="!!isBalanceDisabled" class="text-danger mt-5">
|
||||
{{ $t('form.no_gdd_available') }}
|
||||
</div>
|
||||
<b-row v-else class="test-buttons mt-3">
|
||||
<b-col cols="12" md="6" lg="6">
|
||||
<b-button
|
||||
block
|
||||
type="reset"
|
||||
variant="secondary"
|
||||
@click="onReset"
|
||||
class="mb-3 mb-md-0 mb-lg-0"
|
||||
>
|
||||
{{ $t('form.reset') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col cols="12" md="6" lg="6" class="text-lg-right">
|
||||
<b-button block type="submit" variant="gradido">
|
||||
{{ $t('form.check_now') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-form>
|
||||
</validation-observer>
|
||||
</b-card>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<BRow>
|
||||
<BCol>
|
||||
<input-textarea
|
||||
name="memo"
|
||||
:label="$t('form.message')"
|
||||
:placeholder="$t('form.message')"
|
||||
:rules="{ required: true, min: 5, max: 255 }"
|
||||
:disabled="isBalanceDisabled"
|
||||
/>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<div v-if="!!isBalanceDisabled" class="text-danger mt-5">
|
||||
{{ $t('form.no_gdd_available') }}
|
||||
</div>
|
||||
<BRow v-else class="test-buttons mt-3">
|
||||
<BCol cols="12" md="6" lg="6">
|
||||
<BButton
|
||||
block
|
||||
type="reset"
|
||||
variant="secondary"
|
||||
class="mb-3 mb-md-0 mb-lg-0"
|
||||
@click="onReset"
|
||||
>
|
||||
{{ $t('form.reset') }}
|
||||
</BButton>
|
||||
</BCol>
|
||||
<BCol cols="12" md="6" lg="6" class="text-lg-right">
|
||||
<BButton block type="submit" variant="gradido">
|
||||
{{ $t('form.check_now') }}
|
||||
</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BForm>
|
||||
</BCard>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { SEND_TYPES } from '@/pages/Send'
|
||||
<!--<script>-->
|
||||
<!--import { SEND_TYPES } from '@/utils/sendTypes'-->
|
||||
<!--import InputIdentifier from '@/components/Inputs/InputIdentifier'-->
|
||||
<!--import InputAmount from '@/components/Inputs/InputAmount'-->
|
||||
<!--import InputTextarea from '@/components/Inputs/InputTextarea'-->
|
||||
<!--import CommunitySwitch from '@/components/CommunitySwitch.vue'-->
|
||||
<!--import { user } from '@/graphql/queries'-->
|
||||
<!--import CONFIG from '@/config'-->
|
||||
|
||||
<!--export default {-->
|
||||
<!-- name: 'TransactionForm',-->
|
||||
<!-- components: {-->
|
||||
<!-- InputIdentifier,-->
|
||||
<!-- InputAmount,-->
|
||||
<!-- InputTextarea,-->
|
||||
<!-- CommunitySwitch,-->
|
||||
<!-- },-->
|
||||
<!-- props: {-->
|
||||
<!-- balance: { type: Number, default: 0 },-->
|
||||
<!-- identifier: { type: String, default: '' },-->
|
||||
<!-- amount: { type: Number, default: 0 },-->
|
||||
<!-- memo: { type: String, default: '' },-->
|
||||
<!-- selected: { type: String, default: 'send' },-->
|
||||
<!-- targetCommunity: {-->
|
||||
<!-- type: Object,-->
|
||||
<!-- default: function () {-->
|
||||
<!-- return { uuid: '', name: CONFIG.COMMUNITY_NAME }-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- form: {-->
|
||||
<!-- identifier: this.identifier,-->
|
||||
<!-- amount: this.amount ? String(this.amount) : '',-->
|
||||
<!-- memo: this.memo,-->
|
||||
<!-- targetCommunity: this.targetCommunity,-->
|
||||
<!-- },-->
|
||||
<!-- radioSelected: this.selected,-->
|
||||
<!-- userName: '',-->
|
||||
<!-- recipientCommunity: { uuid: '', name: '' },-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- onValidation() {-->
|
||||
<!-- this.$refs.formValidator.validate()-->
|
||||
<!-- },-->
|
||||
<!-- onSubmit() {-->
|
||||
<!-- if (this.userIdentifier) this.form.identifier = this.userIdentifier.identifier-->
|
||||
<!-- this.$emit('set-transaction', {-->
|
||||
<!-- selected: this.radioSelected,-->
|
||||
<!-- identifier: this.form.identifier,-->
|
||||
<!-- amount: Number(this.form.amount.replace(',', '.')),-->
|
||||
<!-- memo: this.form.memo,-->
|
||||
<!-- userName: this.userName,-->
|
||||
<!-- targetCommunity: this.form.targetCommunity,-->
|
||||
<!-- })-->
|
||||
<!-- },-->
|
||||
<!-- onReset(event) {-->
|
||||
<!-- event.preventDefault()-->
|
||||
<!-- this.form.identifier = ''-->
|
||||
<!-- this.form.amount = ''-->
|
||||
<!-- this.form.memo = ''-->
|
||||
<!-- this.form.targetCommunity = { uuid: '', name: COMMUNITY_NAME }-->
|
||||
<!-- this.$refs.formValidator.validate()-->
|
||||
<!-- this.$router.replace('/send')-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- apollo: {-->
|
||||
<!-- UserName: {-->
|
||||
<!-- query() {-->
|
||||
<!-- return user-->
|
||||
<!-- },-->
|
||||
<!-- fetchPolicy: 'network-only',-->
|
||||
<!-- variables() {-->
|
||||
<!-- return this.userIdentifier-->
|
||||
<!-- },-->
|
||||
<!-- skip() {-->
|
||||
<!-- return !this.userIdentifier-->
|
||||
<!-- },-->
|
||||
<!-- update({ user }) {-->
|
||||
<!-- this.userName = `${user.firstName} ${user.lastName}`-->
|
||||
<!-- },-->
|
||||
<!-- error({ message }) {-->
|
||||
<!-- this.toastError(message)-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- disabled() {-->
|
||||
<!-- if (-->
|
||||
<!-- this.form.identifier.length > 5 &&-->
|
||||
<!-- parseInt(this.form.amount) <= parseInt(this.balance) &&-->
|
||||
<!-- this.form.memo.length > 5 &&-->
|
||||
<!-- this.form.memo.length <= 255-->
|
||||
<!-- ) {-->
|
||||
<!-- return false-->
|
||||
<!-- }-->
|
||||
<!-- return true-->
|
||||
<!-- },-->
|
||||
<!-- isBalanceDisabled() {-->
|
||||
<!-- return this.balance <= 0 ? 'disabled' : false-->
|
||||
<!-- },-->
|
||||
<!-- sendTypes() {-->
|
||||
<!-- return SEND_TYPES-->
|
||||
<!-- },-->
|
||||
<!-- userIdentifier() {-->
|
||||
<!-- if (-->
|
||||
<!-- this.$route.params &&-->
|
||||
<!-- this.$route.params.userIdentifier &&-->
|
||||
<!-- this.$route.params.communityIdentifier-->
|
||||
<!-- ) {-->
|
||||
<!-- return {-->
|
||||
<!-- identifier: this.$route.params.userIdentifier,-->
|
||||
<!-- communityIdentifier: this.$route.params.communityIdentifier,-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- return null-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- mounted() {-->
|
||||
<!-- if (this.form.identifier !== '') this.$refs.formValidator.validate()-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { SEND_TYPES } from '@/utils/sendTypes'
|
||||
import InputIdentifier from '@/components/Inputs/InputIdentifier'
|
||||
import InputAmount from '@/components/Inputs/InputAmount'
|
||||
import InputTextarea from '@/components/Inputs/InputTextarea'
|
||||
import CommunitySwitch from '@/components/CommunitySwitch.vue'
|
||||
import { user } from '@/graphql/queries'
|
||||
import { COMMUNITY_NAME } from '@/config'
|
||||
import CONFIG from '@/config'
|
||||
import { useAppToast } from '@/composables/useToast'
|
||||
|
||||
export default {
|
||||
name: 'TransactionForm',
|
||||
components: {
|
||||
InputIdentifier,
|
||||
InputAmount,
|
||||
InputTextarea,
|
||||
CommunitySwitch,
|
||||
const props = defineProps({
|
||||
balance: { type: Number, default: 0 },
|
||||
identifier: { type: String, default: '' },
|
||||
amount: { type: Number, default: 0 },
|
||||
memo: { type: String, default: '' },
|
||||
selected: { type: String, default: 'send' },
|
||||
targetCommunity: {
|
||||
type: Object,
|
||||
default: () => ({ uuid: '', name: CONFIG.COMMUNITY_NAME }),
|
||||
},
|
||||
props: {
|
||||
balance: { type: Number, default: 0 },
|
||||
identifier: { type: String, default: '' },
|
||||
amount: { type: Number, default: 0 },
|
||||
memo: { type: String, default: '' },
|
||||
selected: { type: String, default: 'send' },
|
||||
targetCommunity: {
|
||||
type: Object,
|
||||
default: function () {
|
||||
return { uuid: '', name: COMMUNITY_NAME }
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['set-transaction'])
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { toastError } = useAppToast()
|
||||
|
||||
const radioSelected = ref(props.selected)
|
||||
const userName = ref('')
|
||||
const recipientCommunity = ref({ uuid: '', name: '' })
|
||||
|
||||
// Use vee-validate's useForm
|
||||
const { handleSubmit, resetForm, defineField } = useForm({
|
||||
initialValues: {
|
||||
identifier: props.identifier,
|
||||
amount: props.amount ? String(props.amount) : '',
|
||||
memo: props.memo,
|
||||
targetCommunity: props.targetCommunity,
|
||||
},
|
||||
data() {
|
||||
})
|
||||
|
||||
const [targetCommunity, targetCommunityProps] = defineField('targetCommunity')
|
||||
|
||||
const userIdentifier = computed(() => {
|
||||
if (route.params.userIdentifier && route.params.communityIdentifier) {
|
||||
return {
|
||||
form: {
|
||||
identifier: this.identifier,
|
||||
amount: this.amount ? String(this.amount) : '',
|
||||
memo: this.memo,
|
||||
targetCommunity: this.targetCommunity,
|
||||
},
|
||||
radioSelected: this.selected,
|
||||
userName: '',
|
||||
recipientCommunity: { uuid: '', name: '' },
|
||||
identifier: route.params.userIdentifier,
|
||||
communityIdentifier: route.params.communityIdentifier,
|
||||
}
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const isBalanceDisabled = computed(() => props.balance <= 0)
|
||||
|
||||
const { result: userResult, error: userError } = useQuery(
|
||||
user,
|
||||
() => userIdentifier.value,
|
||||
() => ({ enabled: !!userIdentifier.value }),
|
||||
)
|
||||
|
||||
watch(
|
||||
() => userResult.value?.user,
|
||||
(user) => {
|
||||
if (user) {
|
||||
userName.value = `${user.firstName} ${user.lastName}`
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onValidation() {
|
||||
this.$refs.formValidator.validate()
|
||||
},
|
||||
onSubmit() {
|
||||
if (this.userIdentifier) this.form.identifier = this.userIdentifier.identifier
|
||||
this.$emit('set-transaction', {
|
||||
selected: this.radioSelected,
|
||||
identifier: this.form.identifier,
|
||||
amount: Number(this.form.amount.replace(',', '.')),
|
||||
memo: this.form.memo,
|
||||
userName: this.userName,
|
||||
targetCommunity: this.form.targetCommunity,
|
||||
})
|
||||
},
|
||||
onReset(event) {
|
||||
event.preventDefault()
|
||||
this.form.identifier = ''
|
||||
this.form.amount = ''
|
||||
this.form.memo = ''
|
||||
this.form.targetCommunity = { uuid: '', name: COMMUNITY_NAME }
|
||||
this.$refs.formValidator.validate()
|
||||
this.$router.replace('/send')
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
UserName: {
|
||||
query() {
|
||||
return user
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
variables() {
|
||||
return this.userIdentifier
|
||||
},
|
||||
skip() {
|
||||
return !this.userIdentifier
|
||||
},
|
||||
update({ user }) {
|
||||
this.userName = `${user.firstName} ${user.lastName}`
|
||||
},
|
||||
error({ message }) {
|
||||
this.toastError(message)
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
disabled() {
|
||||
if (
|
||||
this.form.identifier.length > 5 &&
|
||||
parseInt(this.form.amount) <= parseInt(this.balance) &&
|
||||
this.form.memo.length > 5 &&
|
||||
this.form.memo.length <= 255
|
||||
) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
isBalanceDisabled() {
|
||||
return this.balance <= 0 ? 'disabled' : false
|
||||
},
|
||||
sendTypes() {
|
||||
return SEND_TYPES
|
||||
},
|
||||
userIdentifier() {
|
||||
if (
|
||||
this.$route.params &&
|
||||
this.$route.params.userIdentifier &&
|
||||
this.$route.params.communityIdentifier
|
||||
) {
|
||||
return {
|
||||
identifier: this.$route.params.userIdentifier,
|
||||
communityIdentifier: this.$route.params.communityIdentifier,
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.form.identifier !== '') this.$refs.formValidator.validate()
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
watch(userError, (error) => {
|
||||
if (error) {
|
||||
toastError(error.message)
|
||||
}
|
||||
})
|
||||
|
||||
const onSubmit = handleSubmit((formValues) => {
|
||||
if (userIdentifier.value) formValues.identifier = userIdentifier.value.identifier
|
||||
emit('set-transaction', {
|
||||
selected: radioSelected.value,
|
||||
...formValues,
|
||||
amount: Number(formValues.amount.replace(',', '.')),
|
||||
userName: userName.value,
|
||||
})
|
||||
})
|
||||
|
||||
function onReset(event) {
|
||||
event.preventDefault()
|
||||
resetForm()
|
||||
radioSelected.value = SEND_TYPES.send
|
||||
router.replace('/send')
|
||||
}
|
||||
|
||||
// Expose necessary methods and computed properties
|
||||
// defineExpose({
|
||||
// sendTypes: SEND_TYPES,
|
||||
// handleSubmit: onSubmit,
|
||||
// onReset,
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style>
|
||||
span.errors {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#input-1:focus,
|
||||
#input-2:focus,
|
||||
#input-3:focus {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.border-radius {
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div class="bg-white appBoxShadow gradido-border-radius p-5">
|
||||
<div class="bg-white app-box-shadow gradido-border-radius p-5">
|
||||
<div class="h3 mb-4">{{ $t('gdd_per_link.created') }}</div>
|
||||
<clipboard-copy
|
||||
:link="link"
|
||||
:amount="amount"
|
||||
:memo="memo"
|
||||
:validUntil="validUntil"
|
||||
:valid-until="validUntil"
|
||||
></clipboard-copy>
|
||||
<label>{{ $t('qrCode') }}</label>
|
||||
<div class="text-center">
|
||||
<div><figure-qr-code :link="link" /></div>
|
||||
<div>
|
||||
<b-button variant="secondary" @click="$emit('on-back')" class="mt-4" data-test="close-btn">
|
||||
<BButton variant="secondary" class="mt-4" data-test="close-btn" @click="$emit('on-back')">
|
||||
{{ $t('form.close') }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="bg-white appBoxShadow gradido-border-radius p-4">
|
||||
<div class="bg-white app-box-shadow gradido-border-radius p-4">
|
||||
<div>
|
||||
<div class="gradido-font-15rem">{{ $t('form.sorry') }}</div>
|
||||
<hr />
|
||||
@ -7,21 +7,21 @@
|
||||
<div class="test-send_transaction_error">{{ $t('form.send_transaction_error') }}</div>
|
||||
|
||||
<hr />
|
||||
<div class="test-receiver-not-found" v-if="errorResult === 'recipient not known'">
|
||||
<div v-if="errorResult === 'recipient not known'" class="test-receiver-not-found">
|
||||
{{ $t('transaction.receiverNotFound') }}
|
||||
</div>
|
||||
<div
|
||||
class="test-receiver-not-found"
|
||||
v-if="errorResult === 'GraphQL error: The recipient account was deleted'"
|
||||
class="test-receiver-not-found"
|
||||
>
|
||||
{{ $t('transaction.receiverDeleted') }}
|
||||
</div>
|
||||
<div v-else>{{ errorResult }}</div>
|
||||
</div>
|
||||
<p class="text-center mt-5">
|
||||
<b-button variant="secondary" @click="$emit('on-back')">
|
||||
<BButton variant="secondary" @click="$emit('on-back')">
|
||||
{{ $t('form.close') }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="bg-white appBoxShadow gradido-border-radius p-3">
|
||||
<div class="bg-white app-box-shadow gradido-border-radius p-3">
|
||||
<div class="p-4" data-test="send-transaction-success-text">
|
||||
{{ $t('form.thx') }}
|
||||
<hr />
|
||||
|
||||
@ -113,8 +113,7 @@ describe('GddTransactionList', () => {
|
||||
balance: '31.76099091058520945292',
|
||||
previousBalance: '30.76',
|
||||
balanceDate: '2022-02-28T13:55:47',
|
||||
memo:
|
||||
'Um den Kessel schlingt den Reihn, Werft die Eingeweid‘ hinein. Kröte du, die Nacht und Tag Unterm kalten Steine lag,',
|
||||
memo: 'Um den Kessel schlingt den Reihn, Werft die Eingeweid‘ hinein. Kröte du, die Nacht und Tag Unterm kalten Steine lag,',
|
||||
linkedUser: {
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
@ -133,8 +132,7 @@ describe('GddTransactionList', () => {
|
||||
balance: '10',
|
||||
previousBalance: '31.75',
|
||||
balanceDate: '2022-02-23T10:55:30',
|
||||
memo:
|
||||
'Monatlanges Gift sog ein, In den Topf zuerst hinein… (William Shakespeare, Die Hexen aus Macbeth)',
|
||||
memo: 'Monatlanges Gift sog ein, In den Topf zuerst hinein… (William Shakespeare, Die Hexen aus Macbeth)',
|
||||
linkedUser: {
|
||||
firstName: 'Bibi',
|
||||
lastName: 'Bloxberg',
|
||||
|
||||
@ -2,21 +2,23 @@
|
||||
<div class="gdd-transaction-list">
|
||||
<div class="list-group">
|
||||
<div v-if="!transactions" class="test-no-transactionlist text-right">
|
||||
<b-icon icon="exclamation-triangle" class="mr-2" variant="danger"></b-icon>
|
||||
<!-- <b-icon icon="exclamation-triangle" class="mr-2" variant="danger"></b-icon>-->
|
||||
<IBiExclamationTriangle class="mr-2" />
|
||||
<small>
|
||||
{{ $t('error.no-transactionlist') }}
|
||||
</small>
|
||||
</div>
|
||||
<div v-if="transactionCount < 0" class="test-empty-transactionlist text-right">
|
||||
<b-icon icon="exclamation-triangle" class="mr-2" variant="danger"></b-icon>
|
||||
<!-- <b-icon icon="exclamation-triangle" class="mr-2" variant="danger"></b-icon>-->
|
||||
<IBiExclamationTriangle class="mr-2" />
|
||||
<small>{{ $t('error.empty-transactionlist') }}</small>
|
||||
</div>
|
||||
|
||||
<div v-for="({ id, typeId }, index) in transactions" :key="`l1-` + id">
|
||||
<transaction-list-item
|
||||
v-if="typeId === 'DECAY'"
|
||||
:typeId="typeId"
|
||||
class="pointer bg-white appBoxShadow gradido-border-radius px-4 pt-2 test-list-group-item"
|
||||
:type-id="typeId"
|
||||
class="pointer bg-white app-box-shadow gradido-border-radius px-4 pt-2 test-list-group-item"
|
||||
>
|
||||
<template #DECAY>
|
||||
<transaction-decay v-bind="transactions[index]" />
|
||||
@ -27,8 +29,8 @@
|
||||
<div v-for="({ id, typeId }, index) in transactions" :key="`l2-` + id">
|
||||
<transaction-list-item
|
||||
v-if="typeId !== 'DECAY'"
|
||||
:typeId="typeId"
|
||||
class="pointer mb-3 bg-white appBoxShadow gradido-border-radius p-3 test-list-group-item"
|
||||
:type-id="typeId"
|
||||
class="pointer mb-3 bg-white app-box-shadow gradido-border-radius p-3 test-list-group-item"
|
||||
>
|
||||
<template #SEND>
|
||||
<transaction-send v-bind="transactions[index]" />
|
||||
@ -45,7 +47,7 @@
|
||||
<template #LINK_SUMMARY>
|
||||
<transaction-link-summary
|
||||
v-bind="transactions[index]"
|
||||
:transactionLinkCount="transactionLinkCount"
|
||||
:transaction-link-count="transactionLinkCount"
|
||||
@update-transactions="updateTransactions"
|
||||
/>
|
||||
</template>
|
||||
@ -55,10 +57,10 @@
|
||||
</div>
|
||||
<b-pagination
|
||||
v-if="isPaginationVisible"
|
||||
v-model="currentPage"
|
||||
class="mt-3"
|
||||
pills
|
||||
size="lg"
|
||||
v-model="currentPage"
|
||||
:per-page="pageSize"
|
||||
:total-rows="transactionCount"
|
||||
align="center"
|
||||
@ -81,7 +83,7 @@ import TransactionCreation from '@/components/Transactions/TransactionCreation'
|
||||
import TransactionLinkSummary from '@/components/Transactions/TransactionLinkSummary'
|
||||
|
||||
export default {
|
||||
name: 'gdd-transaction-list',
|
||||
name: 'GddTransactionList',
|
||||
components: {
|
||||
TransactionListItem,
|
||||
TransactionDecay,
|
||||
@ -91,7 +93,7 @@ export default {
|
||||
TransactionLinkSummary,
|
||||
},
|
||||
props: {
|
||||
transactions: { default: () => [] },
|
||||
transactions: { type: Array, default: () => [] },
|
||||
pageSize: { type: Number, default: 25 },
|
||||
timestamp: { type: Number, default: 0 },
|
||||
transactionCount: { type: Number, default: 0 },
|
||||
@ -104,15 +106,6 @@ export default {
|
||||
currentPage: 1,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
updateTransactions() {
|
||||
this.$emit('update-transactions', {
|
||||
currentPage: this.currentPage,
|
||||
pageSize: this.pageSize,
|
||||
})
|
||||
window.scrollTo(0, 0)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isPaginationVisible() {
|
||||
return this.showPagination && this.pageSize < this.transactionCount
|
||||
@ -127,6 +120,15 @@ export default {
|
||||
handler: 'updateTransactions',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateTransactions() {
|
||||
this.$emit('update-transactions', {
|
||||
currentPage: this.currentPage,
|
||||
pageSize: this.pageSize,
|
||||
})
|
||||
window.scrollTo(0, 0)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -135,8 +137,9 @@ collaps-icon {
|
||||
width: 95%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.el-table .cell {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-list-group>
|
||||
<b-list-group-item v-if="count > 5">
|
||||
<BListGroup>
|
||||
<BListGroupItem v-if="count > 5">
|
||||
<!-- eslint-disable @intlify/vue-i18n/no-v-html -->
|
||||
<router-link
|
||||
to="/transactions"
|
||||
v-html="$t('transaction.show_all', { count })"
|
||||
></router-link>
|
||||
<!-- eslint-enable @intlify/vue-i18n/no-v-html -->
|
||||
</b-list-group-item>
|
||||
</b-list-group>
|
||||
</BListGroupItem>
|
||||
</BListGroup>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
export default {
|
||||
name: 'GddTransactionListFooter',
|
||||
props: {
|
||||
count: { count: Number },
|
||||
count: { type: Number },
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -4,40 +4,40 @@
|
||||
<div v-if="transactionGdtCount === 0" class="text-center">
|
||||
{{ $t('gdt.no-transactions') }}
|
||||
<hr />
|
||||
<b-button class="gdt-funding" :href="link" target="_blank">
|
||||
<BButton class="gdt-funding" :href="link" target="_blank">
|
||||
{{ $t('gdt.funding') }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</div>
|
||||
<div v-else-if="transactionGdtCount === -1" class="text-center">
|
||||
{{ $t('gdt.not-reachable') }}
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
v-for="{ id, amount, date, comment, gdtEntryType, factor, gdt } in transactionsGdt"
|
||||
v-else
|
||||
:key="id"
|
||||
>
|
||||
<transaction
|
||||
:id="id"
|
||||
:amount="amount"
|
||||
:date="date"
|
||||
:comment="comment"
|
||||
:gdtEntryType="gdtEntryType"
|
||||
:gdt-entry-type="gdtEntryType"
|
||||
:factor="factor"
|
||||
:gdt="gdt"
|
||||
:id="id"
|
||||
></transaction>
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<b-pagination
|
||||
<BPagination
|
||||
v-if="transactionGdtCount > pageSize"
|
||||
v-model="currentPage"
|
||||
class="mt-3"
|
||||
pills
|
||||
size="lg"
|
||||
v-model="currentPage"
|
||||
:per-page="pageSize"
|
||||
:total-rows="transactionGdtCount"
|
||||
align="center"
|
||||
:hide-ellipsis="true"
|
||||
></b-pagination>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -56,7 +56,7 @@ export default {
|
||||
},
|
||||
transactionGdtCount: { type: Number, required: true },
|
||||
pageSize: { type: Number, required: true },
|
||||
value: { type: Number, required: true },
|
||||
modelValue: { type: Number, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -66,15 +66,15 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
currentPage() {
|
||||
if (this.value !== this.currentPage) this.$emit('input', this.currentPage)
|
||||
if (this.modelValue !== this.currentPage) this.$emit('input', this.currentPage)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.el-table .cell {
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active,
|
||||
|
||||
@ -1,97 +1,147 @@
|
||||
<template>
|
||||
<div class="input-amount">
|
||||
<validation-provider
|
||||
v-if="typ === 'TransactionForm'"
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
>
|
||||
<b-form-group :label="label" :label-for="labelFor" data-test="input-amount">
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
v-bind="ariaInput"
|
||||
<template v-if="typ === 'TransactionForm'">
|
||||
<BFormGroup :label="label" :label-for="labelFor" data-test="input-amount">
|
||||
<BFormInput
|
||||
:id="labelFor"
|
||||
v-focus="amountFocused"
|
||||
:model-value="value"
|
||||
:class="$route.path === '/send' ? 'bg-248' : ''"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="text"
|
||||
:state="validated ? valid : false"
|
||||
:state="meta.valid"
|
||||
trim
|
||||
v-focus="amountFocused"
|
||||
@focus="amountFocused = true"
|
||||
@blur="normalizeAmount(valid)"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
></b-form-input>
|
||||
|
||||
<b-form-invalid-feedback v-bind="ariaMsg">
|
||||
{{ errors[0] }}
|
||||
</b-form-invalid-feedback>
|
||||
</b-form-group>
|
||||
</validation-provider>
|
||||
<b-input-group v-else append="GDD" :label="label" :label-for="labelFor">
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
@update:model-value="normalizeAmount($event)"
|
||||
@focus="amountFocused = true"
|
||||
@blur="normalizeAmount($event)"
|
||||
/>
|
||||
<BFormInvalidFeedback v-if="errorMessage">
|
||||
{{ errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</template>
|
||||
<BInputGroup v-else append="GDD" :label="label" :label-for="labelFor">
|
||||
<BFormInput
|
||||
:id="labelFor"
|
||||
v-focus="amountFocused"
|
||||
:model-value="value"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="text"
|
||||
readonly
|
||||
trim
|
||||
v-focus="amountFocused"
|
||||
@focus="amountFocused = true"
|
||||
@blur="normalizeAmount(valid)"
|
||||
></b-form-input>
|
||||
</b-input-group>
|
||||
/>
|
||||
</BInputGroup>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'InputAmount',
|
||||
props: {
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
typ: { type: String, default: 'TransactionForm' },
|
||||
name: { type: String, required: true, default: 'Amount' },
|
||||
label: { type: String, required: true, default: 'Amount' },
|
||||
placeholder: { type: String, required: true, default: 'Amount' },
|
||||
value: { type: String, required: true },
|
||||
balance: { type: Number, default: 0.0 },
|
||||
disabled: { required: false, type: Boolean, default: false },
|
||||
<!--<script>-->
|
||||
|
||||
<!--export default {-->
|
||||
<!-- name: 'InputAmount',-->
|
||||
<!-- props: {-->
|
||||
<!-- rules: {-->
|
||||
<!-- type: Object,-->
|
||||
<!-- default: () => {},-->
|
||||
<!-- },-->
|
||||
<!-- typ: { type: String, default: 'TransactionForm' },-->
|
||||
<!-- name: { type: String, required: true, default: 'Amount' },-->
|
||||
<!-- label: { type: String, required: true, default: 'Amount' },-->
|
||||
<!-- placeholder: { type: String, required: true, default: 'Amount' },-->
|
||||
<!-- value: { type: String, required: true },-->
|
||||
<!-- balance: { type: Number, default: 0.0 },-->
|
||||
<!-- disabled: { required: false, type: Boolean, default: false },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- currentValue: this.value,-->
|
||||
<!-- amountValue: 0.0,-->
|
||||
<!-- amountFocused: false,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- errorMessages() {-->
|
||||
<!-- return errorMessages-->
|
||||
<!-- },-->
|
||||
<!-- labelFor() {-->
|
||||
<!-- return this.name + '-input-field'-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- watch: {-->
|
||||
<!-- currentValue() {-->
|
||||
<!-- this.$emit('input', this.currentValue)-->
|
||||
<!-- },-->
|
||||
<!-- value() {-->
|
||||
<!-- if (this.value !== this.currentValue) this.currentValue = this.value-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- normalizeAmount(isValid) {-->
|
||||
<!-- this.amountFocused = false-->
|
||||
<!-- if (!isValid) return-->
|
||||
<!-- this.amountValue = this.currentValue.replace(',', '.')-->
|
||||
<!-- this.currentValue = this.$n(this.amountValue, 'ungroupedDecimal')-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- mounted() {-->
|
||||
<!-- if (this.value !== '') this.normalizeAmount(true)-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useField } from 'vee-validate'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const props = defineProps({
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value,
|
||||
amountValue: 0.0,
|
||||
amountFocused: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labelFor() {
|
||||
return this.name + '-input-field'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
currentValue() {
|
||||
this.$emit('input', this.currentValue)
|
||||
},
|
||||
value() {
|
||||
if (this.value !== this.currentValue) this.currentValue = this.value
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
normalizeAmount(isValid) {
|
||||
this.amountFocused = false
|
||||
if (!isValid) return
|
||||
this.amountValue = this.currentValue.replace(',', '.')
|
||||
this.currentValue = this.$n(this.amountValue, 'ungroupedDecimal')
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.value !== '') this.normalizeAmount(true)
|
||||
typ: { type: String, default: 'TransactionForm' },
|
||||
name: { type: String, required: true, default: 'Amount' },
|
||||
label: { type: String, required: true, default: 'Amount' },
|
||||
placeholder: { type: String, required: true, default: 'Amount' },
|
||||
balance: { type: Number, default: 0.0 },
|
||||
disabled: { required: false, type: Boolean, default: false },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
const { n } = useI18n()
|
||||
|
||||
const { value, meta, errorMessage } = useField(props.name, props.rules)
|
||||
|
||||
const amountFocused = ref(false)
|
||||
const amountValue = ref(0.0)
|
||||
|
||||
const labelFor = computed(() => props.name + '-input-field')
|
||||
|
||||
watch(value, (newValue) => {
|
||||
emit('update:modelValue', newValue)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
if (newValue !== value.value) value.value = newValue
|
||||
},
|
||||
)
|
||||
|
||||
const normalizeAmount = (inputValue) => {
|
||||
const oldValue = value.value
|
||||
const amountPattern = /^\d+([,.]\d{1,2})?$/
|
||||
amountFocused.value = false
|
||||
// if (!meta.valid) return
|
||||
// if (!amountPattern.test(inputValue)) {
|
||||
// value.value = oldValue
|
||||
// } else {
|
||||
value.value = inputValue.replace(',', '.')
|
||||
// }
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,79 +1,171 @@
|
||||
<!--<template>-->
|
||||
<!-- <validation-provider-->
|
||||
<!-- tag="div"-->
|
||||
<!-- :rules="rules"-->
|
||||
<!-- :name="name"-->
|
||||
<!-- v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"-->
|
||||
<!-- >-->
|
||||
<!-- <BFormGroup :label="label" :label-for="labelFor" data-test="input-email">-->
|
||||
<!-- <BFormInput-->
|
||||
<!-- v-model="currentValue"-->
|
||||
<!-- v-bind="ariaInput"-->
|
||||
<!-- data-test="input-email"-->
|
||||
<!-- :id="labelFor"-->
|
||||
<!-- :name="name"-->
|
||||
<!-- :placeholder="placeholder"-->
|
||||
<!-- type="email"-->
|
||||
<!-- :state="validated ? valid : false"-->
|
||||
<!-- trim-->
|
||||
<!-- :class="$route.path === '/send' ? 'bg-248' : ''"-->
|
||||
<!-- v-focus="emailFocused"-->
|
||||
<!-- @focus="emailFocused = true"-->
|
||||
<!-- @blur="normalizeEmail()"-->
|
||||
<!-- :disabled="disabled"-->
|
||||
<!-- autocomplete="off"-->
|
||||
<!-- />-->
|
||||
<!-- <BFormInvalidFeedback v-bind="ariaMsg">-->
|
||||
<!-- {{ errors[0] }}-->
|
||||
<!-- </BFormInvalidFeedback>-->
|
||||
<!-- </BFormGroup>-->
|
||||
<!-- </validation-provider>-->
|
||||
<!--</template>-->
|
||||
<template>
|
||||
<validation-provider
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
>
|
||||
<b-form-group :label="label" :label-for="labelFor" data-test="input-email">
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
<div>
|
||||
<BFormGroup :label="defaultTranslations.label" :label-for="labelFor" data-test="input-email">
|
||||
<BFormInput
|
||||
v-bind="ariaInput"
|
||||
data-test="input-email"
|
||||
:id="labelFor"
|
||||
:model-value="value"
|
||||
:state="meta.valid"
|
||||
data-test="input-email"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
:placeholder="defaultTranslations.placeholder"
|
||||
type="email"
|
||||
:state="validated ? valid : false"
|
||||
trim
|
||||
:class="$route.path === '/send' ? 'bg-248' : ''"
|
||||
v-focus="emailFocused"
|
||||
@focus="emailFocused = true"
|
||||
@blur="normalizeEmail()"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
></b-form-input>
|
||||
<b-form-invalid-feedback v-bind="ariaMsg">
|
||||
{{ errors[0] }}
|
||||
</b-form-invalid-feedback>
|
||||
</b-form-group>
|
||||
</validation-provider>
|
||||
@update:modelValue="normalizeEmail($event)"
|
||||
/>
|
||||
<BFormInvalidFeedback v-bind="ariaMsg">
|
||||
{{ errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'InputEmail',
|
||||
props: {
|
||||
rules: {
|
||||
default: () => {
|
||||
return {
|
||||
required: true,
|
||||
email: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
name: { type: String, required: true },
|
||||
label: { type: String, required: true },
|
||||
placeholder: { type: String, required: true },
|
||||
value: { type: String, required: true },
|
||||
disabled: { type: Boolean, required: false, default: false },
|
||||
<!--<script>-->
|
||||
<!--export default {-->
|
||||
<!-- name: 'InputEmail',-->
|
||||
<!-- props: {-->
|
||||
<!-- rules: {-->
|
||||
<!-- default: () => {-->
|
||||
<!-- return {-->
|
||||
<!-- required: true,-->
|
||||
<!-- email: true,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- name: { type: String, required: true },-->
|
||||
<!-- label: { type: String, required: true },-->
|
||||
<!-- placeholder: { type: String, required: true },-->
|
||||
<!-- modelValue: { type: String, required: true },-->
|
||||
<!-- disabled: { type: Boolean, required: false, default: false },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- currentValue: this.modelValue,-->
|
||||
<!-- emailFocused: false,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- labelFor() {-->
|
||||
<!-- return this.name + '-input-field'-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- watch: {-->
|
||||
<!-- currentValue() {-->
|
||||
<!-- this.$emit('input', this.currentValue)-->
|
||||
<!-- },-->
|
||||
<!-- modelValue() {-->
|
||||
<!-- if (this.modelValue !== this.currentValue) {-->
|
||||
<!-- this.currentValue = this.modelValue-->
|
||||
<!-- }-->
|
||||
<!-- this.$emit('onValidation')-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- normalizeEmail() {-->
|
||||
<!-- this.emailFocused = false-->
|
||||
<!-- this.currentValue = this.currentValue.trim()-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, computed, defineProps, defineEmits } from 'vue'
|
||||
import { useField } from 'vee-validate'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import * as yup from 'yup'
|
||||
|
||||
// rules: {
|
||||
// type: [String, Object, Function],
|
||||
// default: () => ({
|
||||
// required: true,
|
||||
// email: true,
|
||||
// }),
|
||||
// },
|
||||
|
||||
// Define props with default values
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
default: 'email',
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value,
|
||||
emailFocused: false,
|
||||
}
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Email',
|
||||
},
|
||||
computed: {
|
||||
labelFor() {
|
||||
return this.name + '-input-field'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'Email',
|
||||
},
|
||||
watch: {
|
||||
currentValue() {
|
||||
this.$emit('input', this.currentValue)
|
||||
},
|
||||
value() {
|
||||
if (this.value !== this.currentValue) {
|
||||
this.currentValue = this.value
|
||||
}
|
||||
this.$emit('onValidation')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
normalizeEmail() {
|
||||
this.emailFocused = false
|
||||
this.currentValue = this.currentValue.trim()
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['onValidation'])
|
||||
|
||||
// Use the useField hook for validation
|
||||
const { value, errorMessage, errors, validate, meta } = useField(() => props.name, 'required|email')
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// const emailFocused = ref(false)
|
||||
|
||||
const defaultTranslations = computed(() => ({
|
||||
label: props.label ?? t('form.email'),
|
||||
placeholder: props.placeholder ?? t('form.email'),
|
||||
}))
|
||||
|
||||
const normalizeEmail = (emailAddress) => {
|
||||
// TODO trigger blur on bootstrap input
|
||||
// emailFocused.value = false
|
||||
value.value = emailAddress.trim()
|
||||
validate()
|
||||
}
|
||||
|
||||
// Computed properties for ARIA attributes and labelFor
|
||||
const ariaInput = computed(() => ({
|
||||
'aria-invalid': errorMessage ? 'true' : false,
|
||||
'aria-describedby': `${props.name}-feedback`,
|
||||
}))
|
||||
|
||||
const ariaMsg = computed(() => ({
|
||||
id: `${props.name}-feedback`,
|
||||
}))
|
||||
|
||||
const labelFor = computed(() => `${props.name}-input-field`)
|
||||
</script>
|
||||
|
||||
@ -1,61 +1,113 @@
|
||||
<template>
|
||||
<!-- <div class="input-hour">-->
|
||||
<!-- <validation-provider-->
|
||||
<!-- tag="div"-->
|
||||
<!-- :rules="rules"-->
|
||||
<!-- :name="name"-->
|
||||
<!-- v-slot="{ valid, validated, ariaInput }"-->
|
||||
<!-- >-->
|
||||
<!-- <b-form-group :label="label" :label-for="labelFor">-->
|
||||
<!-- <b-form-input-->
|
||||
<!-- v-model="currentValue"-->
|
||||
<!-- v-bind="ariaInput"-->
|
||||
<!-- :id="labelFor"-->
|
||||
<!-- :name="name"-->
|
||||
<!-- :placeholder="placeholder"-->
|
||||
<!-- type="number"-->
|
||||
<!-- :state="validated ? valid : false"-->
|
||||
<!-- step="0.25"-->
|
||||
<!-- min="0"-->
|
||||
<!-- :max="validMaxTime"-->
|
||||
<!-- class="bg-248"-->
|
||||
<!-- ></b-form-input>-->
|
||||
<!-- </b-form-group>-->
|
||||
<!-- </validation-provider>-->
|
||||
<!-- </div>-->
|
||||
<div class="input-hour">
|
||||
<validation-provider
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
v-slot="{ valid, validated, ariaInput }"
|
||||
>
|
||||
<b-form-group :label="label" :label-for="labelFor">
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
v-bind="ariaInput"
|
||||
:id="labelFor"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="number"
|
||||
:state="validated ? valid : false"
|
||||
step="0.25"
|
||||
min="0"
|
||||
:max="validMaxTime"
|
||||
class="bg-248"
|
||||
></b-form-input>
|
||||
</b-form-group>
|
||||
</validation-provider>
|
||||
<BFormGroup :label="label" :label-for="labelFor">
|
||||
<BFormInput
|
||||
:id="labelFor"
|
||||
:model-value="currentValue"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="number"
|
||||
:state="meta.valid"
|
||||
step="0.25"
|
||||
min="0"
|
||||
:max="validMaxTime"
|
||||
class="bg-248"
|
||||
@update:model-value="currentValue = $event"
|
||||
/>
|
||||
<BFormInvalidFeedback v-if="errorMessage">
|
||||
{{ errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'InputHour',
|
||||
props: {
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
name: { type: String, required: true },
|
||||
label: { type: String, required: true },
|
||||
placeholder: { type: String, required: true },
|
||||
value: { type: Number, required: true, default: 0 },
|
||||
validMaxTime: { type: Number, required: true },
|
||||
<!--<script>-->
|
||||
<!--export default {-->
|
||||
<!-- name: 'InputHour',-->
|
||||
<!-- props: {-->
|
||||
<!-- rules: {-->
|
||||
<!-- type: Object,-->
|
||||
<!-- default: () => {},-->
|
||||
<!-- },-->
|
||||
<!-- name: { type: String, required: true },-->
|
||||
<!-- label: { type: String, required: true },-->
|
||||
<!-- placeholder: { type: String, required: true },-->
|
||||
<!-- value: { type: Number, required: true, default: 0 },-->
|
||||
<!-- validMaxTime: { type: Number, required: true },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- currentValue: 0,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- labelFor() {-->
|
||||
<!-- return this.name + '-input-field'-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- watch: {-->
|
||||
<!-- currentValue() {-->
|
||||
<!-- this.$emit('input', Number(this.currentValue))-->
|
||||
<!-- },-->
|
||||
<!-- value() {-->
|
||||
<!-- if (this.value !== this.currentValue) this.currentValue = this.value-->
|
||||
<!-- this.$emit('updateAmount', this.currentValue)-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { useField } from 'vee-validate'
|
||||
|
||||
const props = defineProps({
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: 0,
|
||||
}
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
labelFor() {
|
||||
return this.name + '-input-field'
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
watch: {
|
||||
currentValue() {
|
||||
this.$emit('input', Number(this.currentValue))
|
||||
},
|
||||
value() {
|
||||
if (this.value !== this.currentValue) this.currentValue = this.value
|
||||
this.$emit('updateAmount', this.currentValue)
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
}
|
||||
validMaxTime: {
|
||||
type: Number,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const { value: currentValue, errorMessage, meta } = useField(props.name, props.rules)
|
||||
|
||||
const labelFor = computed(() => `${props.name}-input-field`)
|
||||
</script>
|
||||
|
||||
@ -1,68 +1,61 @@
|
||||
<template>
|
||||
<validation-provider
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
>
|
||||
<b-form-group :label="label" :label-for="labelFor" data-test="input-identifier">
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
v-bind="ariaInput"
|
||||
:id="labelFor"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="text"
|
||||
:state="validated ? valid : false"
|
||||
trim
|
||||
class="bg-248"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
></b-form-input>
|
||||
<b-form-invalid-feedback v-bind="ariaMsg">
|
||||
{{ errors[0] }}
|
||||
</b-form-invalid-feedback>
|
||||
</b-form-group>
|
||||
</validation-provider>
|
||||
<BFormGroup :label="label" :label-for="labelFor" data-test="input-identifier">
|
||||
<BFormInput
|
||||
:id="labelFor"
|
||||
:model-value="value"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="text"
|
||||
:state="meta.valid"
|
||||
trim
|
||||
class="bg-248"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
@update:model-value="value = $event"
|
||||
/>
|
||||
<BFormInvalidFeedback v-if="errorMessage">
|
||||
{{ errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'InputEmail',
|
||||
props: {
|
||||
rules: {
|
||||
default: () => {
|
||||
return {
|
||||
required: true,
|
||||
validIdentifier: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
name: { type: String, required: true },
|
||||
label: { type: String, required: true },
|
||||
placeholder: { type: String, required: true },
|
||||
value: { type: String, required: true },
|
||||
disabled: { type: Boolean, required: false, default: false },
|
||||
<script setup>
|
||||
import { computed, watch } from 'vue'
|
||||
import { useField } from 'vee-validate'
|
||||
|
||||
const props = defineProps({
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
required: true,
|
||||
validIdentifier: true,
|
||||
}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value,
|
||||
name: { type: String, required: true },
|
||||
label: { type: String, required: true },
|
||||
placeholder: { type: String, required: true },
|
||||
modelValue: { type: String },
|
||||
disabled: { type: Boolean, required: false, default: false },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue', 'onValidation'])
|
||||
|
||||
const { value, meta, errorMessage } = useField(props.name, props.rules, {
|
||||
initialValue: props.modelValue,
|
||||
})
|
||||
|
||||
const labelFor = computed(() => props.name + '-input-field')
|
||||
|
||||
watch(value, (newValue) => {
|
||||
emit('update:modelValue', newValue)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
if (newValue !== value.value) {
|
||||
value.value = newValue
|
||||
emit('onValidation')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labelFor() {
|
||||
return this.name + '-input-field'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
currentValue() {
|
||||
this.$emit('input', this.currentValue)
|
||||
},
|
||||
value() {
|
||||
if (this.value !== this.currentValue) {
|
||||
this.currentValue = this.value
|
||||
}
|
||||
this.$emit('onValidation')
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
@ -1,87 +1,194 @@
|
||||
<!--<template>-->
|
||||
<!-- <validation-provider-->
|
||||
<!-- tag="div"-->
|
||||
<!-- :rules="rules"-->
|
||||
<!-- :name="name"-->
|
||||
<!-- :bails="!props.showAllErrors"-->
|
||||
<!-- :immediate="props.immediate"-->
|
||||
<!-- v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"-->
|
||||
<!-- >-->
|
||||
<!-- <BFormGroup :label="label" :label-for="labelFor">-->
|
||||
<!-- <BInputGroup>-->
|
||||
<!-- <BFormInput-->
|
||||
<!-- v-model="currentValue"-->
|
||||
<!-- v-bind="ariaInput"-->
|
||||
<!-- :id="labelFor"-->
|
||||
<!-- :name="name"-->
|
||||
<!-- :placeholder="props.placeholder"-->
|
||||
<!-- :type="showPassword ? 'text' : 'password'"-->
|
||||
<!-- :state="validated ? valid : false"-->
|
||||
<!-- data-test="password-input-field"-->
|
||||
<!-- ></BFormInput>-->
|
||||
<!-- <template #append>-->
|
||||
<!-- <BButton-->
|
||||
<!-- variant="outline-light"-->
|
||||
<!-- @click="toggleShowPassword"-->
|
||||
<!-- class="border-left-0 rounded-right"-->
|
||||
<!-- tabindex="-1"-->
|
||||
<!-- >-->
|
||||
<!-- <!– <b-icon :icon="showPassword ? 'eye' : 'eye-slash'" />–>-->
|
||||
<!-- {{ showPassword ? 'eye' : 'eye-slash' }}-->
|
||||
<!-- </BButton>-->
|
||||
<!-- </template>-->
|
||||
<!-- <BFormInvalidFeedback v-bind="ariaMsg">-->
|
||||
<!-- <div v-if="props.showAllErrors">-->
|
||||
<!-- <span v-for="error in errors" :key="error">-->
|
||||
<!-- {{ error }}-->
|
||||
<!-- <br />-->
|
||||
<!-- </span>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-else>-->
|
||||
<!-- {{ errors[0] }}-->
|
||||
<!-- </div>-->
|
||||
<!-- </BFormInvalidFeedback>-->
|
||||
<!-- </BInputGroup>-->
|
||||
<!-- </BFormGroup>-->
|
||||
<!-- </validation-provider>-->
|
||||
<!--</template>-->
|
||||
<template>
|
||||
<validation-provider
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
:bails="!showAllErrors"
|
||||
:immediate="immediate"
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
>
|
||||
<b-form-group :label="label" :label-for="labelFor">
|
||||
<b-input-group>
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
v-bind="ariaInput"
|
||||
<div>
|
||||
<BFormGroup :label="defaultTranslations.label" :label-for="labelFor">
|
||||
<BInputGroup>
|
||||
<BFormInput
|
||||
:id="labelFor"
|
||||
:model-value="value"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
:placeholder="defaultTranslations.placeholder"
|
||||
:type="showPassword ? 'text' : 'password'"
|
||||
:state="validated ? valid : false"
|
||||
:state="meta.valid"
|
||||
data-test="password-input-field"
|
||||
></b-form-input>
|
||||
<b-input-group-append>
|
||||
<b-button
|
||||
v-bind="ariaInput"
|
||||
@update:modelValue="value = $event"
|
||||
/>
|
||||
<template #append>
|
||||
<BButton
|
||||
variant="outline-light"
|
||||
@click="toggleShowPassword"
|
||||
class="border-left-0 rounded-right"
|
||||
tabindex="-1"
|
||||
@click="toggleShowPassword"
|
||||
>
|
||||
<b-icon :icon="showPassword ? 'eye' : 'eye-slash'" />
|
||||
</b-button>
|
||||
</b-input-group-append>
|
||||
<b-form-invalid-feedback v-bind="ariaMsg">
|
||||
<div v-if="showAllErrors">
|
||||
<span v-for="error in errors" :key="error">
|
||||
{{ error }}
|
||||
<br />
|
||||
</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{ errors[0] }}
|
||||
</div>
|
||||
</b-form-invalid-feedback>
|
||||
</b-input-group>
|
||||
</b-form-group>
|
||||
</validation-provider>
|
||||
<IBiEye v-if="showPassword" />
|
||||
<IBiEyeSlash v-else />
|
||||
</BButton>
|
||||
</template>
|
||||
</BInputGroup>
|
||||
<BFormInvalidFeedback v-bind="ariaMsg">
|
||||
<!-- <div v-if="showAllErrors">-->
|
||||
<!-- <span v-for="error in errors" :key="error">-->
|
||||
<!-- {{ error }}-->
|
||||
<!-- <br />-->
|
||||
<!-- </span>-->
|
||||
<!-- </div>-->
|
||||
{{ errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'InputPassword',
|
||||
props: {
|
||||
rules: {
|
||||
default: () => {
|
||||
return {
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
name: { type: String, default: 'password' },
|
||||
label: { type: String, default: 'Password' },
|
||||
placeholder: { type: String, default: 'Password' },
|
||||
value: { required: true, type: String },
|
||||
showAllErrors: { type: Boolean, default: false },
|
||||
immediate: { type: Boolean, default: false },
|
||||
<!--<script>-->
|
||||
<!--export default {-->
|
||||
<!-- name: 'InputPassword',-->
|
||||
<!-- props: {-->
|
||||
<!-- rules: {-->
|
||||
<!-- default: () => {-->
|
||||
<!-- return {-->
|
||||
<!-- required: true,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- name: { type: String, default: 'password' },-->
|
||||
<!-- label: { type: String, default: 'Password' },-->
|
||||
<!-- placeholder: { type: String, default: 'Password' },-->
|
||||
<!-- value: { required: true, type: String },-->
|
||||
<!-- showAllErrors: { type: Boolean, default: false },-->
|
||||
<!-- immediate: { type: Boolean, default: false },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- currentValue: '',-->
|
||||
<!-- showPassword: false,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- labelFor() {-->
|
||||
<!-- return this.name + '-input-field'-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- toggleShowPassword() {-->
|
||||
<!-- this.showPassword = !this.showPassword-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- watch: {-->
|
||||
<!-- currentValue() {-->
|
||||
<!-- this.$emit('input', this.currentValue)-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, defineProps, defineEmits, toRef } from 'vue'
|
||||
import { useField } from 'vee-validate'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// Define props with default values
|
||||
const props = defineProps({
|
||||
name: {
|
||||
type: String,
|
||||
default: 'password',
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: '',
|
||||
showPassword: false,
|
||||
}
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Password',
|
||||
},
|
||||
computed: {
|
||||
labelFor() {
|
||||
return this.name + '-input-field'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'Password',
|
||||
},
|
||||
methods: {
|
||||
toggleShowPassword() {
|
||||
this.showPassword = !this.showPassword
|
||||
},
|
||||
modelValue: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
watch: {
|
||||
currentValue() {
|
||||
this.$emit('input', this.currentValue)
|
||||
},
|
||||
showAllErrors: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
immediate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
|
||||
const name = toRef(props, 'name')
|
||||
// Use the useField hook for validation
|
||||
const { value, errorMessage, meta } = useField(name, 'required')
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const defaultTranslations = computed(() => ({
|
||||
label: props.label ?? t('form.password'),
|
||||
placeholder: props.placeholder ?? t('form.password'),
|
||||
}))
|
||||
|
||||
// Local state
|
||||
const showPassword = ref(false)
|
||||
|
||||
// Toggle password visibility
|
||||
const toggleShowPassword = () => {
|
||||
showPassword.value = !showPassword.value
|
||||
}
|
||||
|
||||
// Computed properties for ARIA attributes and labelFor
|
||||
const ariaInput = computed(() => ({
|
||||
'aria-invalid': meta.valid ? false : 'true',
|
||||
'aria-describedby': `${props.name}-feedback`,
|
||||
}))
|
||||
|
||||
const ariaMsg = computed(() => ({
|
||||
id: `${props.name}-feedback`,
|
||||
}))
|
||||
|
||||
const labelFor = computed(() => `${props.name}-input-field`)
|
||||
</script>
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-row class="mb-2">
|
||||
<b-col>
|
||||
<BRow class="mb-2">
|
||||
<BCol>
|
||||
<input-password
|
||||
id="new-password-input-field"
|
||||
v-model="password"
|
||||
:rules="{
|
||||
required: true,
|
||||
containsLowercaseCharacter: true,
|
||||
@ -12,32 +14,30 @@
|
||||
atLeastOneSpecialCharater: true,
|
||||
noWhitespaceCharacters: true,
|
||||
}"
|
||||
id="new-password-input-field"
|
||||
:label="register ? $t('form.password') : $t('form.password_new')"
|
||||
:showAllErrors="true"
|
||||
:show-all-errors="true"
|
||||
:immediate="true"
|
||||
:name="createId(register ? $t('form.password') : $t('form.password_new'))"
|
||||
:placeholder="register ? $t('form.password') : $t('form.password_new')"
|
||||
v-model="password"
|
||||
></input-password>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row class="mb-2">
|
||||
<b-col>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow class="mb-2">
|
||||
<BCol>
|
||||
<input-password
|
||||
id="repeat-new-password-input-field"
|
||||
v-model="passwordRepeat"
|
||||
:rules="{
|
||||
required: true,
|
||||
samePassword: value.password,
|
||||
}"
|
||||
id="repeat-new-password-input-field"
|
||||
:label="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
|
||||
:immediate="true"
|
||||
:name="createId(register ? $t('form.passwordRepeat') : $t('form.password_new_repeat'))"
|
||||
:placeholder="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
|
||||
v-model="passwordRepeat"
|
||||
></input-password>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -64,11 +64,6 @@ export default {
|
||||
passwordRepeat: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
createId(text) {
|
||||
return text.replace(/ +/g, '-')
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
passwordObject() {
|
||||
return { password: this.password, passwordRepeat: this.passwordRepeat }
|
||||
@ -82,5 +77,10 @@ export default {
|
||||
this.$emit('input', this.passwordObject)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
createId(text) {
|
||||
return text.replace(/ +/g, '-')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,62 +1,55 @@
|
||||
<template>
|
||||
<validation-provider
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
>
|
||||
<b-form-group :label="label" :label-for="labelFor" data-test="input-textarea">
|
||||
<b-form-textarea
|
||||
v-model="currentValue"
|
||||
v-bind="ariaInput"
|
||||
<div>
|
||||
<BFormGroup :label="label" :label-for="labelFor" data-test="input-textarea">
|
||||
<BFormTextarea
|
||||
:id="labelFor"
|
||||
:model-value="currentValue"
|
||||
class="bg-248"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
:state="validated ? valid : false"
|
||||
:state="meta.valid"
|
||||
trim
|
||||
rows="4"
|
||||
max-rows="4"
|
||||
:disabled="disabled"
|
||||
no-resize
|
||||
></b-form-textarea>
|
||||
<b-form-invalid-feedback v-bind="ariaMsg">
|
||||
{{ errors[0] }}
|
||||
</b-form-invalid-feedback>
|
||||
</b-form-group>
|
||||
</validation-provider>
|
||||
@update:modelValue="currentValue = $event"
|
||||
/>
|
||||
<BFormInvalidFeedback v-if="errorMessage">
|
||||
{{ errorMessage }}
|
||||
</BFormInvalidFeedback>
|
||||
</BFormGroup>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'InputTextarea',
|
||||
props: {
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
name: { type: String, required: true },
|
||||
label: { type: String, required: true },
|
||||
placeholder: { type: String, required: true },
|
||||
value: { type: String, required: true },
|
||||
disabled: { required: false, type: Boolean, default: false },
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useField } from 'vee-validate'
|
||||
|
||||
const props = defineProps({
|
||||
rules: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value,
|
||||
}
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
computed: {
|
||||
labelFor() {
|
||||
return this.name + '-input-field'
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
watch: {
|
||||
currentValue() {
|
||||
this.$emit('input', this.currentValue)
|
||||
},
|
||||
value() {
|
||||
if (this.value !== this.currentValue) this.currentValue = this.value
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
}
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const { value: currentValue, errorMessage, meta } = useField(props.name, props.rules)
|
||||
|
||||
const labelFor = computed(() => `${props.name}-input-field`)
|
||||
</script>
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
<template>
|
||||
<div class="input-username">
|
||||
<validation-provider
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
tag="div"
|
||||
:rules="rules"
|
||||
:name="name"
|
||||
:bails="!showAllErrors"
|
||||
:immediate="immediate"
|
||||
vid="username"
|
||||
v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"
|
||||
>
|
||||
<b-form-group :label="$t('form.username')" :description="$t('settings.usernameInfo')">
|
||||
<b-input-group>
|
||||
<b-form-input
|
||||
v-model="currentValue"
|
||||
v-bind="ariaInput"
|
||||
:id="labelFor"
|
||||
v-model="currentValue"
|
||||
:name="name"
|
||||
:placeholder="placeholder"
|
||||
type="text"
|
||||
@ -60,6 +60,7 @@ export default {
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
type: () => {},
|
||||
},
|
||||
name: { type: String, default: 'username' },
|
||||
label: { type: String, default: 'Username' },
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'lastName',
|
||||
name: 'LastName',
|
||||
props: {
|
||||
value: { type: String, default: '' },
|
||||
},
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
<b-dropdown size="sm" :text="currentLanguage.name + ' - ' + currentLanguage.code">
|
||||
<b-dropdown-item
|
||||
v-for="lang in locales"
|
||||
@click.prevent="saveLocale(lang.code)"
|
||||
:key="lang.code"
|
||||
@click.prevent="saveLocale(lang.code)"
|
||||
>
|
||||
{{ lang.name }}
|
||||
</b-dropdown-item>
|
||||
@ -23,6 +23,9 @@ export default {
|
||||
currentLanguage: {},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.setCurrentLanguage()
|
||||
},
|
||||
methods: {
|
||||
setLocale(locale) {
|
||||
this.$store.commit('language', locale)
|
||||
@ -66,8 +69,5 @@ export default {
|
||||
this.currentLanguage = object
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.setCurrentLanguage()
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -5,28 +5,29 @@
|
||||
v-for="lang in locales"
|
||||
:key="lang.code"
|
||||
class="pointer"
|
||||
:class="$store.state.language === lang.code ? 'c-grey' : 'c-blau'"
|
||||
:class="store.state.language === lang.code ? 'c-grey' : 'c-blau'"
|
||||
>
|
||||
<span v-if="lang.code === $store.state.language" class="locales mr-1">
|
||||
<span v-if="lang.code === store.state.language" class="locales mr-1">
|
||||
{{ lang.name }}
|
||||
</span>
|
||||
</span>
|
||||
<b-icon icon="caret-down-fill" aria-hidden="true"></b-icon>
|
||||
<!-- <b-icon icon="caret-down-fill" aria-hidden="true"></b-icon>-->
|
||||
<IBiCaretDownFill />
|
||||
</div>
|
||||
<b-collapse id="collapse-1" class="mt-4">
|
||||
<BCollapse id="collapse-1" class="mt-4">
|
||||
<span
|
||||
v-for="(lang, index) in locales"
|
||||
@click.prevent="saveLocale(lang.code)"
|
||||
:key="lang.code"
|
||||
class="pointer"
|
||||
:class="$store.state.language === lang.code ? 'c-grey' : 'c-blau'"
|
||||
:class="store.state.language === lang.code ? 'c-grey' : 'c-blau'"
|
||||
@click.prevent="saveLocale(lang.code)"
|
||||
>
|
||||
<span v-if="lang.code !== $store.state.language" v-b-toggle.collapse-1 class="locales">
|
||||
<span v-if="lang.code !== store.state.language" v-b-toggle.collapse-1 class="locales">
|
||||
{{ lang.name }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
lang.code !== $store.state.language &&
|
||||
lang.code !== store.state.language &&
|
||||
(indexOfSelectedLocale !== indexOfLastLocale ||
|
||||
(indexOfSelectedLocale === indexOfLastLocale && index !== indexOfSecondLastLocale))
|
||||
"
|
||||
@ -35,78 +36,80 @@
|
||||
{{ locales.length - 1 > index ? $t('math.pipe') : '' }}
|
||||
</span>
|
||||
</span>
|
||||
</b-collapse>
|
||||
</BCollapse>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script setup>
|
||||
import { useStore } from 'vuex'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import { useAppToast } from '@/composables/useToast'
|
||||
import locales from '@/locales/'
|
||||
import { onMounted, ref, computed } from 'vue'
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
|
||||
export default {
|
||||
name: 'LanguageSwitch',
|
||||
data() {
|
||||
return {
|
||||
locales: locales,
|
||||
currentLanguage: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setLocale(locale) {
|
||||
this.$store.commit('language', locale)
|
||||
this.currentLanguage = this.getLocaleObject(locale)
|
||||
},
|
||||
async saveLocale(locale) {
|
||||
if (this.$i18n.locale === locale) return
|
||||
this.setLocale(locale)
|
||||
if (this.$store.state.gradidoID) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
locale: locale,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.toastSuccess(this.$t('settings.language.success'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.toastSuccess(this.$t('error'))
|
||||
})
|
||||
}
|
||||
},
|
||||
getLocaleObject(code) {
|
||||
return this.locales.find((l) => l.code === code)
|
||||
},
|
||||
getNavigatorLanguage() {
|
||||
const lang = navigator.language
|
||||
if (lang) return lang.split('-')[0]
|
||||
return lang
|
||||
},
|
||||
setCurrentLanguage() {
|
||||
let locale = this.$store.state.language || this.getNavigatorLanguage() || 'en'
|
||||
let object = this.getLocaleObject(locale)
|
||||
if (!object) {
|
||||
locale = 'en'
|
||||
object = this.getLocaleObject(locale)
|
||||
}
|
||||
this.setLocale(locale)
|
||||
this.currentLanguage = object
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
indexOfSelectedLocale() {
|
||||
return this.locales.findIndex((element) => element.code === this.$store.state.language)
|
||||
},
|
||||
indexOfSecondLastLocale() {
|
||||
return this.locales.length - 2
|
||||
},
|
||||
indexOfLastLocale() {
|
||||
return this.locales.length - 1
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.setCurrentLanguage()
|
||||
},
|
||||
const store = useStore()
|
||||
const { t, locale } = useI18n()
|
||||
const { mutate } = useMutation(updateUserInfos)
|
||||
const { toastSuccess, toastError } = useAppToast()
|
||||
|
||||
const currentLang = ref({})
|
||||
|
||||
const getLocaleObject = (localeCode) => {
|
||||
return locales.find((lang) => lang.code === localeCode)
|
||||
}
|
||||
|
||||
const setLocale = (newLocale) => {
|
||||
store.commit('language', newLocale)
|
||||
currentLang.value = getLocaleObject(newLocale)
|
||||
}
|
||||
|
||||
const saveLocale = async (newLocale) => {
|
||||
if (locale.value === newLocale) return
|
||||
|
||||
setLocale(newLocale)
|
||||
if (store.state.gradidoID) {
|
||||
try {
|
||||
await mutate({ locale: newLocale })
|
||||
toastSuccess(t('settings.language.success'))
|
||||
} catch (error) {
|
||||
toastError(t('settings.language.error'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getNavigatorLang = () => {
|
||||
const navigatorLang = navigator.language
|
||||
if (navigatorLang) return navigatorLang.split('-')[0]
|
||||
return navigatorLang
|
||||
}
|
||||
|
||||
const setCurrentLanguage = () => {
|
||||
let newLocale = store.state.language || getNavigatorLang() || 'en'
|
||||
let langObject = getLocaleObject(newLocale)
|
||||
if (!langObject) {
|
||||
newLocale = 'en'
|
||||
langObject = getLocaleObject(newLocale)
|
||||
}
|
||||
|
||||
setLocale(newLocale)
|
||||
currentLang.value = langObject
|
||||
}
|
||||
|
||||
const indexOfSelectedLocale = computed(() => {
|
||||
return locales.findIndex((element) => element.code === store.state.language)
|
||||
})
|
||||
|
||||
const indexOfSecondLastLocale = computed(() => {
|
||||
return locales.length - 2
|
||||
})
|
||||
|
||||
const indexOfLastLocale = computed(() => {
|
||||
return locales.length - 1
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
setCurrentLanguage()
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
<script>
|
||||
export default {
|
||||
name: 'LanguageSwitch',
|
||||
props: {
|
||||
language: { type: String },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selected: null,
|
||||
@ -22,12 +25,6 @@ export default {
|
||||
],
|
||||
}
|
||||
},
|
||||
props: {
|
||||
language: { type: String },
|
||||
},
|
||||
created() {
|
||||
this.selected = this.$store.state.language
|
||||
},
|
||||
computed: {
|
||||
languageObject() {
|
||||
return this.selected
|
||||
@ -38,5 +35,8 @@ export default {
|
||||
this.$emit('update-language', this.languageObject)
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.selected = this.$store.state.language
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="redeem-information">
|
||||
<b-jumbotron bg-variant="muted" text-variant="dark" border-variant="info">
|
||||
<BCard bg-variant="muted" text-variant="dark" border-variant="info">
|
||||
<h1 v-if="amount === ''">{{ $t('gdd_per_link.redeemlink-error') }}</h1>
|
||||
<h1 v-if="isContributionLink && amount !== ''">
|
||||
{{ CONFIG.COMMUNITY_NAME }}
|
||||
{{ $t('contribution-link.thanksYouWith') }} {{ amount | GDD }}
|
||||
{{ $t('contribution-link.thanksYouWith') }} {{ $filters.GDD(amount) }}
|
||||
</h1>
|
||||
<h1 v-if="!isContributionLink && amount !== ''">
|
||||
{{ user.firstName }}
|
||||
{{ $t('transaction-link.send_you') }} {{ amount | GDD }}
|
||||
{{ $t('transaction-link.send_you') }} {{ $filters.GDD(amount) }}
|
||||
</h1>
|
||||
<b>{{ memo }}</b>
|
||||
</b-jumbotron>
|
||||
</BCard>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,25 +1,25 @@
|
||||
<template>
|
||||
<div class="redeem-logged-out">
|
||||
<redeem-information v-bind="linkData" :isContributionLink="isContributionLink" />
|
||||
<redeem-information v-bind="linkData" :is-contribution-link="isContributionLink" />
|
||||
|
||||
<b-jumbotron>
|
||||
<BCard>
|
||||
<div class="mb-2">
|
||||
<h2>{{ $t('gdd_per_link.redeem') }}</h2>
|
||||
</div>
|
||||
|
||||
<b-row>
|
||||
<b-col sm="12" md="6">
|
||||
<BRow>
|
||||
<BCol sm="12" md="6">
|
||||
<p>{{ $t('gdd_per_link.no-account') }}</p>
|
||||
<b-button variant="primary" :to="register">
|
||||
<BButton variant="primary" :to="register">
|
||||
{{ $t('gdd_per_link.to-register') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
<b-col sm="12" md="6" class="mt-4 mt-lg-0">
|
||||
</BButton>
|
||||
</BCol>
|
||||
<BCol sm="12" md="6" class="mt-4 mt-lg-0">
|
||||
<p>{{ $t('gdd_per_link.has-account') }}</p>
|
||||
<b-button variant="gradido" :to="login">{{ $t('gdd_per_link.to-login') }}</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-jumbotron>
|
||||
<BButton variant="gradido" :to="login">{{ $t('gdd_per_link.to-login') }}</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCard>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -28,10 +28,10 @@ import { authLinks } from '@/mixins/authLinks'
|
||||
|
||||
export default {
|
||||
name: 'RedeemLoggedOut',
|
||||
mixins: [authLinks],
|
||||
components: {
|
||||
RedeemInformation,
|
||||
},
|
||||
mixins: [authLinks],
|
||||
props: {
|
||||
linkData: { type: Object, required: true },
|
||||
isContributionLink: { type: Boolean, default: false },
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="redeem-self-creator">
|
||||
<redeem-information v-bind="linkData" :isContributionLink="isContributionLink" />
|
||||
<redeem-information v-bind="linkData" :is-contribution-link="isContributionLink" />
|
||||
|
||||
<b-jumbotron>
|
||||
<BCard>
|
||||
<div class="mb-3 text-center">
|
||||
<div class="mt-3">
|
||||
{{ $t('gdd_per_link.no-redeem') }}
|
||||
<b-link to="/transactions">
|
||||
<BLink to="/transactions">
|
||||
<b>{{ $t('gdd_per_link.link-overview') }}</b>
|
||||
</b-link>
|
||||
</BLink>
|
||||
</div>
|
||||
</div>
|
||||
</b-jumbotron>
|
||||
</BCard>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
<template>
|
||||
<div class="redeem-valid">
|
||||
<redeem-information v-bind="linkData" :isContributionLink="isContributionLink" />
|
||||
<b-jumbotron>
|
||||
<redeem-information v-bind="linkData" :is-contribution-link="isContributionLink" />
|
||||
<BCard>
|
||||
<div class="mb-3 text-center">
|
||||
<b-button
|
||||
<BButton
|
||||
variant="gradido"
|
||||
@click="$emit('mutation-link', linkData.amount)"
|
||||
size="lg"
|
||||
:disabled="!validLink"
|
||||
@click="$emit('mutation-link', linkData.amount)"
|
||||
>
|
||||
{{ $t('gdd_per_link.redeem') }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</div>
|
||||
</b-jumbotron>
|
||||
</BCard>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="redeemed-text-box">
|
||||
<b-jumbotron bg-variant="muted" text-variant="dark" border-variant="info">
|
||||
<BCard bg-variant="muted" text-variant="dark" border-variant="info">
|
||||
<h1>
|
||||
{{ text }}
|
||||
</h1>
|
||||
</b-jumbotron>
|
||||
</BCard>
|
||||
|
||||
<div class="text-center">
|
||||
<b-button to="/overview">{{ $t('back') }}</b-button>
|
||||
<BButton to="/overview">{{ $t('back') }}</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div class="navbar-component">
|
||||
<div class="navbar-element">
|
||||
<b-navbar toggleable="lg" class="pr-4">
|
||||
<b-navbar-brand>
|
||||
<b-img
|
||||
<BNavbar toggleable="lg" class="pr-4">
|
||||
<BNavbarBrand>
|
||||
<BImg
|
||||
class="mt-lg--2 mt-3 mb-3 d-none d-lg-block zindex10"
|
||||
:src="logo"
|
||||
width="200"
|
||||
@ -12,11 +12,11 @@
|
||||
<div v-b-toggle.sidebar-mobile variant="link" class="d-block d-lg-none">
|
||||
<span class="navbar-toggler-icon h2"></span>
|
||||
</div>
|
||||
</b-navbar-brand>
|
||||
</BNavbarBrand>
|
||||
|
||||
<b-img class="sheet-img position-absolute zindex-1" :src="sheet"></b-img>
|
||||
<BImg class="sheet-img position-absolute zindex-1" :src="sheet"></BImg>
|
||||
|
||||
<b-navbar-nav class="ml-auto" right>
|
||||
<BNavbarNav class="ml-auto" right>
|
||||
<router-link to="/settings">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="mr-3">
|
||||
@ -33,9 +33,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</router-link>
|
||||
</b-navbar-nav>
|
||||
</b-navbar>
|
||||
<!-- <div class="alertBox">
|
||||
</BNavbarNav>
|
||||
</BNavbar>
|
||||
<!-- <div class="alert-box">
|
||||
<b-alert show dismissible variant="light" class="nav-alert text-dark">
|
||||
<small>{{ $t('1000thanks') }}</small>
|
||||
</b-alert>
|
||||
@ -82,7 +82,7 @@ export default {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.authNavbar > .nav-link {
|
||||
.auth-navbar > .nav-link {
|
||||
color: #383838 !important;
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ export default {
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
|
||||
.authNavbar > .router-link-exact-active {
|
||||
.auth-navbar > .router-link-exact-active {
|
||||
color: #0e79bc !important;
|
||||
}
|
||||
|
||||
@ -103,31 +103,36 @@ button.navbar-toggler > span.navbar-toggler-icon {
|
||||
left: 50%;
|
||||
max-width: 64%;
|
||||
}
|
||||
.alertBox {
|
||||
|
||||
.alert-box {
|
||||
left: 20%;
|
||||
right: 20%;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
top: 25px;
|
||||
}
|
||||
@media screen and (max-width: 1170px) {
|
||||
|
||||
@media screen and (width <= 1170px) {
|
||||
.sheet-img {
|
||||
left: 20%;
|
||||
}
|
||||
.alertBox {
|
||||
|
||||
.alert-box {
|
||||
position: static;
|
||||
margin-left: 5%;
|
||||
margin-right: 5%;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 450px) {
|
||||
|
||||
@media screen and (width <= 450px) {
|
||||
.navbar-element {
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: #f5f5f5e6;
|
||||
}
|
||||
|
||||
.sheet-img {
|
||||
left: 5%;
|
||||
max-width: 61%;
|
||||
|
||||
@ -4,74 +4,74 @@
|
||||
id="side-menu"
|
||||
ref="sideMenu"
|
||||
class="gradido-border-radius pt-2 bg-white"
|
||||
:class="shadow ? 'appBoxShadow' : ''"
|
||||
:class="shadow ? 'app-box-shadow' : ''"
|
||||
>
|
||||
<div class="mb-3 mt-3">
|
||||
<b-nav vertical class="w-200">
|
||||
<b-nav-item to="/overview" class="mb-3" active-class="activeRoute">
|
||||
<b-img src="/img/svg/home.svg" height="20" class="svg-icon" />
|
||||
<BNav vertical class="w-200">
|
||||
<BNavItem to="/overview" class="mb-3" active-class="active-route">
|
||||
<BImg src="/img/svg/home.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2">{{ $t('navigation.overview') }}</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/send" class="mb-3" active-class="activeRoute">
|
||||
<b-icon icon="cash" aria-hidden="true"></b-icon>
|
||||
</BNavItem>
|
||||
<BNavItem to="/send" class="mb-3" active-class="active-route">
|
||||
<IBiCash />
|
||||
<span class="ml-2">{{ $t('navigation.send') }}</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/transactions" :class="transactionClass" active-class="activeRoute">
|
||||
<b-img src="/img/svg/transaction.svg" height="20" class="svg-icon" />
|
||||
</BNavItem>
|
||||
<BNavItem to="/transactions" :class="transactionClass" active-class="active-route">
|
||||
<BImg src="/img/svg/transaction.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2">{{ $t('navigation.transactions') }}</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/community" class="mb-3" active-class="activeRoute">
|
||||
<b-img src="/img/svg/community.svg" height="20" class="svg-icon" />
|
||||
</BNavItem>
|
||||
<BNavItem to="/community" class="mb-3" active-class="active-route">
|
||||
<BImg src="/img/svg/community.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2">{{ $t('creation') }}</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/information" class="mb-3" active-class="activeRoute">
|
||||
<b-img src="/img/svg/info.svg" height="20" class="svg-icon" />
|
||||
</BNavItem>
|
||||
<BNavItem to="/information" class="mb-3" active-class="active-route">
|
||||
<BImg src="/img/svg/info.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2">{{ $t('navigation.info') }}</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/circles" v-if="isHumhub" class="mb-3" active-class="activeRoute">
|
||||
<b-img src="/img/svg/circles.svg" height="20" class="svg-icon" />
|
||||
</BNavItem>
|
||||
<BNavItem v-if="isHumhub" to="/circles" class="mb-3" active-class="active-route">
|
||||
<BImg src="/img/svg/circles.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2">{{ $t('navigation.circles') }}</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item to="/usersearch" v-if="isGMS" active-class="activeRoute">
|
||||
<b-img src="/img/loupe.png" height="20" />
|
||||
</BNavItem>
|
||||
<BNavItem v-if="isGMS" to="/usersearch" active-class="active-route">
|
||||
<BImg src="/img/loupe.png" height="20" />
|
||||
<span class="ml-2">{{ $t('navigation.usersearch') }}</span>
|
||||
</b-nav-item>
|
||||
</b-nav>
|
||||
</BNavItem>
|
||||
</BNav>
|
||||
<hr class="m-3" />
|
||||
<b-nav vertical class="w-100">
|
||||
<b-nav-item
|
||||
<BNav vertical class="w-100">
|
||||
<BNavItem
|
||||
to="/settings"
|
||||
class="mb-3"
|
||||
active-class="activeRoute"
|
||||
active-class="active-route"
|
||||
data-test="settings-menu"
|
||||
>
|
||||
<b-img src="/img/svg/settings.svg" height="20" class="svg-icon" />
|
||||
<BImg src="/img/svg/settings.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2">{{ $t('navigation.settings') }}</span>
|
||||
<b-badge v-if="!$store.state.username" variant="warning">
|
||||
<BBadge v-if="!$store.state.username" variant="warning">
|
||||
{{ $t('settings.newSettings') }}
|
||||
</b-badge>
|
||||
</b-nav-item>
|
||||
<b-nav-item
|
||||
class="mb-3 text-light"
|
||||
</BBadge>
|
||||
</BNavItem>
|
||||
<BNavItem
|
||||
v-if="$store.state.roles && $store.state.roles.length > 0"
|
||||
class="mb-3 text-light"
|
||||
active-class="active-route"
|
||||
@click="$emit('admin')"
|
||||
active-class="activeRoute"
|
||||
>
|
||||
<b-icon icon="shield-check" aria-hidden="true"></b-icon>
|
||||
<IBiShieldCheck />
|
||||
<span class="ml-2">
|
||||
{{ $t('navigation.admin_area') }}
|
||||
</span>
|
||||
</b-nav-item>
|
||||
<b-nav-item
|
||||
</BNavItem>
|
||||
<BNavItem
|
||||
class="font-weight-bold"
|
||||
@click="$emit('logout')"
|
||||
active-class="activeRoute"
|
||||
active-class="active-route"
|
||||
data-test="logout-menu"
|
||||
@click="$emit('logout')"
|
||||
>
|
||||
<b-img src="/img/svg/logout.svg" height="20" class="svg-icon" />
|
||||
<BImg src="/img/svg/logout.svg" height="20" class="svg-icon" />
|
||||
<span class="ml-2 text-205">{{ $t('navigation.logout') }}</span>
|
||||
</b-nav-item>
|
||||
</b-nav>
|
||||
</BNavItem>
|
||||
</BNav>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -87,7 +87,7 @@ export default {
|
||||
computed: {
|
||||
transactionClass() {
|
||||
if (this.$route.path === '/gdt') {
|
||||
return 'mb-3 activeRoute'
|
||||
return 'mb-3 active-route'
|
||||
}
|
||||
return 'mb-3'
|
||||
},
|
||||
@ -102,32 +102,37 @@ export default {
|
||||
</script>
|
||||
<style>
|
||||
.nav-link {
|
||||
color: rgb(56, 56, 56);
|
||||
color: rgb(56 56 56);
|
||||
}
|
||||
.activeRoute {
|
||||
|
||||
.active-route {
|
||||
font-weight: bold;
|
||||
color: rgb(2, 2, 1);
|
||||
border-left: 4px rgb(219, 129, 19) solid;
|
||||
color: rgb(2 2 1);
|
||||
border-left: 4px rgb(219 129 19) solid;
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
filter: brightness(1) invert(0);
|
||||
}
|
||||
|
||||
.activeRoute .svg-icon {
|
||||
.active-route .svg-icon {
|
||||
filter: brightness(0) invert(0);
|
||||
}
|
||||
|
||||
#component-sidebar {
|
||||
min-width: 200px;
|
||||
}
|
||||
@media screen and (min-width: 1025px) {
|
||||
|
||||
@media screen and (width >= 1025px) {
|
||||
#side-menu {
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
#component-sidebar {
|
||||
min-width: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@media screen and (min-width: 1075px) {
|
||||
#side-menu {
|
||||
|
||||
@ -1,33 +1,53 @@
|
||||
<template>
|
||||
<div>
|
||||
<b-sidebar
|
||||
id="sidebar-mobile"
|
||||
sidebar-class="sidebar-radius"
|
||||
width="220px"
|
||||
:backdrop="true"
|
||||
bg-variant="white"
|
||||
no-header-close
|
||||
>
|
||||
<b-img src="img/svg/lines.png" />
|
||||
<div class="py-2">
|
||||
<sidebar @admin="$emit('admin')" @logout="$emit('logout')" :shadow="false" />
|
||||
</div>
|
||||
</b-sidebar>
|
||||
</div>
|
||||
<BCollapse
|
||||
id="sidebar-mobile"
|
||||
sidebar-class="sidebar-radius"
|
||||
:backdrop="true"
|
||||
bg-variant="white"
|
||||
no-header-close
|
||||
horizontal
|
||||
skip-animation
|
||||
>
|
||||
<div class="mobile-sidebar-wrapper py-2">
|
||||
<BImg src="img/svg/lines.png" />
|
||||
<sidebar :shadow="false" @admin="emit('admin')" @logout="emit('logout')" />
|
||||
</div>
|
||||
<div v-b-toggle.sidebar-mobile class="simple-overlay" />
|
||||
</BCollapse>
|
||||
</template>
|
||||
<script>
|
||||
import Sidebar from '@/components/Menu/Sidebar'
|
||||
|
||||
export default {
|
||||
name: 'MobileSidebar',
|
||||
components: {
|
||||
Sidebar,
|
||||
},
|
||||
}
|
||||
<script setup>
|
||||
const emit = defineEmits(['admin', 'logout'])
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.sidebar-radius {
|
||||
.mobile-sidebar-wrapper {
|
||||
width: 220px;
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
border-bottom-right-radius: 26px;
|
||||
border-top-right-radius: 26px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
#sidebar-mobile {
|
||||
width: 220px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.simple-overlay {
|
||||
position: absolute;
|
||||
left: 200px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: #212529;
|
||||
z-index: 9;
|
||||
opacity: 0.6;
|
||||
width: calc(100vw - 200px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="community-news">
|
||||
<div v-for="item in News" :key="item.locale">
|
||||
<b-card
|
||||
<BCard
|
||||
v-if="item.locale === $i18n.locale"
|
||||
class="bg-white appBoxShadow gradido-border-radius"
|
||||
class="bg-white app-box-shadow gradido-border-radius"
|
||||
>
|
||||
<b-card-body>
|
||||
<b-card-title class="h2">{{ item.text }}</b-card-title>
|
||||
<BCardBody>
|
||||
<BCardTitle class="h2">{{ item.text }}</BCardTitle>
|
||||
|
||||
<div class="h3">{{ item.date }}</div>
|
||||
|
||||
<b-row class="my-5">
|
||||
<b-col>
|
||||
<BRow class="my-5">
|
||||
<BCol>
|
||||
{{ item.extra }}
|
||||
<br />
|
||||
<br />
|
||||
@ -21,25 +21,25 @@
|
||||
<span v-if="item.email">
|
||||
<a :href="'mailto:' + item.email">{{ item.email }}</a>
|
||||
</span>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row class="my-5">
|
||||
<b-col cols="12">
|
||||
<BRow class="my-5">
|
||||
<BCol cols="12">
|
||||
<div class="text-lg-right">
|
||||
<b-button v-if="item.url" variant="gradido" :href="item.url" target="_blank">
|
||||
<BButton v-if="item.url" variant="gradido" :href="item.url" target="_blank">
|
||||
{{ item.button }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
<RouterLink v-else-if="item.internUrl" to="/settings/extern">
|
||||
<b-button variant="gradido">
|
||||
<BButton variant="gradido">
|
||||
{{ item.button }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</RouterLink>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-card-body>
|
||||
</b-card>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCardBody>
|
||||
</BCard>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -60,6 +60,6 @@ export default {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 350px 350px;
|
||||
background-image: url(/img/svg/Gradido_Blaetter_Mainpage.svg) !important;
|
||||
background-image: url('/img/svg/Gradido_Blaetter_Mainpage.svg') !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="figure-qr-code">
|
||||
<div class="qrbox">
|
||||
<div>
|
||||
<q-r-canvas :options="options" class="canvas mb-3" id="qrcanvas" ref="canvas" />
|
||||
<q-r-canvas id="qrcanvas" ref="canvas" :options="options" class="canvas mb-3" />
|
||||
</div>
|
||||
<a
|
||||
id="download"
|
||||
@ -62,6 +62,7 @@ export default {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
width: 90%;
|
||||
max-width: 300px;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="session-logout-timeout">
|
||||
<b-modal
|
||||
<BModal
|
||||
id="modalSessionTimeOut"
|
||||
class="bg-variant-danger"
|
||||
hide-header-close
|
||||
@ -8,8 +8,8 @@
|
||||
hide-footer
|
||||
no-close-on-backdrop
|
||||
>
|
||||
<b-card header-tag="header" footer-tag="footer">
|
||||
<b-card-text>
|
||||
<BCard header-tag="header" footer-tag="footer">
|
||||
<BCardText>
|
||||
<div class="p-3 h2">{{ $t('session.warningText') }}</div>
|
||||
<div class="p-3">
|
||||
{{ $t('session.lightText') }}
|
||||
@ -19,85 +19,154 @@
|
||||
<b>{{ tokenExpiresInSeconds }}</b>
|
||||
{{ $t('time.seconds') }}
|
||||
</div>
|
||||
</b-card-text>
|
||||
<b-row>
|
||||
<b-col class="text-center">
|
||||
<b-button size="lg" variant="success" @click="handleOk">
|
||||
</BCardText>
|
||||
<BRow>
|
||||
<BCol class="text-center">
|
||||
<BButton size="lg" variant="success" @click="handleOk">
|
||||
{{ $t('session.extend') }}
|
||||
</b-button>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-card>
|
||||
</BButton>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCard>
|
||||
<template #modal-footer>
|
||||
<b-button size="sm" variant="danger" @click="$emit('logout')">
|
||||
<BButton size="sm" variant="danger" @click="$emit('logout')">
|
||||
{{ $t('navigation.logout') }}
|
||||
</b-button>
|
||||
<b-button size="lg" variant="success" @click="handleOk">
|
||||
</BButton>
|
||||
<BButton size="lg" variant="success" @click="handleOk">
|
||||
{{ $t('session.extend') }}
|
||||
</b-button>
|
||||
</BButton>
|
||||
</template>
|
||||
</b-modal>
|
||||
</BModal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<!--<script>-->
|
||||
<!--import { verifyLogin } from '@/graphql/queries'-->
|
||||
|
||||
<!--export default {-->
|
||||
<!-- name: 'SessionLogoutTimeout',-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- now: new Date().getTime(),-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- timers: {-->
|
||||
<!-- tokenExpires: {-->
|
||||
<!-- time: 15000,-->
|
||||
<!-- autostart: true,-->
|
||||
<!-- repeat: true,-->
|
||||
<!-- immediate: true,-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- tokenExpires() {-->
|
||||
<!-- this.now = new Date().getTime()-->
|
||||
<!-- if (this.tokenExpiresInSeconds < 75 && this.timers.tokenExpires.time !== 1000) {-->
|
||||
<!-- this.timers.tokenExpires.time = 1000-->
|
||||
<!-- this.$timer.restart('tokenExpires')-->
|
||||
<!-- this.$bvModal.show('modalSessionTimeOut')-->
|
||||
<!-- }-->
|
||||
<!-- if (this.tokenExpiresInSeconds === 0) {-->
|
||||
<!-- this.$timer.stop('tokenExpires')-->
|
||||
<!-- this.$emit('logout')-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- handleOk(bvModalEvent) {-->
|
||||
<!-- bvModalEvent.preventDefault()-->
|
||||
<!-- this.$apollo-->
|
||||
<!-- .query({-->
|
||||
<!-- query: verifyLogin,-->
|
||||
<!-- fetchPolicy: 'network-only',-->
|
||||
<!-- })-->
|
||||
<!-- .then((result) => {-->
|
||||
<!-- this.timers.tokenExpires.time = 15000-->
|
||||
<!-- this.$timer.restart('tokenExpires')-->
|
||||
<!-- this.$bvModal.hide('modalSessionTimeOut')-->
|
||||
<!-- })-->
|
||||
<!-- .catch(() => {-->
|
||||
<!-- this.$timer.stop('tokenExpires')-->
|
||||
<!-- this.$emit('logout')-->
|
||||
<!-- })-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- tokenExpiresInSeconds() {-->
|
||||
<!-- const remainingSecs = Math.floor(-->
|
||||
<!-- (new Date(this.$store.state.tokenTime * 1000).getTime() - this.now) / 1000,-->
|
||||
<!-- )-->
|
||||
<!-- return remainingSecs <= 0 ? 0 : remainingSecs-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- beforeDestroy() {-->
|
||||
<!-- this.$timer.stop('tokenExpires')-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
<script setup>
|
||||
// TODO to be checked and fixed
|
||||
import { ref, computed, onBeforeUnmount } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useLazyQuery } from '@vue/apollo-composable'
|
||||
import { useTimer } from 'vue-timer-hook' // TODO change to updated version
|
||||
import { useModal } from 'bootstrap-vue-next'
|
||||
import { verifyLogin } from '@/graphql/queries'
|
||||
|
||||
export default {
|
||||
name: 'SessionLogoutTimeout',
|
||||
data() {
|
||||
return {
|
||||
now: new Date().getTime(),
|
||||
}
|
||||
},
|
||||
timers: {
|
||||
tokenExpires: {
|
||||
time: 15000,
|
||||
autostart: true,
|
||||
repeat: true,
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
tokenExpires() {
|
||||
this.now = new Date().getTime()
|
||||
if (this.tokenExpiresInSeconds < 75 && this.timers.tokenExpires.time !== 1000) {
|
||||
this.timers.tokenExpires.time = 1000
|
||||
this.$timer.restart('tokenExpires')
|
||||
this.$bvModal.show('modalSessionTimeOut')
|
||||
}
|
||||
if (this.tokenExpiresInSeconds === 0) {
|
||||
this.$timer.stop('tokenExpires')
|
||||
this.$emit('logout')
|
||||
}
|
||||
},
|
||||
handleOk(bvModalEvent) {
|
||||
bvModalEvent.preventDefault()
|
||||
this.$apollo
|
||||
.query({
|
||||
query: verifyLogin,
|
||||
fetchPolicy: 'network-only',
|
||||
})
|
||||
.then((result) => {
|
||||
this.timers.tokenExpires.time = 15000
|
||||
this.$timer.restart('tokenExpires')
|
||||
this.$bvModal.hide('modalSessionTimeOut')
|
||||
})
|
||||
.catch(() => {
|
||||
this.$timer.stop('tokenExpires')
|
||||
this.$emit('logout')
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
tokenExpiresInSeconds() {
|
||||
const remainingSecs = Math.floor(
|
||||
(new Date(this.$store.state.tokenTime * 1000).getTime() - this.now) / 1000,
|
||||
)
|
||||
return remainingSecs <= 0 ? 0 : remainingSecs
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$timer.stop('tokenExpires')
|
||||
},
|
||||
const store = useStore()
|
||||
const { result, load: verifyLoginQuery } = useLazyQuery(verifyLogin)
|
||||
const { modal } = useModal()
|
||||
const timer = useTimer()
|
||||
|
||||
const emit = defineEmits(['logout'])
|
||||
|
||||
const now = ref(new Date().getTime())
|
||||
|
||||
const tokenExpiresInSeconds = computed(() => {
|
||||
const remainingSecs = Math.floor(
|
||||
(new Date(store.state.tokenTime * 1000).getTime() - now.value) / 1000,
|
||||
)
|
||||
return remainingSecs <= 0 ? 0 : remainingSecs
|
||||
})
|
||||
|
||||
const handleOk = async () => {
|
||||
return 'OK'
|
||||
}
|
||||
|
||||
// const tokenExpires = () => {
|
||||
// now.value = new Date().getTime()
|
||||
// if (tokenExpiresInSeconds.value < 75 && timer.value.tokenExpires.time !== 1000) {
|
||||
// timer.value.tokenExpires.time = 1000
|
||||
// restartTimer('tokenExpires')
|
||||
// modal.show('modalSessionTimeOut')
|
||||
// }
|
||||
// if (tokenExpiresInSeconds.value === 0) {
|
||||
// stopTimer('tokenExpires')
|
||||
// emit('logout')
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// const handleOk = (bvModalEvent) => {
|
||||
// bvModalEvent.preventDefault()
|
||||
// verifyLoginQuery({
|
||||
// fetchPolicy: 'network-only',
|
||||
// })
|
||||
// .then(() => {
|
||||
// timer.value.tokenExpires.time = 15000
|
||||
// restartTimer('tokenExpires')
|
||||
// modal.hide('modalSessionTimeOut')
|
||||
// })
|
||||
// .catch(() => {
|
||||
// stopTimer('tokenExpires')
|
||||
// emit('logout')
|
||||
// })
|
||||
// }
|
||||
//
|
||||
// // Start the timer
|
||||
// startTimer('tokenExpires', {
|
||||
// time: 15000,
|
||||
// callback: tokenExpires,
|
||||
// immediate: true,
|
||||
// })
|
||||
//
|
||||
// onBeforeUnmount(() => {
|
||||
// stopTimer('tokenExpires')
|
||||
// })
|
||||
</script>
|
||||
|
||||
@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<div class="community-member mt-3 mt-lg-0">
|
||||
<div class="community-member mt-3 mt-lg-0 position-relative">
|
||||
<div class="text-center bg-gradient">
|
||||
<b-badge class="position-absolute mt--2 ml--5 px-3 bg-gradient">
|
||||
<BBadge class="position-absolute mt--2 ml--5 px-3 bg-gradient">
|
||||
{{ $t('member') }}
|
||||
</b-badge>
|
||||
</BBadge>
|
||||
</div>
|
||||
<div
|
||||
class="community-member bg-white appBoxShadow gradido-border-radius p-4 border border-success"
|
||||
class="community-member bg-white app-box-shadow gradido-border-radius p-4 border border-success"
|
||||
>
|
||||
<b-row>
|
||||
<b-col cols="9">
|
||||
<BRow>
|
||||
<BCol cols="9">
|
||||
<div class="h4">{{ $t('community.communityMember') }}</div>
|
||||
<div>{{ CONFIG.COMMUNITY_NAME }}</div>
|
||||
</b-col>
|
||||
<b-col cols="3" align-self="end" class="border-left border-light">
|
||||
<b-icon icon="people"></b-icon>
|
||||
</BCol>
|
||||
<BCol cols="3" align-self="end" class="border-left border-light">
|
||||
<IBiPeople />
|
||||
{{ totalUsers }}
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -1,88 +1,94 @@
|
||||
<template>
|
||||
<div class="gdd-amount translucent-color-opacity">
|
||||
<div class="text-center">
|
||||
<b-badge
|
||||
<BBadge
|
||||
v-if="badgeShow"
|
||||
class="position-absolute mt--2 ml--4 px-3 zindex1"
|
||||
:class="showStatus ? 'bg-gradient' : ''"
|
||||
:variant="showStatus ? '' : 'light'"
|
||||
>
|
||||
{{ $t('GDD') }}
|
||||
</b-badge>
|
||||
</BBadge>
|
||||
</div>
|
||||
<div
|
||||
class="wallet-amount bg-white appBoxShadow gradido-border-radius p-4 border"
|
||||
class="wallet-amount bg-white app-box-shadow gradido-border-radius p-4 border"
|
||||
:class="
|
||||
showStatus || path === '/overview'
|
||||
? 'gradido-global-border-color-accent'
|
||||
: 'border-light opacity-05'
|
||||
"
|
||||
>
|
||||
<b-row>
|
||||
<b-col class="h4">{{ $t('gddKonto') }}</b-col>
|
||||
</b-row>
|
||||
<BRow>
|
||||
<BCol class="h4">{{ $t('gddKonto') }}</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-row>
|
||||
<b-col cols="9">
|
||||
<b-icon
|
||||
icon="layers"
|
||||
class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"
|
||||
></b-icon>
|
||||
<BRow>
|
||||
<BCol cols="9">
|
||||
<!-- <b-icon-->
|
||||
<!-- icon="layers"-->
|
||||
<!-- class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"-->
|
||||
<!-- ></b-icon>-->
|
||||
<IBiLayers />
|
||||
<span v-if="hideAmount" class="font-weight-bold gradido-global-color-accent">
|
||||
{{ $t('asterisks') }}
|
||||
</span>
|
||||
<span v-else class="font-weight-bold gradido-global-color-accent">
|
||||
{{ balance | GDD }}
|
||||
{{ $filters.GDD(balance) }}
|
||||
</span>
|
||||
</b-col>
|
||||
<b-col cols="3" class="border-left border-light">
|
||||
<b-icon
|
||||
:icon="hideAmount ? 'eye-slash' : 'eye'"
|
||||
class="mr-3 gradido-global-border-color-accent pointer hover-icon"
|
||||
@click="updateHideAmountGDD"
|
||||
></b-icon>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol cols="3" class="border-left border-light">
|
||||
<!-- <b-icon-->
|
||||
<!-- :icon="hideAmount ? 'eye-slash' : 'eye'"-->
|
||||
<!-- class="mr-3 gradido-global-border-color-accent pointer hover-icon"-->
|
||||
<!-- @click="updateHideAmountGDD"-->
|
||||
<!-- ></b-icon>-->
|
||||
<button class="transparent-button" @click="updateHideAmountGDD">
|
||||
<IBiEyeSlash v-if="hideAmount" />
|
||||
<IBiEye v-else />
|
||||
</button>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
|
||||
export default {
|
||||
name: 'GddAmount',
|
||||
props: {
|
||||
path: { type: String, required: false, default: '' },
|
||||
balance: { type: Number, required: true },
|
||||
badgeShow: { type: Boolean, default: true },
|
||||
showStatus: { type: Boolean, default: false },
|
||||
},
|
||||
computed: {
|
||||
hideAmount() {
|
||||
return this.$store.state.hideAmountGDD
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async updateHideAmountGDD() {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
hideAmountGDD: !this.hideAmount,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.commit('hideAmountGDD', !this.hideAmount)
|
||||
if (!this.hideAmount) {
|
||||
this.toastSuccess(this.$t('settings.showAmountGDD'))
|
||||
} else {
|
||||
this.toastSuccess(this.$t('settings.hideAmountGDD'))
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
},
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
import { useAppToast } from '../../../composables/useToast'
|
||||
|
||||
const props = defineProps({
|
||||
path: { type: String, required: false, default: '' },
|
||||
balance: { type: Number, required: true },
|
||||
badgeShow: { type: Boolean, default: true },
|
||||
showStatus: { type: Boolean, default: false },
|
||||
})
|
||||
|
||||
const store = useStore()
|
||||
const { mutate } = useMutation(updateUserInfos)
|
||||
const { t } = useI18n()
|
||||
const { toastSuccess, toastError } = useAppToast()
|
||||
|
||||
const hideAmount = computed(() => store.state.hideAmountGDD)
|
||||
|
||||
const updateHideAmountGDD = async () => {
|
||||
try {
|
||||
await mutate({
|
||||
hideAmountGDD: !hideAmount.value,
|
||||
})
|
||||
|
||||
store.commit('hideAmountGDD', !hideAmount.value)
|
||||
|
||||
if (!hideAmount.value) {
|
||||
toastSuccess(t('settings.showAmountGDD'))
|
||||
} else {
|
||||
toastSuccess(t('settings.hideAmountGDD'))
|
||||
}
|
||||
} catch (error) {
|
||||
toastError(error.message)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,82 +1,88 @@
|
||||
<template>
|
||||
<div class="gdt-amount mt-3 mt-lg-0">
|
||||
<div class="text-center">
|
||||
<b-badge
|
||||
<BBadge
|
||||
v-if="badgeShow"
|
||||
class="position-absolute mt--2 ml--4 px-3 zindex1"
|
||||
:class="showStatus ? 'bg-gradient' : ''"
|
||||
:variant="showStatus ? '' : 'light'"
|
||||
>
|
||||
{{ $t('GDT') }}
|
||||
</b-badge>
|
||||
</BBadge>
|
||||
</div>
|
||||
<div
|
||||
class="wallet-amount bg-white appBoxShadow gradido-border-radius p-4 border"
|
||||
class="wallet-amount bg-white app-box-shadow gradido-border-radius p-4 border"
|
||||
:class="showStatus ? 'gradido-global-border-color-accent' : 'border-light opacity-05'"
|
||||
>
|
||||
<b-row>
|
||||
<b-col class="h4">{{ $t('gdt.gdtKonto') }}</b-col>
|
||||
</b-row>
|
||||
<b-row>
|
||||
<b-col cols="9">
|
||||
<b-icon
|
||||
icon="layers"
|
||||
class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"
|
||||
></b-icon>
|
||||
<BRow>
|
||||
<BCol class="h4">{{ $t('gdt.gdtKonto') }}</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol cols="9">
|
||||
<!-- <b-icon-->
|
||||
<!-- icon="layers"-->
|
||||
<!-- class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"-->
|
||||
<!-- ></b-icon>-->
|
||||
<IBiLayers />
|
||||
<span v-if="hideAmount" class="font-weight-bold gradido-global-color-accent">
|
||||
{{ $t('asterisks') }}
|
||||
{{ t('asterisks') }}
|
||||
</span>
|
||||
<span v-else class="font-weight-bold gradido-global-color-accent">
|
||||
{{ $n(GdtBalance, 'decimal') }} {{ $t('GDT') }}
|
||||
{{ n(gdtBalance, 'decimal') }} {{ t('GDT') }}
|
||||
</span>
|
||||
</b-col>
|
||||
<b-col cols="3" class="border-left border-light">
|
||||
<b-icon
|
||||
:icon="hideAmount ? 'eye-slash' : 'eye'"
|
||||
class="mr-3 gradido-global-border-color-accent pointer hover-icon"
|
||||
@click="updateHideAmountGDT"
|
||||
></b-icon>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
<BCol cols="3" class="border-left border-light">
|
||||
<!-- <b-icon-->
|
||||
<!-- :icon="hideAmount ? 'eye-slash' : 'eye'"-->
|
||||
<!-- class="mr-3 gradido-global-border-color-accent pointer hover-icon"-->
|
||||
<!-- @click="updateHideAmountGDT"-->
|
||||
<!-- ></b-icon>-->
|
||||
<button class="transparent-button" @click="updateHideAmountGDT">
|
||||
<IBiEyeSlash v-if="hideAmount" />
|
||||
<IBiEye v-else />
|
||||
</button>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
|
||||
export default {
|
||||
name: 'GdtAmount',
|
||||
props: {
|
||||
GdtBalance: { type: Number, required: true },
|
||||
badgeShow: { type: Boolean, default: true },
|
||||
showStatus: { type: Boolean, default: false },
|
||||
},
|
||||
computed: {
|
||||
hideAmount() {
|
||||
return this.$store.state.hideAmountGDT
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async updateHideAmountGDT() {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
hideAmountGDT: !this.hideAmount,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.commit('hideAmountGDT', !this.hideAmount)
|
||||
if (!this.hideAmount) {
|
||||
this.toastSuccess(this.$t('settings.showAmountGDT'))
|
||||
} else {
|
||||
this.toastSuccess(this.$t('settings.hideAmountGDT'))
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.toastError(error.message)
|
||||
})
|
||||
},
|
||||
},
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useStore } from 'vuex'
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { updateUserInfos } from '@/graphql/mutations'
|
||||
import { useAppToast } from '../../../composables/useToast'
|
||||
|
||||
const props = defineProps({
|
||||
gdtBalance: { type: Number, required: true },
|
||||
badgeShow: { type: Boolean, default: true },
|
||||
showStatus: { type: Boolean, default: false },
|
||||
})
|
||||
|
||||
const store = useStore()
|
||||
const { mutate } = useMutation(updateUserInfos)
|
||||
const { t, n } = useI18n()
|
||||
const { toastSuccess, toastError } = useAppToast()
|
||||
|
||||
const hideAmount = computed(() => store.state.hideAmountGDT)
|
||||
|
||||
const updateHideAmountGDT = async () => {
|
||||
try {
|
||||
await mutate({
|
||||
hideAmountGDT: !hideAmount.value,
|
||||
})
|
||||
|
||||
store.commit('hideAmountGDT', !hideAmount.value)
|
||||
|
||||
if (!hideAmount.value) {
|
||||
toastSuccess(t('settings.showAmountGDT'))
|
||||
} else {
|
||||
toastSuccess(t('settings.hideAmountGDT'))
|
||||
}
|
||||
} catch (error) {
|
||||
toastError(error.message)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,18 +1,38 @@
|
||||
<template>
|
||||
<div class="nav-community">
|
||||
<div class="bg-209 rounded-26 d-flex bd-highlight mx-xl-6 mx-lg-5 shadow">
|
||||
<b-btn to="contribute" active-class="btn-active svg-icon-active" block variant="link">
|
||||
<div
|
||||
class="nav-community-btn-wrapper bg-209 rounded-26 d-flex bd-highlight mx-xl-6 mx-lg-5 shadow justify-content-between"
|
||||
>
|
||||
<BButton
|
||||
to="contribute"
|
||||
active-class="btn-active svg-icon-active"
|
||||
block
|
||||
variant="link"
|
||||
class="nav-community__btn"
|
||||
>
|
||||
<b-img src="/img/svg/write.svg" height="20" class="svg-icon" />
|
||||
{{ $t('community.submitContribution') }}
|
||||
</b-btn>
|
||||
<b-btn to="contributions" active-class="btn-active svg-icon-active" block variant="link">
|
||||
</BButton>
|
||||
<BButton
|
||||
to="contributions"
|
||||
active-class="btn-active svg-icon-active"
|
||||
block
|
||||
variant="link"
|
||||
class="nav-community__btn"
|
||||
>
|
||||
<b-img src="/img/svg/my_profil.svg" height="20" class="svg-icon" />
|
||||
{{ $t('community.myContributions') }}
|
||||
</b-btn>
|
||||
<b-btn to="community" active-class="btn-active svg-icon-active" block variant="link">
|
||||
</BButton>
|
||||
<BButton
|
||||
to="community"
|
||||
active-class="btn-active svg-icon-active"
|
||||
block
|
||||
variant="link"
|
||||
class="nav-community__btn"
|
||||
>
|
||||
<b-img src="/img/svg/community.svg" height="20" class="svg-icon" />
|
||||
{{ $t('community.community') }}
|
||||
</b-btn>
|
||||
</BButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -21,26 +41,33 @@ export default {
|
||||
name: 'NavCommunity',
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.btn {
|
||||
background-color: rgb(209, 209, 209);
|
||||
color: black;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
}
|
||||
.btn-block + .btn-block {
|
||||
margin-top: 0rem;
|
||||
<style scoped lang="scss">
|
||||
.nav-community-btn-wrapper {
|
||||
> :deep(*) {
|
||||
width: calc(100% / 3);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
text-wrap: nowrap;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
|
||||
.svg-icon {
|
||||
:deep(.svg-icon) {
|
||||
filter: brightness(0) invert(0);
|
||||
}
|
||||
.btn-active {
|
||||
|
||||
:deep(.router-link-active) {
|
||||
background-color: rgb(23 141 129);
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
padding: 0.625rem 1.25rem;
|
||||
border-radius: 25px;
|
||||
}
|
||||
.btn-active .svg-icon {
|
||||
|
||||
:deep(.router-link-active .svg-icon) {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="last-contributions d-none d-lg-block">
|
||||
<b-row class="mb-5">
|
||||
<b-col class="h3">{{ $t('contribution.lastContribution') }}</b-col>
|
||||
<b-col cols="1" class="text-right">
|
||||
<BRow class="mb-5">
|
||||
<BCol class="h3">{{ $t('contribution.lastContribution') }}</BCol>
|
||||
<BCol cols="1" class="text-right">
|
||||
<b-icon icon="three-dots-vertical"></b-icon>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
<template>
|
||||
<div class="rightside-last-transactions d-none d-lg-block">
|
||||
<b-row class="mb-3">
|
||||
<b-col class="h3">{{ $t('transaction.lastTransactions') }}</b-col>
|
||||
<!-- <b-col cols="1" class="text-right">
|
||||
<BRow class="mb-3">
|
||||
<BCol class="h3">{{ $t('transaction.lastTransactions') }}</BCol>
|
||||
<!-- <BCol cols="1" class="text-right">
|
||||
<b-icon icon="three-dots-vertical"></b-icon>
|
||||
</b-col> -->
|
||||
</b-row>
|
||||
</BCol> -->
|
||||
</BRow>
|
||||
|
||||
<div v-for="(transaction, index) in transactions" :key="transaction.id">
|
||||
<b-row
|
||||
align-v="center"
|
||||
<BRow
|
||||
v-if="
|
||||
index <= 8 &&
|
||||
transaction.typeId !== 'DECAY' &&
|
||||
transaction.typeId !== 'LINK_SUMMARY' &&
|
||||
transaction.typeId !== 'CREATION'
|
||||
"
|
||||
align-v="center"
|
||||
class="mb-4"
|
||||
>
|
||||
<b-col cols="auto">
|
||||
<BCol cols="auto">
|
||||
<div class="align-items-center">
|
||||
<avatar
|
||||
:size="72"
|
||||
@ -27,25 +27,25 @@
|
||||
:initials="`${transaction.linkedUser.firstName[0]}${transaction.linkedUser.lastName[0]}`"
|
||||
></avatar>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col class="p-1">
|
||||
<b-row>
|
||||
<b-col>
|
||||
</BCol>
|
||||
<BCol class="p-1">
|
||||
<BRow>
|
||||
<BCol>
|
||||
<div class="font-weight-bold">
|
||||
<name :linkedUser="transaction.linkedUser" fontColor="text-dark" />
|
||||
<name :linked-user="transaction.linkedUser" font-color="text-dark" />
|
||||
</div>
|
||||
<div class="d-flex mt-3">
|
||||
<div class="small">
|
||||
{{ transaction.amount | GDD }}
|
||||
{{ $filters.GDD(transaction.amount) }}
|
||||
</div>
|
||||
<div class="small ml-3 text-right">
|
||||
{{ $d(new Date(transaction.balanceDate), 'short') }}
|
||||
</div>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -62,6 +62,7 @@ export default {
|
||||
props: {
|
||||
transactions: {
|
||||
default: () => [],
|
||||
type: Array,
|
||||
},
|
||||
transactionCount: { type: Number, default: 0 },
|
||||
transactionLinkCount: { type: Number, default: 0 },
|
||||
|
||||
@ -1,22 +1,22 @@
|
||||
<template>
|
||||
<div class="gdt-transaction-list">
|
||||
<div class="list-group bg-white appBoxShadow gradido-border-radius p-3 mb-3">
|
||||
<b-row @click="visible = !visible" class="align-items-center">
|
||||
<b-col cols="3" lg="2" md="2">
|
||||
<b-avatar
|
||||
<div class="list-group bg-white app-box-shadow gradido-border-radius p-3 mb-3">
|
||||
<BRow class="align-items-center" @click="visible = !visible">
|
||||
<BCol cols="3" lg="2" md="2">
|
||||
<BAvatar
|
||||
:icon="getLinesByType.icon"
|
||||
variant="light"
|
||||
size="3em"
|
||||
:class="getLinesByType.iconclasses"
|
||||
></b-avatar>
|
||||
</b-col>
|
||||
<b-col>
|
||||
/>
|
||||
</BCol>
|
||||
<BCol>
|
||||
<!-- <div>
|
||||
{{ getLinesByType }}
|
||||
</div> -->
|
||||
<div>
|
||||
<span class="small">{{ this.$d(new Date(date), 'short') }}</span>
|
||||
<span class="small ml-3">{{ this.$d(new Date(date), 'time') }}</span>
|
||||
<span class="small">{{ $d(new Date(date), 'short') }}</span>
|
||||
<span class="small ml-3">{{ $d(new Date(date), 'time') }}</span>
|
||||
</div>
|
||||
<div>
|
||||
{{ getLinesByType.description }}
|
||||
@ -24,111 +24,198 @@
|
||||
<div class="small">
|
||||
{{ getLinesByType.descriptiontext }}
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="8" lg="3" md="3" sm="8" offset="3" offset-md="0" offset-lg="0">
|
||||
</BCol>
|
||||
<BCol cols="8" lg="3" md="3" sm="8" offset="3" offset-md="0" offset-lg="0">
|
||||
<div class="small mb-2">{{ $t('gdt.credit') }}</div>
|
||||
<div class="font-weight-bold">{{ getLinesByType.credittext }}</div>
|
||||
</b-col>
|
||||
<b-col cols="12" md="1" lg="1" class="text-right">
|
||||
</BCol>
|
||||
<BCol cols="12" md="1" lg="1" class="text-right">
|
||||
<collapse-icon class="text-right" :visible="visible" />
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
|
||||
<b-collapse :id="collapseId" class="mt-2" v-model="visible">
|
||||
<BCollapse :id="collapseId" v-model="visible" class="mt-2">
|
||||
<transaction-collapse
|
||||
:amount="amount"
|
||||
:gdtEntryType="gdtEntryType"
|
||||
:gdt-entry-type="gdtEntryType"
|
||||
:factor="factor"
|
||||
:gdt="gdt"
|
||||
></transaction-collapse>
|
||||
</b-collapse>
|
||||
</BCollapse>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<!--<script>-->
|
||||
<!--import CollapseIcon from './TransactionRows/CollapseIcon'-->
|
||||
<!--import TransactionCollapse from './TransactionCollapse'-->
|
||||
<!--import { GdtEntryType } from '../graphql/enums'-->
|
||||
|
||||
<!--export default {-->
|
||||
<!-- name: 'Transaction',-->
|
||||
<!-- components: {-->
|
||||
<!-- CollapseIcon,-->
|
||||
<!-- TransactionCollapse,-->
|
||||
<!-- },-->
|
||||
<!-- props: {-->
|
||||
<!-- amount: { type: Number },-->
|
||||
<!-- date: { type: String },-->
|
||||
<!-- comment: { type: String },-->
|
||||
<!-- gdtEntryType: { type: String, default: GdtEntryType.FORM },-->
|
||||
<!-- factor: { type: Number },-->
|
||||
<!-- gdt: { type: Number },-->
|
||||
<!-- id: { type: Number },-->
|
||||
<!-- },-->
|
||||
<!-- data() {-->
|
||||
<!-- return {-->
|
||||
<!-- collapseStatus: [],-->
|
||||
<!-- visible: false,-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- methods: {-->
|
||||
<!-- getCollapseState(id) {-->
|
||||
<!-- return this.collapseStatus.includes('gdt-collapse-' + id)-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- computed: {-->
|
||||
<!-- collapseId() {-->
|
||||
<!-- return 'gdt-collapse-' + String(this.id)-->
|
||||
<!-- },-->
|
||||
<!-- isGlobalModificator() {-->
|
||||
<!-- return this.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR-->
|
||||
<!-- },-->
|
||||
<!-- getLinesByType() {-->
|
||||
<!-- switch (this.gdtEntryType) {-->
|
||||
<!-- case GdtEntryType.FORM:-->
|
||||
<!-- case GdtEntryType.CVS:-->
|
||||
<!-- case GdtEntryType.ELOPAGE:-->
|
||||
<!-- case GdtEntryType.DIGISTORE:-->
|
||||
<!-- case GdtEntryType.CVS2: {-->
|
||||
<!-- return {-->
|
||||
<!-- icon: 'heart',-->
|
||||
<!-- iconclasses: 'gradido-global-color-accent',-->
|
||||
<!-- description: this.$t('gdt.contribution'),-->
|
||||
<!-- descriptiontext: this.$n(this.amount, 'decimal') + ' €',-->
|
||||
<!-- credittext: this.$n(this.gdt, 'decimal') + ' GDT',-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- case GdtEntryType.ELOPAGE_PUBLISHER: {-->
|
||||
<!-- return {-->
|
||||
<!-- icon: 'person-check',-->
|
||||
<!-- iconclasses: 'gradido-global-color-accent',-->
|
||||
<!-- description: this.$t('gdt.recruited-member'),-->
|
||||
<!-- descriptiontext: '5%',-->
|
||||
<!-- credittext: this.$n(this.amount, 'decimal') + ' GDT',-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- case GdtEntryType.GLOBAL_MODIFICATOR: {-->
|
||||
<!-- return {-->
|
||||
<!-- icon: 'gift',-->
|
||||
<!-- iconclasses: 'gradido-global-color-accent',-->
|
||||
<!-- description: this.$t('gdt.gdt-received'),-->
|
||||
<!-- descriptiontext: this.comment,-->
|
||||
<!-- credittext: this.$n(this.gdt, 'decimal') + ' GDT',-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- default:-->
|
||||
<!-- throw new Error('no lines for this type: ' + this.gdtEntryType)-->
|
||||
<!-- }-->
|
||||
<!-- },-->
|
||||
<!-- },-->
|
||||
<!-- mounted() {-->
|
||||
<!-- this.$root.$on('bv::collapse::state', (collapseId, isJustShown) => {-->
|
||||
<!-- if (isJustShown) {-->
|
||||
<!-- this.collapseStatus.push(collapseId)-->
|
||||
<!-- } else {-->
|
||||
<!-- this.collapseStatus = this.collapseStatus.filter((id) => id !== collapseId)-->
|
||||
<!-- }-->
|
||||
<!-- })-->
|
||||
<!-- },-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import CollapseIcon from './TransactionRows/CollapseIcon'
|
||||
import TransactionCollapse from './TransactionCollapse'
|
||||
import { GdtEntryType } from '../graphql/enums'
|
||||
|
||||
export default {
|
||||
name: 'Transaction',
|
||||
components: {
|
||||
CollapseIcon,
|
||||
TransactionCollapse,
|
||||
},
|
||||
props: {
|
||||
amount: { type: Number },
|
||||
date: { type: String },
|
||||
comment: { type: String },
|
||||
gdtEntryType: { type: String, default: GdtEntryType.FORM },
|
||||
factor: { type: Number },
|
||||
gdt: { type: Number },
|
||||
id: { type: Number },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
collapseStatus: [],
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCollapseState(id) {
|
||||
return this.collapseStatus.includes('gdt-collapse-' + id)
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
collapseId() {
|
||||
return 'gdt-collapse-' + String(this.id)
|
||||
},
|
||||
isGlobalModificator() {
|
||||
return this.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR
|
||||
},
|
||||
getLinesByType() {
|
||||
switch (this.gdtEntryType) {
|
||||
case GdtEntryType.FORM:
|
||||
case GdtEntryType.CVS:
|
||||
case GdtEntryType.ELOPAGE:
|
||||
case GdtEntryType.DIGISTORE:
|
||||
case GdtEntryType.CVS2: {
|
||||
return {
|
||||
icon: 'heart',
|
||||
iconclasses: 'gradido-global-color-accent',
|
||||
description: this.$t('gdt.contribution'),
|
||||
descriptiontext: this.$n(this.amount, 'decimal') + ' €',
|
||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.ELOPAGE_PUBLISHER: {
|
||||
return {
|
||||
icon: 'person-check',
|
||||
iconclasses: 'gradido-global-color-accent',
|
||||
description: this.$t('gdt.recruited-member'),
|
||||
descriptiontext: '5%',
|
||||
credittext: this.$n(this.amount, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.GLOBAL_MODIFICATOR: {
|
||||
return {
|
||||
icon: 'gift',
|
||||
iconclasses: 'gradido-global-color-accent',
|
||||
description: this.$t('gdt.gdt-received'),
|
||||
descriptiontext: this.comment,
|
||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error('no lines for this type: ' + this.gdtEntryType)
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$root.$on('bv::collapse::state', (collapseId, isJustShown) => {
|
||||
if (isJustShown) {
|
||||
this.collapseStatus.push(collapseId)
|
||||
} else {
|
||||
this.collapseStatus = this.collapseStatus.filter((id) => id !== collapseId)
|
||||
}
|
||||
})
|
||||
// Props
|
||||
const props = defineProps({
|
||||
amount: Number,
|
||||
date: String,
|
||||
comment: String,
|
||||
gdtEntryType: {
|
||||
type: String,
|
||||
default: GdtEntryType.FORM,
|
||||
},
|
||||
factor: Number,
|
||||
gdt: Number,
|
||||
id: Number,
|
||||
})
|
||||
|
||||
// Reactive state
|
||||
const collapseStatus = ref([])
|
||||
const visible = ref(false)
|
||||
|
||||
const { t, n } = useI18n()
|
||||
|
||||
const getCollapseState = (id) => {
|
||||
return collapseStatus.value.includes('gdt-collapse-' + id)
|
||||
}
|
||||
|
||||
const collapseId = computed(() => 'gdt-collapse-' + String(props.id))
|
||||
|
||||
const isGlobalModificator = computed(() => props.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR)
|
||||
|
||||
const getLinesByType = computed(() => {
|
||||
switch (props.gdtEntryType) {
|
||||
case GdtEntryType.FORM:
|
||||
case GdtEntryType.CVS:
|
||||
case GdtEntryType.ELOPAGE:
|
||||
case GdtEntryType.DIGISTORE:
|
||||
case GdtEntryType.CVS2: {
|
||||
return {
|
||||
icon: 'heart',
|
||||
iconclasses: 'gradido-global-color-accent',
|
||||
description: t('gdt.contribution'),
|
||||
descriptiontext: n(props.amount, 'decimal') + ' €',
|
||||
credittext: n(props.gdt, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.ELOPAGE_PUBLISHER: {
|
||||
return {
|
||||
icon: 'person-check',
|
||||
iconclasses: 'gradido-global-color-accent',
|
||||
description: t('gdt.recruited-member'),
|
||||
descriptiontext: '5%',
|
||||
credittext: n(props.amount, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.GLOBAL_MODIFICATOR: {
|
||||
return {
|
||||
icon: 'gift',
|
||||
iconclasses: 'gradido-global-color-accent',
|
||||
description: t('gdt.gdt-received'),
|
||||
descriptiontext: props.comment,
|
||||
credittext: n(props.gdt, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error('no lines for this type: ' + props.gdtEntryType)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// Note: This event listener setup might need to be adjusted for Vue 3
|
||||
// You might want to use provide/inject or a global event bus instead
|
||||
// const root = getCurrentInstance().appContext.config.globalProperties
|
||||
// root.$on('bv::collapse::state', (collapseId, isJustShown) => {
|
||||
// if (isJustShown) {
|
||||
// collapseStatus.value.push(collapseId)
|
||||
// } else {
|
||||
// collapseStatus.value = collapseStatus.value.filter((id) => id !== collapseId)
|
||||
// }
|
||||
// })
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<div class="gdt-transaction-collapse py-4 mb-4 gradido-no-border">
|
||||
<b-row class="gdt-list-collapse-header-text mb-3">
|
||||
<b-col class="collapse-headline">
|
||||
<BRow class="gdt-list-collapse-header-text mb-3">
|
||||
<BCol class="collapse-headline">
|
||||
<b>{{ getLinesByType.headline }}</b>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-row class="gdt-list-collapse-box--all">
|
||||
<b-col cols="12" lg="4" md="4">
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow class="gdt-list-collapse-box--all">
|
||||
<BCol cols="12" lg="4" md="4">
|
||||
<div class="collapse-first">{{ getLinesByType.first }}</div>
|
||||
<div class="collapse-second">{{ getLinesByType.second }}</div>
|
||||
</b-col>
|
||||
<b-col offset="1" offset-md="0" offset-lg="0">
|
||||
</BCol>
|
||||
<BCol offset="1" offset-md="0" offset-lg="0">
|
||||
<div class="collapse-firstMath">{{ getLinesByType.firstMath }}</div>
|
||||
<div class="collapse-secondMath">
|
||||
{{ getLinesByType.secondMath }}
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { GdtEntryType } from '../graphql/enums'
|
||||
import { GdtEntryType } from '@/graphql/enums'
|
||||
|
||||
export default {
|
||||
name: 'TransactionCollapse',
|
||||
|
||||
@ -1,74 +1,76 @@
|
||||
<template>
|
||||
<div class="transaction-link gradido-custom-background">
|
||||
<b-row :class="validLink ? '' : 'bg-muted text-light'" class="mb-2 pt-2 pb-2">
|
||||
<b-col cols="1">
|
||||
<BRow :class="validLink ? '' : 'bg-muted text-light'" class="mb-2 pt-2 pb-2">
|
||||
<BCol cols="1">
|
||||
<type-icon color="text-danger" icon="link45deg" class="pt-4 pl-2" />
|
||||
</b-col>
|
||||
<b-col cols="11">
|
||||
<b-row>
|
||||
<b-col>
|
||||
</BCol>
|
||||
<BCol cols="11">
|
||||
<BRow>
|
||||
<BCol>
|
||||
<amount-and-name-row :amount="amount" :text="$t('form.amount')" />
|
||||
<memo-row :memo="memo" />
|
||||
<date-row :date="validUntil" :diffNow="true" :validLink="validLink" />
|
||||
<date-row :date="validUntil" :diff-now="true" :valid-link="validLink" />
|
||||
<decay-row :decay="decay" />
|
||||
</b-col>
|
||||
<b-col cols="12" lg="1" md="1" class="text-center text-md-right pr-5 pr-lg-4">
|
||||
<b-dropdown no-caret right aria-expanded="false" size="sm">
|
||||
</BCol>
|
||||
<BCol cols="12" lg="1" md="1" class="text-center text-md-right pr-5 pr-lg-4">
|
||||
<BDropdown no-caret right aria-expanded="false" size="sm">
|
||||
<template #button-content>
|
||||
<b-icon icon="three-dots-vertical"></b-icon>
|
||||
<IBiThreeDotsVertical />
|
||||
</template>
|
||||
|
||||
<b-dropdown-item v-if="validLink" class="test-copy-link" @click="copyLink">
|
||||
<b-icon icon="clipboard"></b-icon>
|
||||
<BDropdownItem v-if="validLink" class="test-copy-link" @click="copyToClipboard">
|
||||
<IBiClipboard />
|
||||
{{ $t('gdd_per_link.copy-link') }}
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
v-if="validLink"
|
||||
class="test-copy-text pt-3"
|
||||
@click="copyLinkWithText"
|
||||
>
|
||||
<b-icon icon="clipboard-plus"></b-icon>
|
||||
</BDropdownItem>
|
||||
<BDropdownItem v-if="validLink" class="test-copy-text pt-3" @click="copyLinkWithText">
|
||||
<IBiClipboardPlus />
|
||||
{{ $t('gdd_per_link.copy-link-with-text') }}
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item
|
||||
</BDropdownItem>
|
||||
<BDropdownItem
|
||||
v-if="validLink"
|
||||
@click="$bvModal.show('modalPopover-' + id)"
|
||||
class="pt-3 pb-3 test-qr-code"
|
||||
@click="$bvModal.show('modalPopover-' + id)"
|
||||
>
|
||||
<b-img src="img/svg/qr-code.svg" width="18" class="filter"></b-img>
|
||||
<BImg src="img/svg/qr-code.svg" width="18" class="filter"></BImg>
|
||||
{{ $t('qrCode') }}
|
||||
</b-dropdown-item>
|
||||
<b-dropdown-item class="test-delete-link" @click="deleteLink()">
|
||||
<b-icon icon="trash"></b-icon>
|
||||
</BDropdownItem>
|
||||
<BDropdownItem class="test-delete-link" @click="deleteLink()">
|
||||
<IBiTrash />
|
||||
{{ $t('delete') }}
|
||||
</b-dropdown-item>
|
||||
</b-dropdown>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</b-col>
|
||||
</b-row>
|
||||
<b-modal :id="'modalPopover-' + id" ok-only hide-header-close>
|
||||
<b-card header-tag="header" footer-tag="footer">
|
||||
</BDropdownItem>
|
||||
</BDropdown>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BModal :id="'modalPopover-' + id" ok-only hide-header-close>
|
||||
<BCard header-tag="header" footer-tag="footer">
|
||||
<template #header>
|
||||
<h6 class="mb-0">{{ $t('qrCode') }}</h6>
|
||||
</template>
|
||||
<b-card-text><figure-qr-code class="text-center" :link="link" /></b-card-text>
|
||||
<BCardText><figure-qr-code class="text-center" :link="link" /></BCardText>
|
||||
<template #footer>
|
||||
<em>{{ link }}</em>
|
||||
</template>
|
||||
</b-card>
|
||||
</b-modal>
|
||||
<b-modal :id="'modalPopoverCopyError' + id" ok-only hide-header-close>
|
||||
<b-card header-tag="header" footer-tag="footer">
|
||||
<b-card-text>
|
||||
</BCard>
|
||||
</BModal>
|
||||
<BModal :id="'modalPopoverCopyError' + id" ok-only hide-header-close>
|
||||
<BCard header-tag="header" footer-tag="footer">
|
||||
<BCardText>
|
||||
<div class="alert-danger p-3">{{ $t('gdd_per_link.not-copied') }}</div>
|
||||
<div class="alert-muted h3 p-3">{{ link }}</div>
|
||||
</b-card-text>
|
||||
</b-card>
|
||||
</b-modal>
|
||||
</BCardText>
|
||||
</BCard>
|
||||
</BModal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { useMutation } from '@vue/apollo-composable'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useAppToast } from '@/composables/useToast'
|
||||
import { useCopyLinks } from '@/composables/useCopyLinks'
|
||||
import { deleteTransactionLink } from '@/graphql/mutations'
|
||||
import TypeIcon from '../TransactionRows/TypeIcon'
|
||||
import AmountAndNameRow from '../TransactionRows/AmountAndNameRow'
|
||||
@ -76,52 +78,45 @@ import MemoRow from '../TransactionRows/MemoRow'
|
||||
import DateRow from '../TransactionRows/DateRow'
|
||||
import DecayRow from '../TransactionRows/DecayRow'
|
||||
import FigureQrCode from '@/components/QrCode/FigureQrCode'
|
||||
import { copyLinks } from '../../mixins/copyLinks'
|
||||
import { useModal } from 'bootstrap-vue-next'
|
||||
|
||||
export default {
|
||||
name: 'TransactionLink',
|
||||
mixins: [copyLinks],
|
||||
components: {
|
||||
TypeIcon,
|
||||
AmountAndNameRow,
|
||||
MemoRow,
|
||||
DateRow,
|
||||
DecayRow,
|
||||
FigureQrCode,
|
||||
},
|
||||
props: {
|
||||
holdAvailableAmount: { type: String, required: true },
|
||||
id: { type: Number, required: true },
|
||||
},
|
||||
methods: {
|
||||
deleteLink() {
|
||||
this.$bvModal.msgBoxConfirm(this.$t('gdd_per_link.delete-the-link')).then(async (value) => {
|
||||
if (value)
|
||||
await this.$apollo
|
||||
.mutate({
|
||||
mutation: deleteTransactionLink,
|
||||
variables: {
|
||||
id: this.id,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.toastSuccess(this.$t('gdd_per_link.deleted'))
|
||||
this.$emit('reset-transaction-link-list')
|
||||
})
|
||||
.catch((err) => {
|
||||
this.toastError(err.message)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
decay() {
|
||||
return `${this.amount - this.holdAvailableAmount}`
|
||||
},
|
||||
validLink() {
|
||||
return new Date(this.validUntil) > new Date()
|
||||
},
|
||||
},
|
||||
const props = defineProps({
|
||||
holdAvailableAmount: { type: String, required: true },
|
||||
id: { type: Number, required: true },
|
||||
amount: { type: Number, required: true },
|
||||
validUntil: { type: String, required: true },
|
||||
link: { type: String, required: true },
|
||||
memo: { type: String, required: true },
|
||||
})
|
||||
|
||||
const emit = defineEmits(['reset-transaction-link-list'])
|
||||
|
||||
const { t } = useI18n()
|
||||
const { toastSuccess, toastError } = useAppToast()
|
||||
const { copyToClipboard, copyLinkWithText } = useCopyLinks({
|
||||
amount: props.amount,
|
||||
validUntil: props.validUntil,
|
||||
link: props.link,
|
||||
memo: props.memo,
|
||||
})
|
||||
const { showConfirmModal } = useModal()
|
||||
|
||||
const { mutate: deleteTransactionLinkMutation } = useMutation(deleteTransactionLink)
|
||||
|
||||
const decay = computed(() => `${props.amount - props.holdAvailableAmount}`)
|
||||
const validLink = computed(() => new Date(props.validUntil) > new Date())
|
||||
|
||||
async function deleteLink() {
|
||||
const confirmed = await showConfirmModal(t('gdd_per_link.delete-the-link'))
|
||||
if (confirmed) {
|
||||
try {
|
||||
await deleteTransactionLinkMutation({ id: props.id })
|
||||
toastSuccess(t('gdd_per_link.deleted'))
|
||||
emit('reset-transaction-link-list')
|
||||
} catch (err) {
|
||||
toastError(err.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@ -129,6 +124,7 @@ export default {
|
||||
position: relative;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.filter {
|
||||
filter: opacity(0.6);
|
||||
}
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<div class="amount-and-name-row">
|
||||
<b-row>
|
||||
<b-col cols="5">
|
||||
<BRow>
|
||||
<BCol cols="5">
|
||||
<div class="text-right">
|
||||
<span class="gdd-transaction-list-item-amount">
|
||||
{{ amount | GDD }}
|
||||
{{ $filters.GDD(amount) }}
|
||||
</span>
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="7">
|
||||
</BCol>
|
||||
<BCol cols="7">
|
||||
<div class="gdd-transaction-list-item-name">
|
||||
<span>{{ text }}</span>
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<div class="collapse-icon">
|
||||
<b-icon
|
||||
:icon="visible ? 'arrow-up-circle' : 'arrow-down-circle'"
|
||||
:class="visible ? 'text-black' : 'text-muted'"
|
||||
class="h1"
|
||||
/>
|
||||
<!-- <b-icon-->
|
||||
<!-- :icon="visible ? 'arrow-up-circle' : 'arrow-down-circle'"-->
|
||||
<!-- :class="visible ? 'text-black' : 'text-muted'"-->
|
||||
<!-- class="h1"-->
|
||||
<!-- />-->
|
||||
<IBiArrowUpCircle v-if="visible" class="text-black h1" />
|
||||
<IBiArrowDownCircle v-else class="text-muted h1" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
<template>
|
||||
<div class="date-row">
|
||||
<b-row>
|
||||
<b-col cols="5">
|
||||
<BRow>
|
||||
<BCol cols="5">
|
||||
<div class="text-right">
|
||||
{{ text }}
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="7">
|
||||
</BCol>
|
||||
<BCol cols="7">
|
||||
<div class="gdd-transaction-list-item-date">
|
||||
{{ $d(new Date(this.date), 'long') }}
|
||||
{{ $d(new Date(date), 'long') }}
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<div class="decay-row">
|
||||
<b-row v-if="decay">
|
||||
<b-col cols="5">
|
||||
<BRow v-if="decay">
|
||||
<BCol cols="5">
|
||||
<div class="text-right">
|
||||
<b-icon icon="droplet-half" height="15" class="mb-1" />
|
||||
<!-- <b-icon icon="droplet-half" height="15" class="mb-1" />-->
|
||||
<IBiDropletHalf height="15" class="mb-1" />
|
||||
</div>
|
||||
</b-col>
|
||||
<b-col cols="7">
|
||||
</BCol>
|
||||
<BCol cols="7">
|
||||
<div class="gdd-transaction-list-item-decay">
|
||||
<decay-information-short decaytyp="short" :decay="decay" />
|
||||
</div>
|
||||
</b-col>
|
||||
</b-row>
|
||||
</BCol>
|
||||
</BRow>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user