Merge branch 'master' into 1588-frontend-expendable-paginated-link-list

This commit is contained in:
Alexander Friedland 2022-03-16 20:57:03 +01:00 committed by GitHub
commit 3ada62d20f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
89 changed files with 1225 additions and 869 deletions

View File

@ -1,3 +1,4 @@
node_modules node_modules
.git .git
.gitignore .gitignore
!.eslintignore

View File

@ -1,4 +1,3 @@
node_modules node_modules/
coverage dist/
**/*.min.js coverage/
dist

View File

@ -8,9 +8,20 @@ module.exports = {
parserOptions: { parserOptions: {
parser: 'babel-eslint', parser: 'babel-eslint',
}, },
extends: ['standard', 'plugin:vue/essential', 'plugin:prettier/recommended'], extends: [
'standard',
'plugin:vue/essential',
'plugin:prettier/recommended',
'plugin:@intlify/vue-i18n/recommended',
],
// required to lint *.vue files // required to lint *.vue files
plugins: ['vue', 'prettier', 'jest'], plugins: ['vue', 'prettier', 'jest'],
overrides: [
{
files: ['*.json'],
extends: ['plugin:@intlify/vue-i18n/recommended'],
},
],
// add your custom rules here // add your custom rules here
rules: { rules: {
'no-console': ['error'], 'no-console': ['error'],
@ -22,6 +33,17 @@ module.exports = {
allowBinding: false, allowBinding: false,
}, },
], ],
'@intlify/vue-i18n/no-dynamic-keys': 'error',
'@intlify/vue-i18n/no-unused-keys': [
'error',
{
src: './src',
extensions: ['.js', '.vue'],
ignores: [],
enableFix: false,
},
],
'@intlify/vue-i18n/no-missing-keys-in-other-locales': 'error',
'prettier/prettier': [ 'prettier/prettier': [
'error', 'error',
{ {
@ -29,4 +51,12 @@ module.exports = {
}, },
], ],
}, },
settings: {
'vue-i18n': {
localeDir: './src/locales/*.json',
// Specify the version of `vue-i18n` you are using.
// If not specified, the message will be parsed twice.
messageSyntaxVersion: '^8.26.5',
},
},
} }

View File

@ -12,11 +12,10 @@
"build": "vue-cli-service build", "build": "vue-cli-service build",
"dev": "yarn run serve", "dev": "yarn run serve",
"analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json", "analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json",
"lint": "eslint --max-warnings=0 --ext .js,.vue .", "lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'", "stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'",
"test": "TZ=UTC jest --coverage", "test": "TZ=UTC jest --coverage",
"locales": "scripts/missing-keys.sh && scripts/sort.sh" "locales": "scripts/sort.sh"
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.15.8", "@babel/core": "^7.15.8",
@ -52,6 +51,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.15.8", "@babel/eslint-parser": "^7.15.8",
"@intlify/eslint-plugin-vue-i18n": "^1.4.0",
"@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0", "@vue/cli-service": "~4.5.0",

View File

@ -4,24 +4,24 @@
<b-row align-v="center" class="mt-4 justify-content-lg-between"> <b-row align-v="center" class="mt-4 justify-content-lg-between">
<b-col> <b-col>
<div class="copyright text-center text-lg-center text-muted"> <div class="copyright text-center text-lg-center text-muted">
© {{ year }} {{ $t('footer.copyright.year', { year }) }}
<a <a
:href="`https://gradido.net/${$i18n.locale}`" :href="`https://gradido.net/${$i18n.locale}`"
class="font-weight-bold ml-1" class="font-weight-bold ml-1"
target="_blank" target="_blank"
> >
{{ $t('gradido_admin_footer') }} {{ $t('footer.copyright.link') }}
</a> </a>
| {{ $t('math.pipe') }}
<a href="https://github.com/gradido/gradido/releases/latest" target="_blank"> <a href="https://github.com/gradido/gradido/releases/latest" target="_blank">
App version {{ version }} {{ $t('footer.app_version', { version }) }}
</a> </a>
<a <a
v-if="hash" v-if="hash"
:href="'https://github.com/gradido/gradido/commit/' + hash" :href="'https://github.com/gradido/gradido/commit/' + hash"
target="_blank" target="_blank"
> >
({{ shortHash }}) {{ $t('footer.short_hash', { shortHash }) }}
</a> </a>
</div> </div>
</b-col> </b-col>

View File

@ -7,7 +7,7 @@
<b-row class="mt-4"> <b-row class="mt-4">
<b-col class="col-3">{{ $t('transactionlist.amount') }}</b-col> <b-col class="col-3">{{ $t('transactionlist.amount') }}</b-col>
<b-col class="h3"> <b-col class="h3">
<b>{{ item.amount }} GDD</b> <b>{{ item.amount }} {{ $t('GDD') }}</b>
</b-col> </b-col>
</b-row> </b-row>
<b-row> <b-row>

View File

@ -12,7 +12,7 @@
> >
<b-icon icon="plus" variant="success"></b-icon> <b-icon icon="plus" variant="success"></b-icon>
</b-button> </b-button>
<div v-else>{{ $t('e_mail') }}!</div> <div v-else>{{ $t('e_mail') }}{{ $t('math.exclaim') }}</div>
</div> </div>
</template> </template>
</b-table-lite> </b-table-lite>

View File

@ -1,8 +1,6 @@
{ {
"all_emails": "Alle Nutzer", "all_emails": "Alle Nutzer",
"back": "zurück", "back": "zurück",
"bookmark": "bookmark",
"confirmed": "bestätigt",
"creation": "Schöpfung", "creation": "Schöpfung",
"creation_form": { "creation_form": {
"creation_failed": "Ausstehende Schöpfung für {email} konnte nicht erzeugt werden.", "creation_failed": "Ausstehende Schöpfung für {email} konnte nicht erzeugt werden.",
@ -16,7 +14,6 @@
"submit_creation": "Schöpfung einreichen", "submit_creation": "Schöpfung einreichen",
"toasted": "Offene Schöpfung ({value} GDD) für {email} wurde gespeichert und liegt zur Bestätigung bereit", "toasted": "Offene Schöpfung ({value} GDD) für {email} wurde gespeichert und liegt zur Bestätigung bereit",
"toasted_created": "Schöpfung wurde erfolgreich gespeichert", "toasted_created": "Schöpfung wurde erfolgreich gespeichert",
"toasted_default": "`Fall {event} wird nicht unterstützt`",
"toasted_delete": "Offene Schöpfung wurde gelöscht", "toasted_delete": "Offene Schöpfung wurde gelöscht",
"toasted_update": "`Offene Schöpfung {value} GDD) für {email} wurde geändert und liegt zur Bestätigung bereit", "toasted_update": "`Offene Schöpfung {value} GDD) für {email} wurde geändert und liegt zur Bestätigung bereit",
"update_creation": "Schöpfung aktualisieren" "update_creation": "Schöpfung aktualisieren"
@ -27,14 +24,26 @@
"deleted": "gelöscht", "deleted": "gelöscht",
"deleted_user": "Alle gelöschten Nutzer", "deleted_user": "Alle gelöschten Nutzer",
"delete_user": "Nutzer löschen", "delete_user": "Nutzer löschen",
"details": "Details",
"edit": "Bearbeiten", "edit": "Bearbeiten",
"enabled": "aktiviert",
"error": "Fehler", "error": "Fehler",
"e_mail": "E-Mail", "e_mail": "E-Mail",
"firstname": "Vorname", "firstname": "Vorname",
"gradido_admin_footer": "Gradido Akademie Adminkonsole", "footer": {
"app_version": "App version {version}",
"copyright": {
"link": "Gradido Akademie Adminkonsole",
"year": "© {year}"
},
"short_hash": "({shortHash})"
},
"GDD": "GDD",
"hide_details": "Details verbergen", "hide_details": "Details verbergen",
"lastname": "Nachname", "lastname": "Nachname",
"math": {
"exclaim": "!",
"pipe": "|"
},
"moderator": "Moderator", "moderator": "Moderator",
"multiple_creation_text": "Bitte wähle ein oder mehrere Mitglieder aus für die du Schöpfen möchtest.", "multiple_creation_text": "Bitte wähle ein oder mehrere Mitglieder aus für die du Schöpfen möchtest.",
"name": "Name", "name": "Name",
@ -47,7 +56,6 @@
"user_search": "Nutzersuche" "user_search": "Nutzersuche"
}, },
"not_open_creations": "Keine offenen Schöpfungen", "not_open_creations": "Keine offenen Schöpfungen",
"open_creation": "Offene Schöpfung",
"open_creations": "Offene Schöpfungen", "open_creations": "Offene Schöpfungen",
"overlay": { "overlay": {
"confirm": { "confirm": {
@ -56,13 +64,6 @@
"text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar und kann auch nicht mehr gelöscht werden. Bitte überprüfe genau, dass alles stimmt.", "text": "Nach dem Speichern ist der Datensatz nicht mehr änderbar und kann auch nicht mehr gelöscht werden. Bitte überprüfe genau, dass alles stimmt.",
"title": "Schöpfung bestätigen!", "title": "Schöpfung bestätigen!",
"yes": "Ja, Schöpfung bestätigen und speichern!" "yes": "Ja, Schöpfung bestätigen und speichern!"
},
"remove": {
"no": "Nein, nicht löschen.",
"question": "Willst du die vorgespeicherte Schöpfung wirklich löschen?",
"text": "Nach dem Löschen gibt es keine Möglichkeit mehr diesen Datensatz wiederherzustellen. Es wird aber der gesamte Vorgang in der Logdatei als Übersicht gespeichert.",
"title": "Achtung! Schöpfung löschen!",
"yes": "Ja, Schöpfung löschen!"
} }
}, },
"remove": "Entfernen", "remove": "Entfernen",
@ -72,13 +73,11 @@
"status": "Status", "status": "Status",
"success": "Erfolg", "success": "Erfolg",
"text": "Text", "text": "Text",
"transaction": "Transaktion",
"transactionlist": { "transactionlist": {
"amount": "Betrag", "amount": "Betrag",
"balanceDate": "Schöpfungsdatum", "balanceDate": "Schöpfungsdatum",
"community": "Gemeinschaft", "community": "Gemeinschaft",
"date": "Datum", "date": "Datum",
"decay": "Vergänglichkeit",
"memo": "Nachricht", "memo": "Nachricht",
"title": "Alle geschöpften Transaktionen für den Nutzer" "title": "Alle geschöpften Transaktionen für den Nutzer"
}, },

View File

@ -1,8 +1,6 @@
{ {
"all_emails": "All users", "all_emails": "All users",
"back": "back", "back": "back",
"bookmark": "Remember",
"confirmed": "confirmed",
"creation": "Creation", "creation": "Creation",
"creation_form": { "creation_form": {
"creation_failed": "Could not create pending creation for {email}", "creation_failed": "Could not create pending creation for {email}",
@ -16,7 +14,6 @@
"submit_creation": "Submit creation", "submit_creation": "Submit creation",
"toasted": "Open creation ({value} GDD) for {email} has been saved and is ready for confirmation.", "toasted": "Open creation ({value} GDD) for {email} has been saved and is ready for confirmation.",
"toasted_created": "Creation has been successfully saved", "toasted_created": "Creation has been successfully saved",
"toasted_default": "`Case {event} is not supported`",
"toasted_delete": "Open creation has been deleted", "toasted_delete": "Open creation has been deleted",
"toasted_update": "Open creation {value} GDD) for {email} has been changed and is ready for confirmation.", "toasted_update": "Open creation {value} GDD) for {email} has been changed and is ready for confirmation.",
"update_creation": "Creation update" "update_creation": "Creation update"
@ -27,14 +24,26 @@
"deleted": "deleted", "deleted": "deleted",
"deleted_user": "All deleted user", "deleted_user": "All deleted user",
"delete_user": "Delete user", "delete_user": "Delete user",
"details": "Details",
"edit": "Edit", "edit": "Edit",
"enabled": "enabled",
"error": "Error", "error": "Error",
"e_mail": "E-mail", "e_mail": "E-mail",
"firstname": "Firstname", "firstname": "Firstname",
"gradido_admin_footer": "Gradido Academy Admin Console", "footer": {
"app_version": "App version {version}",
"copyright": {
"link": "Gradido Academy Admin Console",
"year": "© {year}"
},
"short_hash": "({shortHash})"
},
"GDD": "GDD",
"hide_details": "Hide details", "hide_details": "Hide details",
"lastname": "Lastname", "lastname": "Lastname",
"math": {
"exclaim": "!",
"pipe": "|"
},
"moderator": "Moderator", "moderator": "Moderator",
"multiple_creation_text": "Please select one or more members for which you would like to perform creations.", "multiple_creation_text": "Please select one or more members for which you would like to perform creations.",
"name": "Name", "name": "Name",
@ -47,7 +56,6 @@
"user_search": "User search" "user_search": "User search"
}, },
"not_open_creations": "No open creations", "not_open_creations": "No open creations",
"open_creation": "Open creation",
"open_creations": "Open creations", "open_creations": "Open creations",
"overlay": { "overlay": {
"confirm": { "confirm": {
@ -56,13 +64,6 @@
"text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.", "text": "After saving, the record can no longer be changed or deleted. Please check carefully that everything is correct.",
"title": "Confirm creation!", "title": "Confirm creation!",
"yes": "Yes, confirm and save creation!" "yes": "Yes, confirm and save creation!"
},
"remove": {
"no": "No, do not delete.",
"question": "Do you really want to delete the pre-stored creation?",
"text": "After deletion, there is no possibility to restore this data record. However, the entire process is saved in the log file as an overview.",
"title": "Attention! Delete creation!",
"yes": "Yes, delete creation!"
} }
}, },
"remove": "Remove", "remove": "Remove",
@ -72,13 +73,11 @@
"status": "Status", "status": "Status",
"success": "Success", "success": "Success",
"text": "Text", "text": "Text",
"transaction": "Transaction",
"transactionlist": { "transactionlist": {
"amount": "Amount", "amount": "Amount",
"balanceDate": "Creation date", "balanceDate": "Creation date",
"community": "Community", "community": "Community",
"date": "Date", "date": "Date",
"decay": "Decay",
"memo": "Message", "memo": "Message",
"title": "All creation-transactions for the user" "title": "All creation-transactions for the user"
}, },

View File

@ -2,7 +2,7 @@
<div class="creation"> <div class="creation">
<b-row> <b-row>
<b-col cols="12" lg="6"> <b-col cols="12" lg="6">
<label>Usersuche</label> <label>{{ $t('user_search') }}</label>
<b-input-group> <b-input-group>
<b-form-input <b-form-input
type="text" type="text"

View File

@ -2,7 +2,6 @@ import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost'
import VueApollo from 'vue-apollo' import VueApollo from 'vue-apollo'
import CONFIG from '../config' import CONFIG from '../config'
import store from '../store/store' import store from '../store/store'
import i18n from '../i18n'
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI }) const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
@ -15,7 +14,6 @@ const authLink = new ApolloLink((operation, forward) => {
}) })
return forward(operation).map((response) => { return forward(operation).map((response) => {
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') { if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
response.errors[0].message = i18n.t('error.session-expired')
store.dispatch('logout', null) store.dispatch('logout', null)
window.location.assign(CONFIG.WALLET_URL) window.location.assign(CONFIG.WALLET_URL)
return response return response

View File

@ -14,6 +14,7 @@ module.exports = {
fallbackLocale: 'de', fallbackLocale: 'de',
localeDir: 'locales', localeDir: 'locales',
enableInSFC: false, enableInSFC: false,
enableLegacy: false,
}, },
}, },
lintOnSave: true, lintOnSave: true,

View File

@ -932,6 +932,13 @@
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.14.0":
version "7.17.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.7.tgz#a5f3328dc41ff39d803f311cfe17703418cf9825"
integrity sha512-L6rvG9GDxaLgFjg41K+5Yv9OMrU98sWe+Ykmc6FDJW/+vYZMhdOMKkISgzptMaERHvS2Y2lw9MDRm2gHhlQQoA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@7", "@babel/template@^7.0.0", "@babel/template@^7.15.4", "@babel/template@^7.3.3", "@babel/template@^7.4.0": "@babel/template@7", "@babel/template@^7.0.0", "@babel/template@^7.15.4", "@babel/template@^7.3.3", "@babel/template@^7.4.0":
version "7.15.4" version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.15.4.tgz#51898d35dcf3faa670c4ee6afcfd517ee139f194"
@ -1001,6 +1008,21 @@
minimatch "^3.0.4" minimatch "^3.0.4"
strip-json-comments "^3.1.1" strip-json-comments "^3.1.1"
"@eslint/eslintrc@^1.2.0":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6"
integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
espree "^9.3.1"
globals "^13.9.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
js-yaml "^4.1.0"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@hapi/address@2.x.x": "@hapi/address@2.x.x":
version "2.1.4" version "2.1.4"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
@ -1042,6 +1064,83 @@
cssnano-preset-default "^4.0.0" cssnano-preset-default "^4.0.0"
postcss "^7.0.0" postcss "^7.0.0"
"@intlify/core-base@^9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.1.9.tgz#e4e8c951010728e4af3a0d13d74cf3f9e7add7f6"
integrity sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==
dependencies:
"@intlify/devtools-if" "9.1.9"
"@intlify/message-compiler" "9.1.9"
"@intlify/message-resolver" "9.1.9"
"@intlify/runtime" "9.1.9"
"@intlify/shared" "9.1.9"
"@intlify/vue-devtools" "9.1.9"
"@intlify/devtools-if@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/devtools-if/-/devtools-if-9.1.9.tgz#a30e1dd1256ff2c5c98d8d75d075384fba898e5d"
integrity sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==
dependencies:
"@intlify/shared" "9.1.9"
"@intlify/eslint-plugin-vue-i18n@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@intlify/eslint-plugin-vue-i18n/-/eslint-plugin-vue-i18n-1.4.0.tgz#f8fe791892c2dce7d189a364b6a908c87e1c3ac9"
integrity sha512-anB1eBf6rpxpWyW883gi6O1hozQy4Q02VyzyodOUnohOqT07GATVSxnr2J9/qQSV47xWukV+9LiRErJcU7d/uA==
dependencies:
"@eslint/eslintrc" "^1.2.0"
"@intlify/core-base" "^9.1.9"
"@intlify/message-compiler" "^9.1.9"
debug "^4.3.1"
glob "^7.1.3"
ignore "^5.0.5"
is-language-code "^3.1.0"
js-yaml "^4.0.0"
json5 "^2.1.3"
jsonc-eslint-parser "^2.0.0"
lodash "^4.17.11"
parse5 "^6.0.0"
semver "^7.3.4"
vue-eslint-parser "^8.0.0"
yaml-eslint-parser "^0.5.0"
"@intlify/message-compiler@9.1.9", "@intlify/message-compiler@^9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.1.9.tgz#1193cbd224a71c2fb981455b8534a3c766d2948d"
integrity sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==
dependencies:
"@intlify/message-resolver" "9.1.9"
"@intlify/shared" "9.1.9"
source-map "0.6.1"
"@intlify/message-resolver@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/message-resolver/-/message-resolver-9.1.9.tgz#3155ccd2f5e6d0dc16cad8b7f1d8e97fcda05bfc"
integrity sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==
"@intlify/runtime@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/runtime/-/runtime-9.1.9.tgz#2c12ce29518a075629efed0a8ed293ee740cb285"
integrity sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==
dependencies:
"@intlify/message-compiler" "9.1.9"
"@intlify/message-resolver" "9.1.9"
"@intlify/shared" "9.1.9"
"@intlify/shared@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.1.9.tgz#0baaf96128b85560666bec784ffb01f6623cc17a"
integrity sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==
"@intlify/vue-devtools@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/vue-devtools/-/vue-devtools-9.1.9.tgz#2be8f4dbe7f7ed4115676eb32348141d411e426b"
integrity sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==
dependencies:
"@intlify/message-resolver" "9.1.9"
"@intlify/runtime" "9.1.9"
"@intlify/shared" "9.1.9"
"@istanbuljs/load-nyc-config@^1.0.0": "@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -2399,6 +2498,11 @@ acorn@^8.2.4:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
acorn@^8.5.0, acorn@^8.7.0:
version "8.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
address@^1.1.2: address@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
@ -2645,6 +2749,11 @@ argparse@^1.0.7:
dependencies: dependencies:
sprintf-js "~1.0.2" sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
arr-diff@^4.0.0: arr-diff@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@ -4892,7 +5001,7 @@ debug@^3.1.1, debug@^3.2.6, debug@^3.2.7:
dependencies: dependencies:
ms "^2.1.1" ms "^2.1.1"
debug@^4.3.0, debug@^4.3.3: debug@^4.3.0, debug@^4.3.1, debug@^4.3.3:
version "4.3.3" version "4.3.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
@ -5615,6 +5724,14 @@ eslint-scope@^5.1.1:
esrecurse "^4.3.0" esrecurse "^4.3.0"
estraverse "^4.1.1" estraverse "^4.1.1"
eslint-scope@^7.0.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
eslint-utils@^2.0.0, eslint-utils@^2.1.0: eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
@ -5644,6 +5761,11 @@ eslint-visitor-keys@^3.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186"
integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q== integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==
eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@7.25.0: eslint@7.25.0:
version "7.25.0" version "7.25.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.25.0.tgz#1309e4404d94e676e3e831b3a3ad2b050031eb67" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.25.0.tgz#1309e4404d94e676e3e831b3a3ad2b050031eb67"
@ -5710,6 +5832,15 @@ espree@^7.3.0, espree@^7.3.1:
acorn-jsx "^5.3.1" acorn-jsx "^5.3.1"
eslint-visitor-keys "^1.3.0" eslint-visitor-keys "^1.3.0"
espree@^9.0.0, espree@^9.3.1:
version "9.3.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
dependencies:
acorn "^8.7.0"
acorn-jsx "^5.3.1"
eslint-visitor-keys "^3.3.0"
esprima@^4.0.0, esprima@^4.0.1: esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@ -7003,16 +7134,16 @@ ignore@^4.0.3, ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
ignore@^5.0.5, ignore@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
ignore@^5.1.1, ignore@^5.1.4: ignore@^5.1.1, ignore@^5.1.4:
version "5.1.8" version "5.1.8"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
ignore@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
import-cwd@^2.0.0: import-cwd@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
@ -7386,6 +7517,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-language-code@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-language-code/-/is-language-code-3.1.0.tgz#b2386b49227e7010636f16d0c2c681ca40136ab5"
integrity sha512-zJdQ3QTeLye+iphMeK3wks+vXSRFKh68/Pnlw7aOfApFSEIOhYa8P9vwwa6QrImNNBMJTiL1PpYF0f4BxDuEgA==
dependencies:
"@babel/runtime" "^7.14.0"
is-negative-zero@^2.0.1: is-negative-zero@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
@ -8571,6 +8709,13 @@ js-yaml@^3.13.1:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
js-yaml@^4.0.0, js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
jsbn@~0.1.0: jsbn@~0.1.0:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@ -8723,7 +8868,7 @@ json3@^3.3.3:
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==
json5@2.x, json5@^2.1.2: json5@2.x, json5@^2.1.2, json5@^2.1.3:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
@ -8742,6 +8887,16 @@ json5@^1.0.1:
dependencies: dependencies:
minimist "^1.2.0" minimist "^1.2.0"
jsonc-eslint-parser@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/jsonc-eslint-parser/-/jsonc-eslint-parser-2.1.0.tgz#4c126b530aa583d85308d0b3041ff81ce402bbb2"
integrity sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==
dependencies:
acorn "^8.5.0"
eslint-visitor-keys "^3.0.0"
espree "^9.0.0"
semver "^7.3.5"
jsonfile@^4.0.0: jsonfile@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@ -10014,7 +10169,7 @@ parse5@5.1.0:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==
parse5@6.0.1, parse5@^6.0.1: parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
@ -11700,16 +11855,16 @@ source-map-url@^0.4.0:
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@^0.5.0, source-map@^0.5.6: source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7" version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@^0.7.3: source-map@^0.7.3:
version "0.7.3" version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
@ -12970,6 +13125,19 @@ vue-eslint-parser@^7.10.0:
lodash "^4.17.21" lodash "^4.17.21"
semver "^6.3.0" semver "^6.3.0"
vue-eslint-parser@^8.0.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz#5d31129a1b3dd89c0069ca0a1c88f970c360bd0d"
integrity sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==
dependencies:
debug "^4.3.2"
eslint-scope "^7.0.0"
eslint-visitor-keys "^3.1.0"
espree "^9.0.0"
esquery "^1.4.0"
lodash "^4.17.21"
semver "^7.3.5"
vue-functional-data-merge@^3.1.0: vue-functional-data-merge@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz#08a7797583b7f35680587f8a1d51d729aa1dc657" resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz#08a7797583b7f35680587f8a1d51d729aa1dc657"
@ -13515,7 +13683,16 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml@^1.10.0: yaml-eslint-parser@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-0.5.0.tgz#01d4e4d992a820769ea85ef5fd526dfc20ebc6f5"
integrity sha512-nJeyLA3YHAzhBTZbRAbu3W6xrSCucyxExmA+ZDtEdUFpGllxAZpto2Zxo2IG0r0eiuEiBM4e+wiAdxTziTq94g==
dependencies:
eslint-visitor-keys "^3.0.0"
lodash "^4.17.21"
yaml "^1.10.2"
yaml@^1.10.0, yaml@^1.10.2:
version "1.10.2" version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==

View File

@ -3,7 +3,7 @@ module.exports = {
verbose: true, verbose: true,
preset: 'ts-jest', preset: 'ts-jest',
collectCoverage: true, collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**'], collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**'],
setupFiles: ['<rootDir>/test/testSetup.ts'], setupFiles: ['<rootDir>/test/testSetup.ts'],
moduleNameMapper: { moduleNameMapper: {
'@/(.*)': '<rootDir>/src/$1', '@/(.*)': '<rootDir>/src/$1',

View File

@ -13,7 +13,8 @@
"start": "node build/src/index.js", "start": "node build/src/index.js",
"dev": "nodemon -w src --ext ts --exec ts-node src/index.ts", "dev": "nodemon -w src --ext ts --exec ts-node src/index.ts",
"lint": "eslint --max-warnings=0 --ext .js,.ts .", "lint": "eslint --max-warnings=0 --ext .js,.ts .",
"test": "TZ=UTC NODE_ENV=development jest --runInBand --coverage --forceExit --detectOpenHandles" "test": "TZ=UTC NODE_ENV=development jest --runInBand --coverage --forceExit --detectOpenHandles",
"seed": "TZ=UTC ts-node src/seeds/index.ts"
}, },
"dependencies": { "dependencies": {
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
@ -42,6 +43,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/express": "^4.17.12", "@types/express": "^4.17.12",
"@types/faker": "^5.5.9",
"@types/jsonwebtoken": "^8.5.2", "@types/jsonwebtoken": "^8.5.2",
"@types/node": "^16.10.3", "@types/node": "^16.10.3",
"@types/nodemailer": "^6.4.4", "@types/nodemailer": "^6.4.4",
@ -54,6 +56,7 @@
"eslint-plugin-node": "^11.1.0", "eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-promise": "^5.1.0", "eslint-plugin-promise": "^5.1.0",
"faker": "^5.5.3",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"prettier": "^2.3.1", "prettier": "^2.3.1",
"ts-node": "^10.0.0", "ts-node": "^10.0.0",

View File

@ -1,9 +1,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { testEnvironment, createUser, headerPushMock, cleanDB, resetToken } from '@test/helpers' import { testEnvironment, headerPushMock, resetToken, cleanDB } from '@test/helpers'
import { createUserMutation, setPasswordMutation } from '@test/graphql' import { createUserFactory } from '@/seeds/factory/user'
import gql from 'graphql-tag' import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
import { createUser, setPassword } from '@/seeds/graphql/mutations'
import { login, logout } from '@/seeds/graphql/queries'
import { GraphQLError } from 'graphql' import { GraphQLError } from 'graphql'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn' import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { User } from '@entity/User' import { User } from '@entity/User'
@ -11,8 +13,6 @@ import CONFIG from '@/config'
import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail' import { sendAccountActivationEmail } from '@/mailer/sendAccountActivationEmail'
// import { klicktippSignIn } from '@/apis/KlicktippController' // import { klicktippSignIn } from '@/apis/KlicktippController'
jest.setTimeout(1000000)
jest.mock('@/mailer/sendAccountActivationEmail', () => { jest.mock('@/mailer/sendAccountActivationEmail', () => {
return { return {
__esModule: true, __esModule: true,
@ -31,24 +31,6 @@ jest.mock('@/apis/KlicktippController', () => {
let mutate: any, query: any, con: any let mutate: any, query: any, con: any
const loginQuery = gql`
query ($email: String!, $password: String!, $publisherId: Int) {
login(email: $email, password: $password, publisherId: $publisherId) {
email
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}
hasElopage
publisherId
isAdmin
}
}
`
beforeAll(async () => { beforeAll(async () => {
const testEnv = await testEnvironment() const testEnv = await testEnvironment()
mutate = testEnv.mutate mutate = testEnv.mutate
@ -77,7 +59,7 @@ describe('UserResolver', () => {
beforeAll(async () => { beforeAll(async () => {
jest.clearAllMocks() jest.clearAllMocks()
result = await mutate({ mutation: createUserMutation, variables }) result = await mutate({ mutation: createUser, variables })
}) })
afterAll(async () => { afterAll(async () => {
@ -149,7 +131,7 @@ describe('UserResolver', () => {
describe('email already exists', () => { describe('email already exists', () => {
it('throws an error', async () => { it('throws an error', async () => {
await expect(mutate({ mutation: createUserMutation, variables })).resolves.toEqual( await expect(mutate({ mutation: createUser, variables })).resolves.toEqual(
expect.objectContaining({ expect.objectContaining({
errors: [new GraphQLError('User already exists.')], errors: [new GraphQLError('User already exists.')],
}), }),
@ -160,7 +142,7 @@ describe('UserResolver', () => {
describe('unknown language', () => { describe('unknown language', () => {
it('sets "de" as default language', async () => { it('sets "de" as default language', async () => {
await mutate({ await mutate({
mutation: createUserMutation, mutation: createUser,
variables: { ...variables, email: 'bibi@bloxberg.de', language: 'es' }, variables: { ...variables, email: 'bibi@bloxberg.de', language: 'es' },
}) })
await expect(User.find()).resolves.toEqual( await expect(User.find()).resolves.toEqual(
@ -177,7 +159,7 @@ describe('UserResolver', () => {
describe('no publisher id', () => { describe('no publisher id', () => {
it('sets publisher id to null', async () => { it('sets publisher id to null', async () => {
await mutate({ await mutate({
mutation: createUserMutation, mutation: createUser,
variables: { ...variables, email: 'raeuber@hotzenplotz.de', publisherId: undefined }, variables: { ...variables, email: 'raeuber@hotzenplotz.de', publisherId: undefined },
}) })
await expect(User.find()).resolves.toEqual( await expect(User.find()).resolves.toEqual(
@ -208,11 +190,11 @@ describe('UserResolver', () => {
let newUser: any let newUser: any
beforeAll(async () => { beforeAll(async () => {
await mutate({ mutation: createUserMutation, variables: createUserVariables }) await mutate({ mutation: createUser, variables: createUserVariables })
const loginEmailOptIn = await LoginEmailOptIn.find() const loginEmailOptIn = await LoginEmailOptIn.find()
emailOptIn = loginEmailOptIn[0].verificationCode.toString() emailOptIn = loginEmailOptIn[0].verificationCode.toString()
result = await mutate({ result = await mutate({
mutation: setPasswordMutation, mutation: setPassword,
variables: { code: emailOptIn, password: 'Aa12345_' }, variables: { code: emailOptIn, password: 'Aa12345_' },
}) })
newUser = await User.find() newUser = await User.find()
@ -252,11 +234,11 @@ describe('UserResolver', () => {
describe('no valid password', () => { describe('no valid password', () => {
beforeAll(async () => { beforeAll(async () => {
await mutate({ mutation: createUserMutation, variables: createUserVariables }) await mutate({ mutation: createUser, variables: createUserVariables })
const loginEmailOptIn = await LoginEmailOptIn.find() const loginEmailOptIn = await LoginEmailOptIn.find()
emailOptIn = loginEmailOptIn[0].verificationCode.toString() emailOptIn = loginEmailOptIn[0].verificationCode.toString()
result = await mutate({ result = await mutate({
mutation: setPasswordMutation, mutation: setPassword,
variables: { code: emailOptIn, password: 'not-valid' }, variables: { code: emailOptIn, password: 'not-valid' },
}) })
}) })
@ -280,9 +262,9 @@ describe('UserResolver', () => {
describe('no valid optin code', () => { describe('no valid optin code', () => {
beforeAll(async () => { beforeAll(async () => {
await mutate({ mutation: createUserMutation, variables: createUserVariables }) await mutate({ mutation: createUser, variables: createUserVariables })
result = await mutate({ result = await mutate({
mutation: setPasswordMutation, mutation: setPassword,
variables: { code: 'not valid', password: 'Aa12345_' }, variables: { code: 'not valid', password: 'Aa12345_' },
}) })
}) })
@ -303,7 +285,7 @@ describe('UserResolver', () => {
describe('login', () => { describe('login', () => {
const variables = { const variables = {
email: 'peter@lustig.de', email: 'bibi@bloxberg.de',
password: 'Aa12345_', password: 'Aa12345_',
publisherId: 1234, publisherId: 1234,
} }
@ -316,7 +298,7 @@ describe('UserResolver', () => {
describe('no users in database', () => { describe('no users in database', () => {
beforeAll(async () => { beforeAll(async () => {
result = await query({ query: loginQuery, variables }) result = await query({ query: login, variables })
}) })
it('throws an error', () => { it('throws an error', () => {
@ -330,14 +312,8 @@ describe('UserResolver', () => {
describe('user is in database and correct login data', () => { describe('user is in database and correct login data', () => {
beforeAll(async () => { beforeAll(async () => {
await createUser(mutate, { await createUserFactory(mutate, bibiBloxberg)
email: 'peter@lustig.de', result = await query({ query: login, variables })
firstName: 'Peter',
lastName: 'Lustig',
language: 'de',
publisherId: 1234,
})
result = await query({ query: loginQuery, variables })
}) })
afterAll(async () => { afterAll(async () => {
@ -350,15 +326,15 @@ describe('UserResolver', () => {
data: { data: {
login: { login: {
coinanimation: true, coinanimation: true,
email: 'peter@lustig.de', email: 'bibi@bloxberg.de',
firstName: 'Peter', firstName: 'Bibi',
hasElopage: false, hasElopage: false,
isAdmin: false, isAdmin: false,
klickTipp: { klickTipp: {
newsletterState: false, newsletterState: false,
}, },
language: 'de', language: 'de',
lastName: 'Lustig', lastName: 'Bloxberg',
publisherId: 1234, publisherId: 1234,
}, },
}, },
@ -373,13 +349,7 @@ describe('UserResolver', () => {
describe('user is in database and wrong password', () => { describe('user is in database and wrong password', () => {
beforeAll(async () => { beforeAll(async () => {
await createUser(mutate, { await createUserFactory(mutate, bibiBloxberg)
email: 'peter@lustig.de',
firstName: 'Peter',
lastName: 'Lustig',
language: 'de',
publisherId: 1234,
})
}) })
afterAll(async () => { afterAll(async () => {
@ -388,7 +358,7 @@ describe('UserResolver', () => {
it('returns an error', () => { it('returns an error', () => {
expect( expect(
query({ query: loginQuery, variables: { ...variables, password: 'wrong' } }), query({ query: login, variables: { ...variables, password: 'wrong' } }),
).resolves.toEqual( ).resolves.toEqual(
expect.objectContaining({ expect.objectContaining({
errors: [new GraphQLError('No user with this credentials')], errors: [new GraphQLError('No user with this credentials')],
@ -399,16 +369,10 @@ describe('UserResolver', () => {
}) })
describe('logout', () => { describe('logout', () => {
const logoutQuery = gql`
query {
logout
}
`
describe('unauthenticated', () => { describe('unauthenticated', () => {
it('throws an error', async () => { it('throws an error', async () => {
resetToken() resetToken()
await expect(query({ query: logoutQuery })).resolves.toEqual( await expect(query({ query: logout })).resolves.toEqual(
expect.objectContaining({ expect.objectContaining({
errors: [new GraphQLError('401 Unauthorized')], errors: [new GraphQLError('401 Unauthorized')],
}), }),
@ -418,19 +382,13 @@ describe('UserResolver', () => {
describe('authenticated', () => { describe('authenticated', () => {
const variables = { const variables = {
email: 'peter@lustig.de', email: 'bibi@bloxberg.de',
password: 'Aa12345_', password: 'Aa12345_',
} }
beforeAll(async () => { beforeAll(async () => {
await createUser(mutate, { await createUserFactory(mutate, bibiBloxberg)
email: 'peter@lustig.de', await query({ query: login, variables })
firstName: 'Peter',
lastName: 'Lustig',
language: 'de',
publisherId: 1234,
})
await query({ query: loginQuery, variables })
}) })
afterAll(async () => { afterAll(async () => {
@ -438,7 +396,7 @@ describe('UserResolver', () => {
}) })
it('returns true', async () => { it('returns true', async () => {
await expect(query({ query: logoutQuery })).resolves.toEqual( await expect(query({ query: logout })).resolves.toEqual(
expect.objectContaining({ expect.objectContaining({
data: { logout: 'true' }, data: { logout: 'true' },
errors: undefined, errors: undefined,

View File

@ -0,0 +1,43 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { createUser, setPassword } from '@/seeds/graphql/mutations'
import { User } from '@entity/User'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { ServerUser } from '@entity/ServerUser'
import { UserInterface } from '@/seeds/users/UserInterface'
export const createUserFactory = async (mutate: any, user: UserInterface): Promise<void> => {
await mutate({ mutation: createUser, variables: user })
let dbUser = await User.findOneOrFail({ where: { email: user.email } })
if (user.emailChecked) {
const optin = await LoginEmailOptIn.findOneOrFail({ where: { userId: dbUser.id } })
await mutate({
mutation: setPassword,
variables: { password: 'Aa12345_', code: optin.verificationCode },
})
}
// refetch data
dbUser = await User.findOneOrFail({ where: { email: user.email } })
if (user.createdAt || user.deletedAt) {
if (user.createdAt) dbUser.createdAt = user.createdAt
if (user.deletedAt) dbUser.deletedAt = user.deletedAt
await dbUser.save()
}
if (user.isAdmin) {
const admin = new ServerUser()
admin.username = dbUser.firstName
admin.password = 'please_refactor'
admin.email = dbUser.email
admin.role = 'admin'
admin.activated = 1
admin.lastLogin = new Date()
admin.created = dbUser.createdAt
admin.modified = dbUser.createdAt
await admin.save()
}
}

View File

@ -0,0 +1,9 @@
export const GdtEntryType = {
FORM: 'FORM',
CVS: 'CVS',
ELOPAGE: 'ELOPAGE',
ELOPAGE_PUBLISHER: 'ELOPAGE_PUBLISHER',
DIGISTORE: 'DIGISTORE',
CVS2: 'CVS2',
GLOBAL_MODIFICATOR: 'GLOBAL_MODIFICATOR',
}

View File

@ -0,0 +1,71 @@
import gql from 'graphql-tag'
export const subscribeNewsletter = gql`
mutation ($email: String!, $language: String!) {
subscribeNewsletter(email: $email, language: $language)
}
`
export const unsubscribeNewsletter = gql`
mutation ($email: String!) {
unsubscribeNewsletter(email: $email)
}
`
export const setPassword = gql`
mutation ($code: String!, $password: String!) {
setPassword(code: $code, password: $password)
}
`
export const updateUserInfos = gql`
mutation (
$firstName: String
$lastName: String
$password: String
$passwordNew: String
$locale: String
$coinanimation: Boolean
) {
updateUserInfos(
firstName: $firstName
lastName: $lastName
password: $password
passwordNew: $passwordNew
language: $locale
coinanimation: $coinanimation
)
}
`
export const createUser = gql`
mutation (
$firstName: String!
$lastName: String!
$email: String!
$language: String!
$publisherId: Int
) {
createUser(
email: $email
firstName: $firstName
lastName: $lastName
language: $language
publisherId: $publisherId
)
}
`
export const sendCoins = gql`
mutation ($email: String!, $amount: Decimal!, $memo: String!) {
sendCoins(email: $email, amount: $amount, memo: $memo)
}
`
export const createTransactionLink = gql`
mutation ($amount: Decimal!, $memo: String!) {
createTransactionLink(amount: $amount, memo: $memo) {
code
}
}
`

View File

@ -0,0 +1,144 @@
import gql from 'graphql-tag'
export const login = gql`
query ($email: String!, $password: String!, $publisherId: Int) {
login(email: $email, password: $password, publisherId: $publisherId) {
email
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}
hasElopage
publisherId
isAdmin
}
}
`
export const verifyLogin = gql`
query {
verifyLogin {
email
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}
hasElopage
publisherId
isAdmin
}
}
`
export const logout = gql`
query {
logout
}
`
export const transactionsQuery = gql`
query (
$currentPage: Int = 1
$pageSize: Int = 25
$order: Order = DESC
$onlyCreations: Boolean = false
) {
transactionList(
currentPage: $currentPage
pageSize: $pageSize
order: $order
onlyCreations: $onlyCreations
) {
balanceGDT
count
balance
decayStartBlock
transactions {
id
typeId
amount
balance
balanceDate
memo
linkedUser {
firstName
lastName
}
decay {
decay
start
end
duration
}
}
}
}
`
export const sendResetPasswordEmail = gql`
query ($email: String!) {
sendResetPasswordEmail(email: $email)
}
`
export const listGDTEntriesQuery = gql`
query ($currentPage: Int!, $pageSize: Int!) {
listGDTEntries(currentPage: $currentPage, pageSize: $pageSize) {
count
gdtEntries {
id
amount
date
comment
gdtEntryType
factor
gdt
}
gdtSum
}
}
`
export const communityInfo = gql`
query {
getCommunityInfo {
name
description
registerUrl
url
}
}
`
export const communities = gql`
query {
communities {
id
name
url
description
registerUrl
}
}
`
export const queryTransactionLink = gql`
query ($code: String!) {
queryTransactionLink(code: $code) {
amount
memo
createdAt
validUntil
user {
firstName
publisherId
}
}
}
`

View File

@ -0,0 +1,64 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import createServer from '../server/createServer'
import { createTestClient } from 'apollo-server-testing'
import { name, internet, random } from 'faker'
import { users } from './users/index'
import { createUserFactory } from './factory/user'
import { entities } from '@entity/index'
const context = {
token: '',
setHeaders: {
push: (value: string): void => {
context.token = value
},
// eslint-disable-next-line @typescript-eslint/no-empty-function
forEach: (): void => {},
},
}
export const cleanDB = async () => {
// this only works as lond we do not have foreign key constraints
for (let i = 0; i < entities.length; i++) {
await resetEntity(entities[i])
}
}
const resetEntity = async (entity: any) => {
const items = await entity.find({ withDeleted: true })
if (items.length > 0) {
const ids = items.map((i: any) => i.id)
await entity.delete(ids)
}
}
const run = async () => {
const server = await createServer(context)
const testClient = createTestClient(server.apollo)
const { mutate } = testClient
const { con } = server
await cleanDB()
// seed the standard users
for (let i = 0; i < users.length; i++) {
await createUserFactory(mutate, users[i])
}
// seed 100 random users
for (let i = 0; i < 100; i++) {
await createUserFactory(mutate, {
firstName: name.firstName(),
lastName: name.lastName(),
email: internet.email(),
language: random.boolean() ? 'en' : 'de',
})
}
await con.close()
}
run()

View File

@ -0,0 +1,12 @@
export interface UserInterface {
email?: string
firstName?: string
lastName?: string
// description?: string
createdAt?: Date
emailChecked?: boolean
language?: string
deletedAt?: Date
publisherId?: number
isAdmin?: boolean
}

View File

@ -0,0 +1,11 @@
import { UserInterface } from './UserInterface'
export const bibiBloxberg: UserInterface = {
email: 'bibi@bloxberg.de',
firstName: 'Bibi',
lastName: 'Bloxberg',
// description: 'Hex Hex',
emailChecked: true,
language: 'de',
publisherId: 1234,
}

View File

@ -0,0 +1,10 @@
import { UserInterface } from './UserInterface'
export const bobBaumeister: UserInterface = {
email: 'bob@baumeister.de',
firstName: 'Bob',
lastName: 'der Baumeister',
// description: 'Können wir das schaffen? Ja, wir schaffen das!',
emailChecked: true,
language: 'de',
}

View File

@ -0,0 +1,12 @@
import { UserInterface } from './UserInterface'
export const garrickOllivander: UserInterface = {
email: 'garrick@ollivander.com',
firstName: 'Garrick',
lastName: 'Ollivander',
// description: `Curious ... curious ...
// Renowned wandmaker Mr Ollivander owns the wand shop Ollivanders: Makers of Fine Wands Since 382 BC in Diagon Alley. His shop is widely considered the best place to purchase a wand.`,
createdAt: new Date('2022-01-10T10:23:17'),
emailChecked: false,
language: 'en',
}

View File

@ -0,0 +1,15 @@
import { peterLustig } from './peter-lustig'
import { bibiBloxberg } from './bibi-bloxberg'
import { bobBaumeister } from './bob-baumeister'
import { raeuberHotzenplotz } from './raeuber-hotzenplotz'
import { stephenHawking } from './stephen-hawking'
import { garrickOllivander } from './garrick-ollivander'
export const users = [
peterLustig,
bibiBloxberg,
bobBaumeister,
raeuberHotzenplotz,
stephenHawking,
garrickOllivander,
]

View File

@ -0,0 +1,12 @@
import { UserInterface } from './UserInterface'
export const peterLustig: UserInterface = {
email: 'peter@lustig.de',
firstName: 'Peter',
lastName: 'Lustig',
// description: 'Latzhose und Nickelbrille',
createdAt: new Date('2020-11-25T10:48:43'),
emailChecked: true,
language: 'de',
isAdmin: true,
}

View File

@ -0,0 +1,10 @@
import { UserInterface } from './UserInterface'
export const raeuberHotzenplotz: UserInterface = {
email: 'raeuber@hotzenplotz.de',
firstName: 'Räuber',
lastName: 'Hotzenplotz',
// description: 'Pfefferpistole',
emailChecked: true,
language: 'de',
}

View File

@ -0,0 +1,12 @@
import { UserInterface } from './UserInterface'
export const stephenHawking: UserInterface = {
email: 'stephen@hawking.uk',
firstName: 'Stephen',
lastName: 'Hawking',
// description: 'A Brief History of Time',
emailChecked: true,
createdAt: new Date('1942-01-08T09:17:52'),
deletedAt: new Date('2018-03-14T09:17:52'),
language: 'en',
}

View File

@ -1,25 +0,0 @@
import gql from 'graphql-tag'
export const createUserMutation = gql`
mutation (
$email: String!
$firstName: String!
$lastName: String!
$language: String!
$publisherId: Int
) {
createUser(
email: $email
firstName: $firstName
lastName: $lastName
language: $language
publisherId: $publisherId
)
}
`
export const setPasswordMutation = gql`
mutation ($code: String!, $password: String!) {
setPassword(code: $code, password: $password)
}
`

View File

@ -4,9 +4,6 @@
import { createTestClient } from 'apollo-server-testing' import { createTestClient } from 'apollo-server-testing'
import createServer from '../src/server/createServer' import createServer from '../src/server/createServer'
import { initialize } from '@dbTools/helpers' import { initialize } from '@dbTools/helpers'
import { createUserMutation, setPasswordMutation } from './graphql'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { User } from '@entity/User'
import { entities } from '@entity/index' import { entities } from '@entity/index'
export const headerPushMock = jest.fn((t) => { export const headerPushMock = jest.fn((t) => {
@ -46,19 +43,6 @@ export const resetEntity = async (entity: any) => {
} }
} }
export const createUser = async (mutate: any, user: any) => {
// resetToken()
await mutate({ mutation: createUserMutation, variables: user })
const dbUser = await User.findOne({ where: { email: user.email } })
if (!dbUser) throw new Error('Ups, no user found')
const optin = await LoginEmailOptIn.findOne({ where: { userId: dbUser.id } })
if (!optin) throw new Error('Ups, no optin found')
await mutate({
mutation: setPasswordMutation,
variables: { password: 'Aa12345_', code: optin.verificationCode },
})
}
export const resetToken = () => { export const resetToken = () => {
context.token = '' context.token = ''
} }

View File

@ -4,3 +4,4 @@
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
console.info = () => {} console.info = () => {}
jest.setTimeout(1000000)

View File

@ -811,6 +811,11 @@
"@types/qs" "*" "@types/qs" "*"
"@types/serve-static" "*" "@types/serve-static" "*"
"@types/faker@^5.5.9":
version "5.5.9"
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.9.tgz#588ede92186dc557bff8341d294335d50d255f0c"
integrity sha512-uCx6mP3UY5SIO14XlspxsGjgaemrxpssJI0Ol+GfhxtcKpv9pgRZYsS4eeKeHVLje6Qtc8lGszuBI461+gVZBA==
"@types/fs-capacitor@*": "@types/fs-capacitor@*":
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz#17113e25817f584f58100fb7a08eed288b81956e" resolved "https://registry.yarnpkg.com/@types/fs-capacitor/-/fs-capacitor-2.0.0.tgz#17113e25817f584f58100fb7a08eed288b81956e"
@ -2510,6 +2515,11 @@ express@^4.17.1:
utils-merge "1.0.1" utils-merge "1.0.1"
vary "~1.1.2" vary "~1.1.2"
faker@^5.5.3:
version "5.5.3"
resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e"
integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3" version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"

View File

@ -1,3 +1,4 @@
node_modules node_modules
.git .git
.gitignore .gitignore
!.eslintignore

View File

@ -1,3 +1,3 @@
node_modules node_modules/
**/*.min.js dist/
dist coverage/

View File

@ -8,9 +8,24 @@ module.exports = {
parserOptions: { parserOptions: {
parser: 'babel-eslint', parser: 'babel-eslint',
}, },
extends: ['standard', 'plugin:vue/essential', 'plugin:prettier/recommended'], extends: [
'standard',
'plugin:vue/essential',
'plugin:prettier/recommended',
'plugin:@intlify/vue-i18n/recommended',
],
// required to lint *.vue files // required to lint *.vue files
plugins: ['vue', 'prettier', 'jest'], plugins: ['vue', 'prettier', 'jest'],
overrides: [
{
files: ['*.json'],
extends: ['plugin:@intlify/vue-i18n/recommended'],
rules: {
// TODO: enable
'@intlify/vue-i18n/no-html-messages': 'off',
},
},
],
// add your custom rules here // add your custom rules here
rules: { rules: {
'no-console': ['error'], 'no-console': ['error'],
@ -22,6 +37,29 @@ module.exports = {
allowBinding: false, allowBinding: false,
}, },
], ],
'@intlify/vue-i18n/no-dynamic-keys': 'error',
'@intlify/vue-i18n/no-unused-keys': [
'error',
{
src: './src',
extensions: ['.js', '.vue'],
// TODO: remove ignores
ignores: [
'/site.thx./',
'/form./',
'/time./',
'/decay.types./',
'settings.password.resend_subtitle',
'settings.password.reset-password.text',
'settings.password.set',
'settings.password.set-password.text',
'settings.password.subtitle',
'site.login.signin',
],
enableFix: false,
},
],
'@intlify/vue-i18n/no-missing-keys-in-other-locales': 'error',
'prettier/prettier': [ 'prettier/prettier': [
'error', 'error',
{ {
@ -29,4 +67,12 @@ module.exports = {
}, },
], ],
}, },
settings: {
'vue-i18n': {
localeDir: './src/locales/*.json',
// Specify the version of `vue-i18n` you are using.
// If not specified, the message will be parsed twice.
messageSyntaxVersion: '^8.22.4',
},
},
} }

1
frontend/.gitignore vendored
View File

@ -5,7 +5,6 @@ dist/
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
test/unit/coverage
package-lock.json package-lock.json
/.env /.env

View File

@ -8,11 +8,10 @@
"build": "vue-cli-service build", "build": "vue-cli-service build",
"dev": "yarn run serve", "dev": "yarn run serve",
"analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json", "analyse-bundle": "yarn build && webpack-bundle-analyzer dist/webpack.stats.json",
"lint": "eslint --max-warnings=0 --ext .js,.vue .", "lint": "eslint --max-warnings=0 --ext .js,.vue,.json .",
"stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'", "stylelint": "stylelint --max-warnings=0 '**/*.{scss,vue}'",
"i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'",
"test": "TZ=UTC jest --coverage", "test": "TZ=UTC jest --coverage",
"locales": "scripts/missing-keys.sh && scripts/sort.sh" "locales": "scripts/sort.sh"
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.13.13", "@babel/core": "^7.13.13",
@ -67,6 +66,7 @@
"vuex-persistedstate": "^4.0.0-beta.3" "vuex-persistedstate": "^4.0.0-beta.3"
}, },
"devDependencies": { "devDependencies": {
"@intlify/eslint-plugin-vue-i18n": "^1.4.0",
"@vue/cli-plugin-babel": "^3.7.0", "@vue/cli-plugin-babel": "^3.7.0",
"@vue/cli-plugin-eslint": "^3.7.0", "@vue/cli-plugin-eslint": "^3.7.0",
"@vue/cli-service": "^3.7.0", "@vue/cli-service": "^3.7.0",

View File

@ -1,36 +0,0 @@
{"state":"success", "statisticdata":
[
{
"i_creation_sum": 29288278.4653,
"i_creation_mon": 68278.4653,
"i_creation_365d": 19288278.4653,
"i_creation_30d": 288278.4653,
"i_creation_14d": 88278.4653,
"i_creation_7d": 3278.4653
},
{
"i_transience_sum": 8278.4653,
"i_transience_mon": 8278.4653,
"i_transience_365d": 8278.4653,
"i_transience_30d": 178.4653,
"i_transience_14d": 78.4653,
"i_transience_7d": 8.4653
},
{
"i_exchange_sum": 23345.2324,
"i_exchange_mon": 2,
"i_exchange_365d": 2,
"i_exchange_30d": 2,
"i_exchange_14d": 2,
"i_exchange_7d": 2
},
{
"i_members_sum": 5398,
"i_members_mon": 234,
"i_members_365d": 2356,
"i_members_30d": 123,
"i_members_14d": 23,
"i_members_7d": 24
}
]
}

View File

@ -1,64 +0,0 @@
{"state":"success", "statisticdata":
[
{
"charts_creation_0_mon": 5635,
"charts_creation_1_mon": 5635,
"charts_creation_2_mon": 5635,
"charts_creation_3_mon": 5635,
"charts_creation_4_mon": 5635,
"charts_creation_5_mon": 5635,
"charts_creation_6_mon": 5635,
"charts_creation_7_mon": 5635,
"charts_creation_8_mon": 5635,
"charts_creation_9_mon": 5635,
"charts_creation_10_mon": 5635,
"charts_creation_11_mon": 5635,
"charts_creation_12_mon": 5635
},
{
"charts_transience_0_mon": 5635,
"charts_transience_1_mon": 5635,
"charts_transience_2_mon": 5635,
"charts_transience_3_mon": 5635,
"charts_transience_4_mon": 5635,
"charts_transience_5_mon": 5635,
"charts_transience_6_mon": 5635,
"charts_transience_7_mon": 5635,
"charts_transience_8_mon": 5635,
"charts_transience_9_mon": 5635,
"charts_transience_10_mon": 5635,
"charts_transience_11_mon": 5635,
"charts_transience_12_mon": 5635
},
{
"charts_exchange_0_mon": 5635,
"charts_exchange_1_mon": 5635,
"charts_exchange_2_mon": 5635,
"charts_exchange_3_mon": 5635,
"charts_exchange_4_mon": 5635,
"charts_exchange_5_mon": 5635,
"charts_exchange_6_mon": 5635,
"charts_exchange_7_mon": 5635,
"charts_exchange_8_mon": 5635,
"charts_exchange_9_mon": 5635,
"charts_exchange_10_mon": 5635,
"charts_exchange_11_mon": 5635,
"charts_exchange_12_mon": 5635
},
{
"charts_members_0_mon": 5635,
"charts_members_1_mon": 5635,
"charts_members_2_mon": 5635,
"charts_members_3_mon": 5635,
"charts_members_4_mon": 5635,
"charts_members_5_mon": 5635,
"charts_members_6_mon": 5635,
"charts_members_7_mon": 5635,
"charts_members_8_mon": 5635,
"charts_members_9_mon": 5635,
"charts_members_10_mon": 5635,
"charts_members_11_mon": 5635,
"charts_members_12_mon": 5635
}
]
}

View File

@ -1,19 +0,0 @@
{"state":"success", "statisticdata":
[
{
"community_entries1_mon": 5635,
"community_entries2_mon": 5635,
"community_entries3_mon": 5635,
"community_entries4_mon": 5635,
"community_entries5_mon": 5635,
"community_entries6_mon": 5635,
"community_entries7_mon": 5635,
"community_entries8_mon": 5635,
"community_entries9_mon": 5635,
"community_entries0_mon": 5635,
"community_entries10_mon": 5635,
"community_entries11_mon": 5635,
"community_entries12_mon": 5635
}
]
}

View File

@ -1,61 +0,0 @@
{"state":"success", "transactions":
[
{
"name": "Jon Tester",
"email": "jon@example.de",
"type": "send",
"transaction_id": 12,
"date": "29-11-2020",
"balance": 7000,
"memo": "Reperatur Waschbecken",
"pubkey": "abcdefghi123456789"
},
{
"name": "Gradido Community",
"email": "gradido@example.de",
"type": "creation",
"transaction_id": 11,
"date": "1-11-2020",
"balance": 10000,
"memo": "Müll gesammelt im Wald",
"pubkey": "abcdefghi123456789"
},
{
"name": "Maria Tester",
"email": "maria@example.de",
"type": "receive",
"transaction_id": 7,
"date": "23-10-2020",
"balance": 5000,
"memo": "Spende an Alice ",
"pubkey": "abcdefghi123456789"
},
{
"name": "Alice Tester",
"email": "alice@example.de",
"type": "receive",
"transaction_id": 5,
"date": "2-8-2020",
"balance": 1000,
"memo": "Bob hat meinen Müll getrennt",
"pubkey": "abcdefghi123456789"
},
{
"name": "Gradido Community",
"email": "gradido@example.de",
"type": "creation",
"transaction_id": 1,
"date": "11-7-2020",
"balance": 10000,
"memo": "Bob hat meinen Müll getrennt",
"pubkey": "abcdefghi123456789"
}
],
"transactionExecutingCount": 8750,
"count": 5
}

View File

@ -1,49 +0,0 @@
{"state":"success", "participation":
[
{
"name": "",
"type": "submitted",
"participation_id": 412,
"date_submitted": "9-12-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "8-12-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
},
{
"name": "",
"type": "in progress",
"participation_id": 312,
"date_submitted": "2-11-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "2-11-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
},
{
"name": "",
"type": "confirmed",
"participation_id": 212,
"date_submitted": "20-10-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "20-10-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
},
{
"name": "",
"type": "rejected",
"participation_id": 142,
"date_submitted": "17-9-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "17-9-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
}
],
"count": 4
}

View File

@ -1,52 +0,0 @@
{"state":"success", "admin0userlist":
[
{
"created": 1578688666,
"disabled": false,
"email": "dervommond@gmail.com",
"email_checked": true,
"first_name": "Max",
"group_alias": "gdd1",
"ident_hash": 2928827813,
"last_name": "Miau",
"public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b",
"role": "admin",
"username": "",
"balance_gdd": 174500,
"balance_gdt": 4500,
"errorCount": 0
},
{
"created": 1578685678,
"disabled": false,
"email": "ttwer@gmail.com",
"email_checked": true,
"first_name": "John",
"group_alias": "gdd1",
"ident_hash": 2928827813,
"last_name": "Doe",
"public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71x",
"role": "user",
"username": "",
"balance_gdd": 144500,
"balance_gdt": 0,
"errorCount": 0
},
{
"created": 1578635671,
"disabled": false,
"email": "test@gmail.com",
"email_checked": true,
"first_name": "Alice",
"group_alias": "gdd1",
"ident_hash": 4928827813,
"last_name": "Seer",
"public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71a",
"role": "user",
"username": "",
"balance_gdd": 444500,
"balance_gdt": 4500,
"errorCount": 0
}
]
}

View File

@ -1,19 +0,0 @@
{"state":"success", "userdata":
[
{
"created": 1578688666,
"disabled": false,
"email": "dervommond@gmail.com",
"email_checked": true,
"first_name": "Max",
"group_alias": "gdd1",
"ident_hash": 2928827813,
"last_name": "Miau",
"public_hex": "2ed28a1cf5e116d83615406bc577152221c2f774a5656f66a0e7540f7576d71b",
"role": "admin",
"username": "",
"balance": 174500,
"errorCount": 0
}
]
}

View File

@ -1,45 +0,0 @@
{"state":"success", "participation":
[
{
"type": "submitted",
"participation_id": 412,
"date_submitted": "9-12-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "8-12-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
},
{
"type": "in progress",
"participation_id": 312,
"date_submitted": "2-11-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "2-11-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
},
{
"type": "confirmed",
"participation_id": 212,
"date_submitted": "20-10-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "20-10-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
},
{
"type": "rejected",
"participation_id": 142,
"date_submitted": "17-9-2020",
"titel": "Lorem Ipsum panta lore es Tastina sero was. ",
"text": "Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. Lorem Ipsum panta lore es Tastina sero was. ",
"date_participation": "17-9-2020",
"plz_participation": "01099",
"pubkey": "abcdefghi123456789"
}
],
"count": 4
}

View File

@ -1,61 +0,0 @@
{"state":"success", "transactions":
[
{
"name": "Jon Tester",
"email": "jon@example.de",
"type": "send",
"transaction_id": 12,
"date": "29-11-2020",
"balance": 7000,
"memo": "Reperatur Waschbecken",
"pubkey": "abcdefghi123456789"
},
{
"name": "Gradido Community",
"email": "gradido@example.de",
"type": "creation",
"transaction_id": 11,
"date": "1-11-2020",
"balance": 10000,
"memo": "Müll gesammelt im Wald",
"pubkey": "abcdefghi123456789"
},
{
"name": "Maria Tester",
"email": "maria@example.de",
"type": "receive",
"transaction_id": 7,
"date": "23-10-2020",
"balance": 5000,
"memo": "Spende an Alice ",
"pubkey": "abcdefghi123456789"
},
{
"name": "Alice Tester",
"email": "alice@example.de",
"type": "receive",
"transaction_id": 5,
"date": "2-8-2020",
"balance": 1000,
"memo": "Bob hat meinen Müll getrennt",
"pubkey": "abcdefghi123456789"
},
{
"name": "Gradido Community",
"email": "gradido@example.de",
"type": "creation",
"transaction_id": 1,
"date": "11-7-2020",
"balance": 10000,
"memo": "Bob hat meinen Müll getrennt",
"pubkey": "abcdefghi123456789"
}
],
"transactionExecutingCount": 8750,
"count": 5
}

View File

@ -1,17 +0,0 @@
#!/bin/bash
ROOT_DIR=$(dirname "$0")/..
sorting="jq -f $ROOT_DIR/scripts/sort_filter.jq"
english="$sorting $ROOT_DIR/src/locales/en.json"
german="$sorting $ROOT_DIR/src/locales/de.json"
listPaths="jq -c 'path(..)|[.[]|tostring]|join(\".\")'"
diffString="<( $english | $listPaths ) <( $german | $listPaths )"
if eval "diff -q $diffString";
then
: # all good
else
eval "diff -y $diffString | grep '[|<>]'";
printf "\nEnglish and German translation keys do not match, see diff above.\n"
exit 1
fi

View File

@ -11,7 +11,7 @@ describe('ContentFooter', () => {
$i18n: { $i18n: {
locale: 'en', locale: 'en',
}, },
$t: jest.fn((t) => t), $t: jest.fn((t, options) => (options ? [t, options] : t)),
} }
const Wrapper = () => { const Wrapper = () => {
@ -33,11 +33,11 @@ describe('ContentFooter', () => {
}) })
it('renders the copyright year', () => { it('renders the copyright year', () => {
expect(wrapper.find('div.copyright').text()).toMatch(/©\s*2[0-9]{3,3}\s+/) expect(mocks.$t).toBeCalledWith('footer.copyright.year', { year: 2022 })
}) })
it('renders a link to Gradido-Akademie', () => { it('renders a link to Gradido-Akademie', () => {
expect(wrapper.find('div.copyright').find('a').text()).toEqual('Gradido-Akademie') expect(wrapper.find('div.copyright').find('a').text()).toEqual('footer.copyright.link')
}) })
it('links to the login page when clicked on copyright', () => { it('links to the login page when clicked on copyright', () => {
@ -51,7 +51,7 @@ describe('ContentFooter', () => {
it('shows the current version', async () => { it('shows the current version', async () => {
wrapper.setData({ version: 1.23 }) wrapper.setData({ version: 1.23 })
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('div.copyright').findAll('a').at(1).text()).toEqual('App version 1.23') expect(mocks.$t).toBeCalledWith('footer.app_version', { version: 1.23 })
}) })
it('links to latest release on GitHub', () => { it('links to latest release on GitHub', () => {
@ -64,7 +64,7 @@ describe('ContentFooter', () => {
wrapper.setData({ shortHash: 'ACCEDED' }) wrapper.setData({ shortHash: 'ACCEDED' })
wrapper.setData({ hash: 'ACCEDEDC001D00DC001D00DC001D00DC001CAFA' }) wrapper.setData({ hash: 'ACCEDEDC001D00DC001D00DC001D00DC001CAFA' })
await wrapper.vm.$nextTick() await wrapper.vm.$nextTick()
expect(wrapper.find('div.copyright').findAll('a').at(2).text()).toEqual('(ACCEDED)') expect(mocks.$t).toBeCalledWith('footer.short_hash', { shortHash: 'ACCEDED' })
}) })
it('links to last release commit', async () => { it('links to last release commit', async () => {
@ -78,7 +78,7 @@ describe('ContentFooter', () => {
describe('links to gradido.net', () => { describe('links to gradido.net', () => {
it('has a link to the legal notice', () => { it('has a link to the legal notice', () => {
expect(wrapper.findAll('a.nav-link').at(0).text()).toEqual('imprint') expect(wrapper.findAll('a.nav-link').at(0).text()).toEqual('footer.imprint')
}) })
it('links to the https://gradido.net/en/impressum when locale is en', () => { it('links to the https://gradido.net/en/impressum when locale is en', () => {
@ -88,7 +88,7 @@ describe('ContentFooter', () => {
}) })
it('has a link to the privacy policy', () => { it('has a link to the privacy policy', () => {
expect(wrapper.findAll('a.nav-link').at(1).text()).toEqual('privacy_policy') expect(wrapper.findAll('a.nav-link').at(1).text()).toEqual('footer.privacy_policy')
}) })
it('links to the https://gradido.net/en/datenschutz when locale is en', () => { it('links to the https://gradido.net/en/datenschutz when locale is en', () => {
@ -98,7 +98,7 @@ describe('ContentFooter', () => {
}) })
it('has a link to the members area', () => { it('has a link to the members area', () => {
expect(wrapper.findAll('a.nav-link').at(2).text()).toEqual('members_area') expect(wrapper.findAll('a.nav-link').at(2).text()).toEqual('navigation.members_area')
}) })
it('links to the elopage', () => { it('links to the elopage', () => {

View File

@ -3,24 +3,24 @@
<b-row align-v="center" class="mt-4 justify-content-lg-between"> <b-row align-v="center" class="mt-4 justify-content-lg-between">
<b-col> <b-col>
<div class="copyright text-center text-lg-center text-muted"> <div class="copyright text-center text-lg-center text-muted">
© {{ year }} {{ $t('footer.copyright.year', { year }) }}
<a <a
:href="`https://gradido.net/${$i18n.locale}`" :href="`https://gradido.net/${$i18n.locale}`"
class="font-weight-bold ml-1" class="font-weight-bold ml-1"
target="_blank" target="_blank"
> >
Gradido-Akademie {{ $t('footer.copyright.link') }}
</a> </a>
| {{ $t('math.pipe') }}
<a href="https://github.com/gradido/gradido/releases/latest" target="_blank"> <a href="https://github.com/gradido/gradido/releases/latest" target="_blank">
App version {{ version }} {{ $t('footer.app_version', { version }) }}
</a> </a>
<a <a
v-if="hash" v-if="hash"
:href="'https://github.com/gradido/gradido/commit/' + hash" :href="'https://github.com/gradido/gradido/commit/' + hash"
target="_blank" target="_blank"
> >
({{ shortHash }}) {{ $t('footer.short_hash', { shortHash }) }}
</a> </a>
</div> </div>
</b-col> </b-col>
@ -29,16 +29,16 @@
<b-col> <b-col>
<b-nav class="nav-footer justify-content-center"> <b-nav class="nav-footer justify-content-center">
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank"> <b-nav-item :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
{{ $t('imprint') }} {{ $t('footer.imprint') }}
</b-nav-item> </b-nav-item>
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank"> <b-nav-item :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
{{ $t('privacy_policy') }} {{ $t('footer.privacy_policy') }}
</b-nav-item> </b-nav-item>
<b-nav-item <b-nav-item
:href="`https://elopage.com/s/gradido/sign_in?locale=${$i18n.locale}`" :href="`https://elopage.com/s/gradido/sign_in?locale=${$i18n.locale}`"
target="_blank" target="_blank"
> >
{{ $t('members_area') }} {{ $t('navigation.members_area') }}
</b-nav-item> </b-nav-item>
<b-nav-item <b-nav-item
:href=" :href="
@ -48,10 +48,10 @@
" "
target="_blank" target="_blank"
> >
{{ $t('whitepaper') }} {{ $t('footer.whitepaper') }}
</b-nav-item> </b-nav-item>
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/contact/`" target="_blank"> <b-nav-item :href="`https://gradido.net/${$i18n.locale}/contact/`" target="_blank">
{{ $t('site.navbar.support') }} {{ $t('navigation.support') }}
</b-nav-item> </b-nav-item>
</b-nav> </b-nav>
</b-col> </b-col>

View File

@ -14,7 +14,7 @@
<b-col cols="6"> <b-col cols="6">
<div> <div>
{{ (Number(balance) - Number(decay.decay)) | GDD }} {{ (Number(balance) - Number(decay.decay)) | GDD }}
{{ decay.decay | GDD }} = {{ decay.decay | GDD }} {{ $t('math.equal') }}
<b>{{ balance | GDD }}</b> <b>{{ balance | GDD }}</b>
</div> </div>
</b-col> </b-col>

View File

@ -4,12 +4,11 @@
<b-col cols="12" class="text-center"> <b-col cols="12" class="text-center">
<div> <div>
<div class="display-4">{{ $t('decay.Starting_block_decay') }}</div> <div class="display-4">{{ $t('decay.Starting_block_decay') }}</div>
<div>{{ $t('decay.decay_introduced') }} :</div> <div>{{ $t('decay.decay_introduced') }}</div>
</div> </div>
<div> <div>
<span v-if="decay.start"> <span v-if="decay.start">
{{ $d(new Date(decay.start), 'long') }} {{ $d(new Date(decay.start), 'long') }}
{{ $i18n.locale === 'de' ? 'Uhr' : '' }}
</span> </span>
</div> </div>
</b-col> </b-col>
@ -28,7 +27,8 @@
</b-row> </b-row>
<!-- Type--> <!-- Type-->
<b-row> <b-row>
<b-col cols="6" class="text-right">{{ $t(`decay.${typeId.toLowerCase()}`) }}</b-col> <!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<b-col cols="6" class="text-right">{{ $t(`decay.types.${typeId.toLowerCase()}`) }}</b-col>
<b-col cols="6">{{ amount | GDD }}</b-col> <b-col cols="6">{{ amount | GDD }}</b-col>
</b-row> </b-row>
<!-- Decay--> <!-- Decay-->

View File

@ -15,7 +15,6 @@
<div> <div>
<span> <span>
{{ $d(new Date(decay.start), 'long') }} {{ $d(new Date(decay.start), 'long') }}
{{ $i18n.locale === 'de' ? 'Uhr' : '' }}
</span> </span>
</div> </div>
</b-col> </b-col>
@ -44,7 +43,8 @@
</b-row> </b-row>
<!-- Type--> <!-- Type-->
<b-row> <b-row>
<b-col cols="6" class="text-right">{{ $t(`decay.${typeId.toLowerCase()}`) }}</b-col> <!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<b-col cols="6" class="text-right">{{ $t(`decay.types.${typeId.toLowerCase()}`) }}</b-col>
<b-col cols="6">{{ amount | GDD }}</b-col> <b-col cols="6">{{ amount | GDD }}</b-col>
</b-row> </b-row>
<!-- Decay--> <!-- Decay-->
@ -82,7 +82,8 @@ export default {
const result = [] const result = []
order.forEach((timeSpan) => { order.forEach((timeSpan) => {
if (this.duration[timeSpan] > 0) { if (this.duration[timeSpan] > 0) {
const locale = this.$t(`decay.${timeSpan}`) // eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
const locale = this.$t(`time.${timeSpan}`)
result.push(`${this.duration[timeSpan]} ${locale}`) result.push(`${this.duration[timeSpan]} ${locale}`)
} }
}) })

View File

@ -1,5 +1,6 @@
<template> <template>
<b-alert show variant="secondary"> <b-alert show variant="secondary">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-v-html -->
<span class="alert-text" v-html="$t('form.scann_code')"></span> <span class="alert-text" v-html="$t('form.scann_code')"></span>
<b-col v-show="!scan" lg="12" class="text-right"> <b-col v-show="!scan" lg="12" class="text-right">
<a @click="toggle" class="nav-link pointer"> <a @click="toggle" class="nav-link pointer">
@ -18,6 +19,7 @@
<b-row> <b-row>
<b-col lg="8"> <b-col lg="8">
<b-alert show variant="secondary"> <b-alert show variant="secondary">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-v-html -->
<span class="alert-text" v-html="$t('form.scann_code')"></span> <span class="alert-text" v-html="$t('form.scann_code')"></span>
</b-alert> </b-alert>
</b-col> </b-col>

View File

@ -28,12 +28,14 @@
<strong>{{ $t('gdd_per_link.decay-14-day') }}</strong> <strong>{{ $t('gdd_per_link.decay-14-day') }}</strong>
</b-col> </b-col>
<b-col class="text-right borderbottom"> <b-col class="text-right borderbottom">
<strong>~ {{ (amount * 0.028 * -1) | GDD }}</strong> <strong>{{ $t('math.aprox') }} {{ (amount * 0.028 * -1) | GDD }}</strong>
</b-col> </b-col>
</b-row> </b-row>
<b-row class="pr-3"> <b-row class="pr-3">
<b-col class="text-right">{{ $t('form.new_balance') }}</b-col> <b-col class="text-right">{{ $t('form.new_balance') }}</b-col>
<b-col class="text-right">~ {{ (balance - amount - amount * 0.028) | GDD }}</b-col> <b-col class="text-right">
{{ $t('math.aprox') }} {{ (balance - amount - amount * 0.028) | GDD }}
</b-col>
</b-row> </b-row>
</b-container> </b-container>

View File

@ -15,7 +15,7 @@
<label class="input-2" for="input-2">{{ $t('form.amount') }}</label> <label class="input-2" for="input-2">{{ $t('form.amount') }}</label>
<b-input-group id="input-group-2" class="borderbottom" size="lg"> <b-input-group id="input-group-2" class="borderbottom" size="lg">
<b-input-group-prepend class="p-2 d-none d-md-block gray-background"> <b-input-group-prepend class="p-2 d-none d-md-block gray-background">
<div class="m-1 mt-2">GDD</div> <div class="m-1 mt-2">{{ $t('GDD') }}</div>
</b-input-group-prepend> </b-input-group-prepend>
<div class="p-3">{{ (amount * -1) | GDD }}</div> <div class="p-3">{{ (amount * -1) | GDD }}</div>
@ -27,7 +27,7 @@
<b-input-group-prepend class="d-none d-md-block gray-background"> <b-input-group-prepend class="d-none d-md-block gray-background">
<b-icon icon="chat-right-text" class="display-4 m-3 mt-4"></b-icon> <b-icon icon="chat-right-text" class="display-4 m-3 mt-4"></b-icon>
</b-input-group-prepend> </b-input-group-prepend>
<div class="p-3">{{ memo ? memo : '-' }}</div> <div class="p-3">{{ memo ? memo : $t('em-dash') }}</div>
</b-input-group> </b-input-group>
</b-list-group> </b-list-group>
</b-col> </b-col>

View File

@ -76,7 +76,7 @@
<label class="input-2" for="input-2">{{ $t('form.amount') }}</label> <label class="input-2" for="input-2">{{ $t('form.amount') }}</label>
<b-input-group id="input-group-2" class="border border-default" size="lg"> <b-input-group id="input-group-2" class="border border-default" size="lg">
<b-input-group-prepend class="p-2 d-none d-md-block"> <b-input-group-prepend class="p-2 d-none d-md-block">
<div class="m-1 mt-2">GDD</div> <div class="m-1 mt-2">{{ $t('GDD') }}</div>
</b-input-group-prepend> </b-input-group-prepend>
<b-form-input <b-form-input

View File

@ -19,7 +19,7 @@
> >
{{ $t('transaction.receiverDeleted') }} {{ $t('transaction.receiverDeleted') }}
</div> </div>
<div v-else>({{ errorResult }})</div> <div v-else>{{ errorResult }}</div>
</div> </div>
<p class="text-center mt-3"> <p class="text-center mt-3">
<b-button variant="success" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button> <b-button variant="success" @click="$emit('on-reset')">{{ $t('form.close') }}</b-button>

View File

@ -440,7 +440,7 @@ describe('GddTransactionList', () => {
}) })
it('shows the text "1 / 2"', () => { it('shows the text "1 / 2"', () => {
expect(paginationButtons.find('p.text-center').text()).toBe('1 / 2') expect(paginationButtons.find('p.text-center').text()).toBe('1 math.div 2')
}) })
it('emits update-transactions when next button is clicked', async () => { it('emits update-transactions when next button is clicked', async () => {
@ -452,7 +452,7 @@ describe('GddTransactionList', () => {
it('shows text "2 / 2" when next button is clicked', async () => { it('shows text "2 / 2" when next button is clicked', async () => {
await paginationButtons.find('button.next-page').trigger('click') await paginationButtons.find('button.next-page').trigger('click')
expect(paginationButtons.find('p.text-center').text()).toBe('2 / 2') expect(paginationButtons.find('p.text-center').text()).toBe('2 math.div 2')
}) })
it('has next-button disabled when next button is clicked', async () => { it('has next-button disabled when next button is clicked', async () => {

View File

@ -2,10 +2,12 @@
<div> <div>
<b-list-group> <b-list-group>
<b-list-group-item v-if="count > 5"> <b-list-group-item v-if="count > 5">
<!-- eslint-disable @intlify/vue-i18n/no-v-html -->
<router-link <router-link
to="/transactions" to="/transactions"
v-html="$t('transaction.show_all', { count: count })" v-html="$t('transaction.show_all', { count })"
></router-link> ></router-link>
<!-- eslint-enable @intlify/vue-i18n/no-v-html -->
</b-list-group-item> </b-list-group-item>
</b-list-group> </b-list-group>
</div> </div>

View File

@ -54,31 +54,31 @@ describe('Navbar', () => {
expect(wrapper.findAll('.nav-item').at(1).text()).toEqual('1234 GDD') expect(wrapper.findAll('.nav-item').at(1).text()).toEqual('1234 GDD')
}) })
it('has first nav-item "overview" in navbar', () => { it('has first nav-item "navigation.overview" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('overview') expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('navigation.overview')
}) })
it('has first nav-item "send" in navbar', () => { it('has first nav-item "navigation.send" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(4).text()).toEqual('send') expect(wrapper.findAll('.nav-item').at(4).text()).toEqual('navigation.send')
}) })
it('has first nav-item "transactions" in navbar', () => { it('has first nav-item "navigation.transactions" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('transactions') expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.transactions')
}) })
it('has first nav-item "my-profil" in navbar', () => { it('has first nav-item "navigation.profile" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('site.navbar.my-profil') expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.profile')
}) })
it('has a link to the members area', () => { it('has a link to the members area', () => {
expect(wrapper.findAll('.nav-item').at(7).text()).toContain('members_area') expect(wrapper.findAll('.nav-item').at(7).text()).toContain('navigation.members_area')
expect(wrapper.findAll('.nav-item').at(7).find('a').attributes('href')).toBe( expect(wrapper.findAll('.nav-item').at(7).find('a').attributes('href')).toBe(
'https://elopage.com', 'https://elopage.com',
) )
}) })
it('has first nav-item "admin_area" in navbar', () => { it('has first nav-item "navigation.admin_area" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(8).text()).toEqual('admin_area') expect(wrapper.findAll('.nav-item').at(8).text()).toEqual('navigation.admin_area')
}) })
it('has first nav-item "logout" in navbar', () => { it('has first nav-item "navigation.logout" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(9).text()).toEqual('logout') expect(wrapper.findAll('.nav-item').at(9).text()).toEqual('navigation.logout')
}) })
}) })
}) })

View File

@ -10,10 +10,10 @@
</div> </div>
<b-navbar-nav class="ml-auto" is-nav> <b-navbar-nav class="ml-auto" is-nav>
<b-nav-item>{{ pending ? '—' : balance | amount }} GDD</b-nav-item> <b-nav-item>{{ pending ? $t('em-dash') : balance | amount }} {{ $t('GDD') }}</b-nav-item>
<b-nav-item to="/profile" right class="d-none d-sm-none d-md-none d-lg-flex shadow-lg"> <b-nav-item to="/profile" right class="d-none d-sm-none d-md-none d-lg-flex shadow-lg">
<small> <small>
{{ $store.state.firstName }} {{ $store.state.lastName }}, {{ $store.state.firstName }} {{ $store.state.lastName }}
<b>{{ $store.state.email }}</b> <b>{{ $store.state.email }}</b>
<b-icon class="ml-3" icon="gear-fill" aria-hidden="true"></b-icon> <b-icon class="ml-3" icon="gear-fill" aria-hidden="true"></b-icon>
</small> </small>
@ -32,40 +32,42 @@
<b-link to="/profile"> <b-link to="/profile">
<small> <small>
{{ $store.state.firstName }} {{ $store.state.firstName }}
{{ $store.state.lastName }}, {{ $store.state.lastName }}
<b>{{ $store.state.email }}</b> <b>{{ $store.state.email }}</b>
</small> </small>
</b-link> </b-link>
</div> </div>
<b-nav-item to="/overview" class="mb-3"> <b-nav-item to="/overview" class="mb-3">
<b-icon icon="house" aria-hidden="true"></b-icon> <b-icon icon="house" aria-hidden="true"></b-icon>
{{ $t('overview') }} {{ $t('navigation.overview') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/send" class="mb-3"> <b-nav-item to="/send" class="mb-3">
<b-icon icon="arrow-left-right" aria-hidden="true"></b-icon> <b-icon icon="arrow-left-right" aria-hidden="true"></b-icon>
{{ $t('send') }} {{ $t('navigation.send') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/transactions" class="mb-3"> <b-nav-item to="/transactions" class="mb-3">
<b-icon icon="layout-text-sidebar-reverse" aria-hidden="true"></b-icon> <b-icon icon="layout-text-sidebar-reverse" aria-hidden="true"></b-icon>
{{ $t('transactions') }} {{ $t('navigation.transactions') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/profile" class="mb-3"> <b-nav-item to="/profile" class="mb-3">
<b-icon icon="gear" aria-hidden="true"></b-icon> <b-icon icon="gear" aria-hidden="true"></b-icon>
{{ $t('site.navbar.my-profil') }} {{ $t('navigation.profile') }}
</b-nav-item> </b-nav-item>
<br /> <br />
<b-nav-item :href="elopageUri" class="mb-3" target="_blank"> <b-nav-item :href="elopageUri" class="mb-3" target="_blank">
<b-icon icon="link45deg" aria-hidden="true"></b-icon> <b-icon icon="link45deg" aria-hidden="true"></b-icon>
{{ $t('members_area') }} {{ $t('navigation.members_area') }}
<b-badge v-if="!$store.state.hasElopage" pill variant="danger">!</b-badge> <b-badge v-if="!$store.state.hasElopage" pill variant="danger">
{{ $t('math.exclaim') }}
</b-badge>
</b-nav-item> </b-nav-item>
<b-nav-item class="mb-3" v-if="$store.state.isAdmin" @click="$emit('admin')"> <b-nav-item class="mb-3" v-if="$store.state.isAdmin" @click="$emit('admin')">
<b-icon icon="shield-check" aria-hidden="true"></b-icon> <b-icon icon="shield-check" aria-hidden="true"></b-icon>
{{ $t('admin_area') }} {{ $t('navigation.admin_area') }}
</b-nav-item> </b-nav-item>
<b-nav-item class="mb-3" @click="$emit('logout')"> <b-nav-item class="mb-3" @click="$emit('logout')">
<b-icon icon="power" aria-hidden="true"></b-icon> <b-icon icon="power" aria-hidden="true"></b-icon>
{{ $t('logout') }} {{ $t('navigation.logout') }}
</b-nav-item> </b-nav-item>
</b-nav> </b-nav>
</b-collapse> </b-collapse>

View File

@ -36,29 +36,29 @@ describe('Sidebar', () => {
expect(wrapper.findAll('.nav-item')).toHaveLength(7) expect(wrapper.findAll('.nav-item')).toHaveLength(7)
}) })
it('has first nav-item "overview" in navbar', () => { it('has first nav-item "navigation.overview" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(0).text()).toEqual('overview') expect(wrapper.findAll('.nav-item').at(0).text()).toEqual('navigation.overview')
}) })
it('has first nav-item "send" in navbar', () => { it('has first nav-item "navigation.send" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(1).text()).toEqual('send') expect(wrapper.findAll('.nav-item').at(1).text()).toEqual('navigation.send')
}) })
it('has first nav-item "transactions" in navbar', () => { it('has first nav-item "navigation.transactions" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(2).text()).toEqual('transactions') expect(wrapper.findAll('.nav-item').at(2).text()).toEqual('navigation.transactions')
}) })
it('has first nav-item "my-profil" in navbar', () => { it('has first nav-item "navigation.profile" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('site.navbar.my-profil') expect(wrapper.findAll('.nav-item').at(3).text()).toEqual('navigation.profile')
}) })
it('has a link to the members area', () => { it('has a link to the members area', () => {
expect(wrapper.findAll('.nav-item').at(4).text()).toContain('members_area') expect(wrapper.findAll('.nav-item').at(4).text()).toContain('navigation.members_area')
expect(wrapper.findAll('.nav-item').at(4).find('a').attributes('href')).toBe('#') expect(wrapper.findAll('.nav-item').at(4).find('a').attributes('href')).toBe('#')
}) })
it('has first nav-item "admin_area" in navbar', () => { it('has first nav-item "navigation.admin_area" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('admin_area') expect(wrapper.findAll('.nav-item').at(5).text()).toEqual('navigation.admin_area')
}) })
it('has first nav-item "logout" in navbar', () => { it('has first nav-item "navigation.logout" in navbar', () => {
expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('logout') expect(wrapper.findAll('.nav-item').at(6).text()).toEqual('navigation.logout')
}) })
}) })
}) })

View File

@ -6,35 +6,37 @@
<b-nav vertical class="w-200"> <b-nav vertical class="w-200">
<b-nav-item to="/overview" class="mb-3"> <b-nav-item to="/overview" class="mb-3">
<b-icon icon="house" aria-hidden="true"></b-icon> <b-icon icon="house" aria-hidden="true"></b-icon>
{{ $t('overview') }} {{ $t('navigation.overview') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/send" class="mb-3"> <b-nav-item to="/send" class="mb-3">
<b-icon icon="arrow-left-right" aria-hidden="true"></b-icon> <b-icon icon="arrow-left-right" aria-hidden="true"></b-icon>
{{ $t('send') }} {{ $t('navigation.send') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/transactions" class="mb-3"> <b-nav-item to="/transactions" class="mb-3">
<b-icon icon="layout-text-sidebar-reverse" aria-hidden="true"></b-icon> <b-icon icon="layout-text-sidebar-reverse" aria-hidden="true"></b-icon>
{{ $t('transactions') }} {{ $t('navigation.transactions') }}
</b-nav-item> </b-nav-item>
<b-nav-item to="/profile" class="mb-3"> <b-nav-item to="/profile" class="mb-3">
<b-icon icon="gear" aria-hidden="true"></b-icon> <b-icon icon="gear" aria-hidden="true"></b-icon>
{{ $t('site.navbar.my-profil') }} {{ $t('navigation.profile') }}
</b-nav-item> </b-nav-item>
</b-nav> </b-nav>
<hr /> <hr />
<b-nav vertical class="w-100"> <b-nav vertical class="w-100">
<b-nav-item class="mb-3" :href="elopageUri" target="_blank"> <b-nav-item class="mb-3" :href="elopageUri" target="_blank">
<b-icon icon="link45deg" aria-hidden="true"></b-icon> <b-icon icon="link45deg" aria-hidden="true"></b-icon>
{{ $t('members_area') }} {{ $t('navigation.members_area') }}
<b-badge v-if="!$store.state.hasElopage" pill variant="danger">!</b-badge> <b-badge v-if="!$store.state.hasElopage" pill variant="danger">
{{ $t('math.exclaim') }}
</b-badge>
</b-nav-item> </b-nav-item>
<b-nav-item class="mb-3" v-if="$store.state.isAdmin" @click="$emit('admin')"> <b-nav-item class="mb-3" v-if="$store.state.isAdmin" @click="$emit('admin')">
<b-icon icon="shield-check" aria-hidden="true"></b-icon> <b-icon icon="shield-check" aria-hidden="true"></b-icon>
{{ $t('admin_area') }} {{ $t('navigation.admin_area') }}
</b-nav-item> </b-nav-item>
<b-nav-item class="mb-3" @click="$emit('logout')"> <b-nav-item class="mb-3" @click="$emit('logout')">
<b-icon icon="power" aria-hidden="true"></b-icon> <b-icon icon="power" aria-hidden="true"></b-icon>
{{ $t('logout') }} {{ $t('navigation.logout') }}
</b-nav-item> </b-nav-item>
</b-nav> </b-nav>
</div> </div>

View File

@ -12,8 +12,12 @@ const propsData = {
describe('PaginationButtons', () => { describe('PaginationButtons', () => {
let wrapper let wrapper
const mocks = {
$t: jest.fn((t) => t),
}
const Wrapper = () => { const Wrapper = () => {
return mount(PaginationButtons, { localVue, propsData }) return mount(PaginationButtons, { localVue, mocks, propsData })
} }
describe('mount', () => { describe('mount', () => {

View File

@ -7,7 +7,7 @@
</b-button> </b-button>
</b-col> </b-col>
<b-col cols="3"> <b-col cols="3">
<p class="text-center pt-2">{{ value }} / {{ totalPages }}</p> <p class="text-center pt-2">{{ value }} {{ $t('math.div') }} {{ totalPages }}</p>
</b-col> </b-col>
<b-col> <b-col>
<b-button class="next-page" :disabled="!hasNext" @click="currentValue++"> <b-button class="next-page" :disabled="!hasNext" @click="currentValue++">

View File

@ -7,6 +7,7 @@ describe('Status', () => {
let wrapper let wrapper
const mocks = { const mocks = {
$t: jest.fn((t) => t),
$n: jest.fn((n) => n), $n: jest.fn((n) => n),
} }
@ -26,7 +27,7 @@ describe('Status', () => {
describe('balance is pending', () => { describe('balance is pending', () => {
it('it displays an en-dash', () => { it('it displays an en-dash', () => {
expect(wrapper.find('div.gdd-status-div').text()).toEqual(' GDD') expect(wrapper.find('div.gdd-status-div').text()).toEqual('em-dash GDD')
}) })
}) })

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="gdd-status"> <div class="gdd-status">
<div class="p-0 gdd-status-div"> <div class="p-0 gdd-status-div">
{{ pending || balance === null ? '—' : $n(balance, 'decimal') }} {{ statusText }} {{ pending || balance === null ? $t('em-dash') : $n(balance, 'decimal') }} {{ statusText }}
</div> </div>
</div> </div>
</template> </template>

View File

@ -51,7 +51,7 @@
{{ $t('form.date') }} {{ $t('form.date') }}
</b-col> </b-col>
<b-col cols="6"> <b-col cols="6">
{{ $d(new Date(date), 'long') }} {{ $i18n.locale === 'de' ? 'Uhr' : '' }} {{ $d(new Date(date), 'long') }}
</b-col> </b-col>
</b-row> </b-row>

View File

@ -15,18 +15,18 @@
<div class="text-center font-weight-bold"> <div class="text-center font-weight-bold">
{{ $n(balance, 'decimal') }} {{ $n(balance, 'decimal') }}
</div> </div>
<div class="text-center">GDD</div> <div class="text-center">{{ $t('GDD') }}</div>
</b-col> </b-col>
<b-col> <b-col>
<div class="text-center font-weight-bold"> <div class="text-center font-weight-bold">
{{ transactionCount }} {{ transactionCount }}
</div> </div>
<div class="text-center"> <div class="text-center">
{{ $t('transactions') }} {{ $t('navigation.transactions') }}
</div> </div>
</b-col> </b-col>
<b-col> <b-col>
<div class="text-center font-weight-bold">--</div> <div class="text-center font-weight-bold">{{ $t('em-dash') }}</div>
<div class="text-center"> <div class="text-center">
{{ $t('community.community') }} {{ $t('community.community') }}
</div> </div>

View File

@ -42,8 +42,8 @@ describe('UserCard_FormUserMail', () => {
expect(wrapper.find('a[href="#formusermail"]').exists()).toBeTruthy() expect(wrapper.find('a[href="#formusermail"]').exists()).toBeTruthy()
}) })
it('renders the E-Mail form.change', () => { it('renders the form.email form.change', () => {
expect(wrapper.findAll('div.col').at(0).text()).toBe('E-Mail form.change') expect(wrapper.findAll('div.col').at(0).text()).toBe('form.email form.change')
}) })
it('renders the E-Mail', () => { it('renders the E-Mail', () => {

View File

@ -4,7 +4,7 @@
<b-row class="mb-4 text-right"> <b-row class="mb-4 text-right">
<b-col class="text-right"> <b-col class="text-right">
<a href="#formusermail" v-if="edit_email" @click="edit_email = !edit_email"> <a href="#formusermail" v-if="edit_email" @click="edit_email = !edit_email">
<span>E-Mail {{ $t('form.change') }}</span> <span>{{ $t('form.email') }} {{ $t('form.change') }}</span>
</a> </a>
<div v-else> <div v-else>
<a href="#formusermail" @click="onSubmit"> <a href="#formusermail" @click="onSubmit">
@ -21,7 +21,7 @@
<b-row class="mb-3"> <b-row class="mb-3">
<b-col class="col-lg-3 col-md-10 col-sm-10 text-md-left text-lg-right"> <b-col class="col-lg-3 col-md-10 col-sm-10 text-md-left text-lg-right">
<small>E-Mail</small> <small>{{ $t('form.email') }}</small>
</b-col> </b-col>
<b-col v-if="edit_email" class="col-md-9 col-sm-10">{{ $store.state.email }}</b-col> <b-col v-if="edit_email" class="col-md-9 col-sm-10">{{ $store.state.email }}</b-col>
<b-col v-else class="col-md-9 col-sm-10"> <b-col v-else class="col-md-9 col-sm-10">

View File

@ -22,6 +22,7 @@
<b>{{ $t('language') }}</b> <b>{{ $t('language') }}</b>
</small> </small>
</b-col> </b-col>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<b-col class="col-12">{{ $t(buildTagFromLanguageString()) }}</b-col> <b-col class="col-12">{{ $t(buildTagFromLanguageString()) }}</b-col>
</b-row> </b-row>
</div> </div>

View File

@ -8,7 +8,7 @@
</div> </div>
</template> </template>
<script> <script>
import ContentFooter from './ContentFooter.vue' import ContentFooter from '@/components/ContentFooter.vue'
import LanguageSwitch from '@/components/LanguageSwitch.vue' import LanguageSwitch from '@/components/LanguageSwitch.vue'
export default { export default {
components: { components: {

View File

@ -41,7 +41,7 @@
import Navbar from '@/components/Menu/Navbar.vue' import Navbar from '@/components/Menu/Navbar.vue'
import Sidebar from '@/components/Menu/Sidebar.vue' import Sidebar from '@/components/Menu/Sidebar.vue'
import { logout, transactionsQuery } from '@/graphql/queries' import { logout, transactionsQuery } from '@/graphql/queries'
import ContentFooter from './ContentFooter.vue' import ContentFooter from '@/components/ContentFooter.vue'
import { FadeTransition } from 'vue2-transitions' import { FadeTransition } from 'vue2-transitions'
import CONFIG from '@/config' import CONFIG from '@/config'

View File

@ -1,22 +1,11 @@
{ {
"admin_area": "Adminbereich",
"advanced-calculation": "Vorausberechnung", "advanced-calculation": "Vorausberechnung",
"back": "Zurück", "back": "Zurück",
"community": { "community": {
"choose-another-community": "Eine andere Gemeinschaft auswählen", "choose-another-community": "Eine andere Gemeinschaft auswählen",
"communities": {
"form": {
"date_period": "Datum / Zeitraum",
"hours": "Stunden",
"hours_report": "Stundenbericht",
"more_hours": "weitere Stunden",
"submit": "Einreichen"
}
},
"community": "Gemeinschaft", "community": "Gemeinschaft",
"continue-to-registration": "Weiter zur Registrierung", "continue-to-registration": "Weiter zur Registrierung",
"current-community": "Aktuelle Gemeinschaft", "current-community": "Aktuelle Gemeinschaft",
"location": "Ort:",
"other-communities": "Weitere Gemeinschaften", "other-communities": "Weitere Gemeinschaften",
"switch-to-this-community": "zu dieser Gemeinschaft wechseln" "switch-to-this-community": "zu dieser Gemeinschaft wechseln"
}, },
@ -24,38 +13,40 @@
"before_startblock_transaction": "Diese Transaktion beinhaltet keine Vergänglichkeit.", "before_startblock_transaction": "Diese Transaktion beinhaltet keine Vergänglichkeit.",
"calculation_decay": "Berechnung der Vergänglichkeit", "calculation_decay": "Berechnung der Vergänglichkeit",
"calculation_total": "Berechnung der Gesamtsumme", "calculation_total": "Berechnung der Gesamtsumme",
"created": "Geschöpft",
"days": "Tage",
"decay": "Vergänglichkeit", "decay": "Vergänglichkeit",
"decayStart": " - Startblock für Vergänglichkeit am: ", "decay_introduced": "Die Vergänglichkeit wurde eingeführt am:",
"decay_introduced": "Die Vergänglichkeit wurde eingeführt am ",
"decay_since_last_transaction": "Vergänglichkeit seit der letzten Transaktion", "decay_since_last_transaction": "Vergänglichkeit seit der letzten Transaktion",
"first_transaction": "Die erste Transaktion beinhaltet keine Vergänglichkeit.",
"hours": "Stunden",
"last_transaction": "Letzte Transaktion", "last_transaction": "Letzte Transaktion",
"minutes": "Minuten",
"months": "Monate",
"noDecay": "Keine Vergänglichkeit",
"past_time": "Vergangene Zeit", "past_time": "Vergangene Zeit",
"receive": "Empfangen",
"seconds": "Sekunden",
"send": "Gesendet",
"since_introduction": "seit Einführung der Vergänglichkeit",
"Starting_block_decay": "Startblock Vergänglichkeit", "Starting_block_decay": "Startblock Vergänglichkeit",
"toCommunity": "An die Gemeinschaft",
"total": "Gesamt", "total": "Gesamt",
"year": "Jahre" "types": {
"created": "Geschöpft",
"noDecay": "Keine Vergänglichkeit",
"receive": "Empfangen",
"send": "Gesendet"
}
}, },
"delete": "löschen", "delete": "löschen",
"em-dash": "—",
"error": { "error": {
"change-password": "Fehler beim Ändern des Passworts",
"empty-transactionlist": "Es gab einen Fehler mit der Übermittlung der Anzahl deiner Transaktionen.", "empty-transactionlist": "Es gab einen Fehler mit der Übermittlung der Anzahl deiner Transaktionen.",
"error": "Fehler", "error": "Fehler!",
"no-account": "Leider konnten wir keinen Account mit diesen Daten finden.", "no-account": "Leider konnten wir keinen Account mit diesen Daten finden.",
"no-email-verify": "Dein Konto wurde noch nicht bestätigt. Bitte überprüfe deine E-Mails und klicke auf den Aktivierungslink!",
"no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt", "no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt",
"session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet." "session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet."
}, },
"footer": {
"app_version": "App version {version}",
"copyright": {
"link": "Gradido-Akademie",
"year": "© {year}"
},
"imprint": "Impressum",
"privacy_policy": "Datenschutzerklärung",
"short_hash": "({shortHash})",
"whitepaper": "Whitepaper"
},
"form": { "form": {
"amount": "Betrag", "amount": "Betrag",
"at": "am", "at": "am",
@ -101,6 +92,7 @@
}, },
"your_amount": "Dein Betrag" "your_amount": "Dein Betrag"
}, },
"GDD": "GDD",
"gdd_per_link": { "gdd_per_link": {
"copy": "kopieren", "copy": "kopieren",
"created": "Der Link wurde erstellt!", "created": "Der Link wurde erstellt!",
@ -113,14 +105,9 @@
"links_count": "Aktive Links", "links_count": "Aktive Links",
"links_sum": "Summe deiner versendeten Gradidos", "links_sum": "Summe deiner versendeten Gradidos",
"not-copied": "Konnte den Link nicht kopieren: {err}", "not-copied": "Konnte den Link nicht kopieren: {err}",
"sentence_1": "Wähle einen Betrag aus, welchen du per Link versenden möchtest. Du kannst auch noch eine Nachricht eintragen. Beim Klick „jetzt generieren“ wird ein Link erstellt, den du versenden kannst.", "sentence_1": "Wähle einen Betrag aus, welchen du per Link versenden möchtest. Du kannst auch noch eine Nachricht eintragen. Beim Klick „jetzt generieren“ wird ein Link erstellt, den du versenden kannst."
"sentence_2": "Der Link ist 14 Tage gültig!",
"sentence_3": "Wird der Link nicht innerhalb der 14 Tage Frist abgerufen, wird er automatisch gelöscht. Der Betrag wird dann wieder deinem Konto gutgeschrieben.",
"sentence_4": "Wer den Link aktiviert, erhält die Zahlung von deinem Konto. Wer noch nicht Mitglied bei Gradido ist, wird durch den Registrierungsprozess geleitet und bekommt den GDD Betrag nach Registrierung / Bestätigung seines Gradido Kontos gut geschrieben.",
"sentence_5": "Der Vergänglichkeitsbetrag wird von dir getragen und für die maximale Gültigkeit deinem Betrag aufgerechnet. Dir wird aber nur der Betrag als Vergänglichkeit berechnet, je nachdem wie viel Tage bis zum Einlösen des Links vergangen sind. Bis zum Einlösen wird die Vergänglichkeit für den gesamten Zeitraum der Gültigkeit vorgehalten."
}, },
"gdt": { "gdt": {
"action": "Aktion",
"calculation": "Berechnung der GradidoTransform", "calculation": "Berechnung der GradidoTransform",
"contribution": "Beitrag", "contribution": "Beitrag",
"conversion": "Umrechnung", "conversion": "Umrechnung",
@ -136,23 +123,33 @@
"raise": "Erhöhung", "raise": "Erhöhung",
"recruited-member": "Eingeladenes Mitglied" "recruited-member": "Eingeladenes Mitglied"
}, },
"imprint": "Impressum",
"language": "Sprache", "language": "Sprache",
"link-load": "den letzten Link nachladen | die letzten {n} Links nachladen | weitere {n} Links nachladen", "link-load": "den letzten Link nachladen | die letzten {n} Links nachladen | weitere {n} Links nachladen",
"links-list": { "links-list": {
"header": "Liste deiner aktiven Links" "header": "Liste deiner aktiven Links"
}, },
"login": "Anmeldung", "login": "Anmeldung",
"logout": "Abmelden", "math": {
"members_area": "Mitgliederbereich", "aprox": "~",
"message": "hallo gradido!!", "div": "/",
"overview": "Übersicht", "equal": "=",
"privacy_policy": "Datenschutzerklärung", "exclaim": "!",
"pipe": "|"
},
"navigation": {
"admin_area": "Adminbereich",
"logout": "Abmelden",
"members_area": "Mitgliederbereich",
"overview": "Übersicht",
"profile": "Mein Profil",
"send": "Senden",
"support": "Support",
"transactions": "Transaktionen"
},
"publisher": { "publisher": {
"infoText": "Wenn dir dein Empfehlungsgeber seine Publisher-Id gegeben hat, trage sie hier ein, sonst lass das Feld bitte unverändert!", "infoText": "Wenn dir dein Empfehlungsgeber seine Publisher-Id gegeben hat, trage sie hier ein, sonst lass das Feld bitte unverändert!",
"publisherId": "Publisher-Id" "publisherId": "Publisher-Id:"
}, },
"send": "Senden",
"send_gdd": "GDD versenden", "send_gdd": "GDD versenden",
"send_per_link": "GDD versenden per Link", "send_per_link": "GDD versenden per Link",
"settings": { "settings": {
@ -165,7 +162,6 @@
"changeLanguage": "Sprache ändern", "changeLanguage": "Sprache ändern",
"de": "Deutsch", "de": "Deutsch",
"en": "English", "en": "English",
"select_language": "Bitte wähle eine Sprache.",
"success": "Deine Sprache wurde erfolgreich geändert." "success": "Deine Sprache wurde erfolgreich geändert."
}, },
"name": { "name": {
@ -180,7 +176,6 @@
"password": { "password": {
"change-password": "Passwort ändern", "change-password": "Passwort ändern",
"forgot_pwd": "Passwort vergessen?", "forgot_pwd": "Passwort vergessen?",
"not-authenticated": "Leider konnten wir dich nicht authentifizieren. Bitte wende dich an den Support.",
"resend_subtitle": "Dein Aktivierungslink ist abgelaufen. Du kannst hier ein neuen anfordern.", "resend_subtitle": "Dein Aktivierungslink ist abgelaufen. Du kannst hier ein neuen anfordern.",
"reset": "Passwort zurücksetzen", "reset": "Passwort zurücksetzen",
"reset-password": { "reset-password": {
@ -196,24 +191,12 @@
}, },
"signup": "Registrieren", "signup": "Registrieren",
"site": { "site": {
"404": {
"back": "Zurück zur Übersicht",
"ooops": "Ooops!",
"text": "Seite nicht gefunden. Aber keine Sorge, wir haben noch viele andere Seiten zu erkunden."
},
"checkEmail": {
"errorText": "E-Mail konnte nicht verifiziert werden.",
"title": "E-Mail wird verifiziert"
},
"login": { "login": {
"community": "Tausend Dank, weil du bei uns bist!", "community": "Tausend Dank, weil du bei uns bist!",
"heading": "Gradido",
"new_wallet": "Neues Konto erstellen", "new_wallet": "Neues Konto erstellen",
"signin": "Anmelden" "signin": "Anmelden"
}, },
"navbar": {
"my-profil": "Mein Profil",
"support": "Support"
},
"signup": { "signup": {
"agree": "Ich stimme der <a href='https://gradido.net/de/datenschutz/' target='_blank' >Datenschutzerklärung</a> zu.", "agree": "Ich stimme der <a href='https://gradido.net/de/datenschutz/' target='_blank' >Datenschutzerklärung</a> zu.",
"dont_match": "Die Passwörter stimmen nicht überein.", "dont_match": "Die Passwörter stimmen nicht überein.",
@ -238,10 +221,17 @@
} }
}, },
"success": "Erfolg", "success": "Erfolg",
"time": {
"days": "Tage",
"hours": "Stunden",
"minutes": "Minuten",
"months": "Monate",
"seconds": "Sekunden",
"year": "Jahre"
},
"transaction": { "transaction": {
"gdd-text": "Gradido Transaktionen", "gdd-text": "Gradido Transaktionen",
"gdt-text": "GradidoTransform Transaktionen", "gdt-text": "GradidoTransform Transaktionen",
"more": "mehr",
"nullTransactions": "Du hast noch keine Transaktionen auf deinem Konto.", "nullTransactions": "Du hast noch keine Transaktionen auf deinem Konto.",
"receiverDeleted": "Das Empfängerkonto wurde gelöscht", "receiverDeleted": "Das Empfängerkonto wurde gelöscht",
"receiverNotFound": "Empfänger nicht gefunden", "receiverNotFound": "Empfänger nicht gefunden",
@ -250,7 +240,5 @@
"transaction-link": { "transaction-link": {
"button": "einlösen", "button": "einlösen",
"send_you": "sendet dir" "send_you": "sendet dir"
}, }
"transactions": "Transaktionen",
"whitepaper": "Whitepaper"
} }

View File

@ -1,22 +1,11 @@
{ {
"admin_area": "Admin Area",
"advanced-calculation": "Advanced calculation", "advanced-calculation": "Advanced calculation",
"back": "Back", "back": "Back",
"community": { "community": {
"choose-another-community": "Choose another community", "choose-another-community": "Choose another community",
"communities": {
"form": {
"date_period": "Date / Period",
"hours": "hours",
"hours_report": "Hourly report",
"more_hours": "more hours",
"submit": "Submit"
}
},
"community": "Community", "community": "Community",
"continue-to-registration": "Continue to registration", "continue-to-registration": "Continue to registration",
"current-community": "Current community", "current-community": "Current community",
"location": "Location:",
"other-communities": "Other communities", "other-communities": "Other communities",
"switch-to-this-community": "Switch to this community" "switch-to-this-community": "Switch to this community"
}, },
@ -24,38 +13,40 @@
"before_startblock_transaction": "This transaction does not include decay.", "before_startblock_transaction": "This transaction does not include decay.",
"calculation_decay": "Calculation of Decay", "calculation_decay": "Calculation of Decay",
"calculation_total": "Calculation of the total Amount", "calculation_total": "Calculation of the total Amount",
"created": "Created",
"days": "Days",
"decay": "Decay", "decay": "Decay",
"decayStart": " - Starting block for decay at: ", "decay_introduced": "Decay was introduced on:",
"decay_introduced": "Decay was introduced on",
"decay_since_last_transaction": "Decay since the last transaction", "decay_since_last_transaction": "Decay since the last transaction",
"first_transaction": "The first transaction does not include decay.",
"hours": "Hours",
"last_transaction": "Last transaction:", "last_transaction": "Last transaction:",
"minutes": "Minutes",
"months": "Months",
"noDecay": "No Decay",
"past_time": "Time passed", "past_time": "Time passed",
"receive": "Received",
"seconds": "Seconds",
"send": "Sent",
"since_introduction": "Since the introduction of Decay",
"Starting_block_decay": "Starting Block Decay", "Starting_block_decay": "Starting Block Decay",
"toCommunity": "To the community",
"total": "Total", "total": "Total",
"year": "Years" "types": {
"created": "Created",
"noDecay": "No Decay",
"receive": "Received",
"send": "Sent"
}
}, },
"delete": "delete", "delete": "delete",
"em-dash": "—",
"error": { "error": {
"change-password": "Error while changing password",
"empty-transactionlist": "There was an error with the transmission of the number of your transactions.", "empty-transactionlist": "There was an error with the transmission of the number of your transactions.",
"error": "Error", "error": "Error!",
"no-account": "Unfortunately we could not find an account to the given data!", "no-account": "Unfortunately we could not find an account to the given data!",
"no-email-verify": "Your account has not been confirmed yet. Please check your emails and click on the activation link!",
"no-transactionlist": "Unfortunately, there was an error. No transactions have been sent from the server.", "no-transactionlist": "Unfortunately, there was an error. No transactions have been sent from the server.",
"session-expired": "The session was closed for security reasons." "session-expired": "The session was closed for security reasons."
}, },
"footer": {
"app_version": "App version {version}",
"copyright": {
"link": "Gradido-Akademie",
"year": "© {year}"
},
"imprint": "Legal notice",
"privacy_policy": "Privacy policy",
"short_hash": "({shortHash})",
"whitepaper": "Whitepaper"
},
"form": { "form": {
"amount": "Amount", "amount": "Amount",
"at": "at", "at": "at",
@ -101,6 +92,7 @@
}, },
"your_amount": "Your amount" "your_amount": "Your amount"
}, },
"GDD": "GDD",
"gdd_per_link": { "gdd_per_link": {
"copy": "copy", "copy": "copy",
"created": "Link was created!", "created": "Link was created!",
@ -113,14 +105,9 @@
"links_count": "Active links", "links_count": "Active links",
"links_sum": "Total of your sent Gradidos", "links_sum": "Total of your sent Gradidos",
"not-copied": "Could not copy link: {err}", "not-copied": "Could not copy link: {err}",
"sentence_1": "Select an amount that you would like to send via link. You can also enter a message. Click 'Generate now' to create a link that you can share.", "sentence_1": "Select an amount that you would like to send via link. You can also enter a message. Click 'Generate now' to create a link that you can share."
"sentence_2": "The link is valid for 14 days!",
"sentence_3": "If the link is not redeemed within the 14-day validity period, it will be invalidated automatically. The amount will then be available to your account again.",
"sentence_4": "Whoever activates the link will receive the payment from your account. If the recipient is not yet a member of Gradido, he will be guided through the registration process and will get the GDD amount credited after registration / confirmation of the newly created Gradido account.",
"sentence_5": "The decay amount will be blocked for your account for the whole duration of the link. However, you will only be charged the amount of decay for the time which has actually passed until the link is redeemed. The remaining amount will then be available to your account again."
}, },
"gdt": { "gdt": {
"action": "Action",
"calculation": "Calculation of GradidoTransform", "calculation": "Calculation of GradidoTransform",
"contribution": "Contribution", "contribution": "Contribution",
"conversion": "Conversion", "conversion": "Conversion",
@ -136,23 +123,33 @@
"raise": "Increase", "raise": "Increase",
"recruited-member": "Invited member" "recruited-member": "Invited member"
}, },
"imprint": "Legal notice",
"language": "Language", "language": "Language",
"link-load": "Load the last link | Load the last {n} links | Load more {n} links", "link-load": "Load the last link | Load the last {n} links | Load more {n} links",
"links-list": { "links-list": {
"header": "List of your active links" "header": "List of your active links"
}, },
"login": "Login", "login": "Login",
"logout": "Logout", "math": {
"members_area": "Members area", "aprox": "~",
"message": "hello gradido !!", "div": "/",
"overview": "Overview", "equal": "=",
"privacy_policy": "Privacy policy", "exclaim": "!",
"pipe": "|"
},
"navigation": {
"admin_area": "Admin Area",
"logout": "Logout",
"members_area": "Members area",
"overview": "Overview",
"profile": "My profile",
"send": "Send",
"support": "Support",
"transactions": "Transactions"
},
"publisher": { "publisher": {
"infoText": "If your referrer has given you his publisher id, enter it here, otherwise leave the field unchanged!", "infoText": "If your referrer has given you his publisher id, enter it here, otherwise leave the field unchanged!",
"publisherId": "PublisherID" "publisherId": "PublisherID:"
}, },
"send": "Send",
"send_gdd": "GDD send", "send_gdd": "GDD send",
"send_per_link": "GDD send via link", "send_per_link": "GDD send via link",
"settings": { "settings": {
@ -165,7 +162,6 @@
"changeLanguage": "Change language", "changeLanguage": "Change language",
"de": "Deutsch", "de": "Deutsch",
"en": "English", "en": "English",
"select_language": "Please choose your language.",
"success": "Your language has been successfully updated." "success": "Your language has been successfully updated."
}, },
"name": { "name": {
@ -180,7 +176,6 @@
"password": { "password": {
"change-password": "Change password", "change-password": "Change password",
"forgot_pwd": "Forgot password?", "forgot_pwd": "Forgot password?",
"not-authenticated": "Unfortunately we could not authenticate you. Please contact the support.",
"resend_subtitle": "Your activation link has expired, here you can order a new one.", "resend_subtitle": "Your activation link has expired, here you can order a new one.",
"reset": "Reset password", "reset": "Reset password",
"reset-password": { "reset-password": {
@ -196,24 +191,12 @@
}, },
"signup": "Sign up", "signup": "Sign up",
"site": { "site": {
"404": {
"back": "Back to the overview",
"ooops": "Ooops!",
"text": "Page not found. But don't worry, we have many other sites to explore."
},
"checkEmail": {
"errorText": "Could not verify the email.",
"title": "Verifing email"
},
"login": { "login": {
"community": "A thousand thanks for being with us!", "community": "A thousand thanks for being with us!",
"heading": "Gradido",
"new_wallet": "Create new account", "new_wallet": "Create new account",
"signin": "Sign in" "signin": "Sign in"
}, },
"navbar": {
"my-profil": "My profile",
"support": "Support"
},
"signup": { "signup": {
"agree": "I agree to the <a href='https://gradido.net/en/datenschutz/' target='_blank' > privacy policy</a>.", "agree": "I agree to the <a href='https://gradido.net/en/datenschutz/' target='_blank' > privacy policy</a>.",
"dont_match": "Passwords don't match.", "dont_match": "Passwords don't match.",
@ -238,10 +221,17 @@
} }
}, },
"success": "Success", "success": "Success",
"time": {
"days": "Days",
"hours": "Hours",
"minutes": "Minutes",
"months": "Months",
"seconds": "Seconds",
"year": "Years"
},
"transaction": { "transaction": {
"gdd-text": "Gradido Transactions", "gdd-text": "Gradido Transactions",
"gdt-text": "GradidoTransform Transactions", "gdt-text": "GradidoTransform Transactions",
"more": "more",
"nullTransactions": "You don't have any transactions on your account yet.", "nullTransactions": "You don't have any transactions on your account yet.",
"receiverDeleted": "The recipient account was deleted", "receiverDeleted": "The recipient account was deleted",
"receiverNotFound": "Recipient not found", "receiverNotFound": "Recipient not found",
@ -250,7 +240,5 @@
"transaction-link": { "transaction-link": {
"button": "redeem", "button": "redeem",
"send_you": "wants to send you" "send_you": "wants to send you"
}, }
"transactions": "Transactions",
"whitepaper": "Whitepaper"
} }

View File

@ -5,8 +5,9 @@
<div class="header-body text-center mb-7"> <div class="header-body text-center mb-7">
<b-row class="justify-content-center"> <b-row class="justify-content-center">
<b-col xl="5" lg="6" md="8" class="px-2"> <b-col xl="5" lg="6" md="8" class="px-2">
<h1>{{ $t(displaySetup.headline) }}</h1> <h1>{{ $t('settings.password.reset') }}</h1>
<p class="text-lead">{{ $t(displaySetup.subtitle) }}</p> <!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<p class="text-lead">{{ $t(subtitle) }}</p>
</b-col> </b-col>
</b-row> </b-row>
</div> </div>
@ -22,7 +23,7 @@
<input-email v-model="form.email"></input-email> <input-email v-model="form.email"></input-email>
<div class="text-center"> <div class="text-center">
<b-button type="submit" variant="primary"> <b-button type="submit" variant="primary">
{{ $t(displaySetup.button) }} {{ $t('settings.password.send_now') }}
</b-button> </b-button>
</div> </div>
</b-form> </b-form>
@ -41,21 +42,6 @@
import { sendResetPasswordEmail } from '@/graphql/queries' import { sendResetPasswordEmail } from '@/graphql/queries'
import InputEmail from '@/components/Inputs/InputEmail' import InputEmail from '@/components/Inputs/InputEmail'
const textFields = {
resetPassword: {
headline: 'settings.password.reset',
subtitle: 'settings.password.resend_subtitle',
button: 'settings.password.send_now',
cancel: 'back',
},
login: {
headline: 'settings.password.reset',
subtitle: 'settings.password.subtitle',
button: 'settings.password.send_now',
cancel: 'back',
},
}
export default { export default {
name: 'ForgotPassword', name: 'ForgotPassword',
components: { components: {
@ -67,7 +53,7 @@ export default {
form: { form: {
email: '', email: '',
}, },
displaySetup: {}, subtitle: 'settings.password.subtitle',
} }
}, },
methods: { methods: {
@ -89,9 +75,7 @@ export default {
}, },
created() { created() {
if (this.$route.params.comingFrom) { if (this.$route.params.comingFrom) {
this.displaySetup = textFields[this.$route.params.comingFrom] this.subtitle = 'settings.password.resend_subtitle'
} else {
this.displaySetup = textFields.login
} }
}, },
} }

View File

@ -98,7 +98,7 @@ describe('Login', () => {
describe('Login header', () => { describe('Login header', () => {
it('has a welcome message', () => { it('has a welcome message', () => {
expect(wrapper.find('div.header').text()).toBe('Gradido site.login.community') expect(wrapper.find('div.header').text()).toBe('site.login.heading site.login.community')
}) })
}) })

View File

@ -6,7 +6,7 @@
<div class="text-center mb-7 header"> <div class="text-center mb-7 header">
<b-row class="justify-content-center"> <b-row class="justify-content-center">
<b-col xl="5" lg="6" md="8" class="px-2"> <b-col xl="5" lg="6" md="8" class="px-2">
<h1>Gradido</h1> <h1>{{ $t('site.login.heading') }}</h1>
<p class="text-lead">{{ $t('site.login.community') }}</p> <p class="text-lead">{{ $t('site.login.community') }}</p>
</b-col> </b-col>
</b-row> </b-row>

View File

@ -270,7 +270,7 @@ describe('Register', () => {
it('shows error message', () => { it('shows error message', () => {
expect(wrapper.find('span.alert-text').exists()).toBeTruthy() expect(wrapper.find('span.alert-text').exists()).toBeTruthy()
expect(wrapper.find('span.alert-text').text().length !== 0).toBeTruthy() expect(wrapper.find('span.alert-text').text().length !== 0).toBeTruthy()
expect(wrapper.find('span.alert-text').text()).toContain('error.error!') expect(wrapper.find('span.alert-text').text()).toContain('error.error')
expect(wrapper.find('span.alert-text').text()).toContain('Ouch!') expect(wrapper.find('span.alert-text').text()).toContain('Ouch!')
}) })

View File

@ -100,6 +100,7 @@
v-model="form.agree" v-model="form.agree"
:name="$t('site.signup.agree')" :name="$t('site.signup.agree')"
> >
<!-- eslint-disable-next-line @intlify/vue-i18n/no-v-html -->
<span class="text-muted" v-html="$t('site.signup.agree')"></span> <span class="text-muted" v-html="$t('site.signup.agree')"></span>
</b-form-checkbox> </b-form-checkbox>
</b-col> </b-col>
@ -113,14 +114,12 @@
> >
<span class="alert-icon"><i class="ni ni-point"></i></span> <span class="alert-icon"><i class="ni ni-point"></i></span>
<span class="alert-text"> <span class="alert-text">
<strong>{{ $t('error.error') }}!</strong> <strong>{{ $t('error.error') }}</strong>
{{ messageError }} {{ messageError }}
</span> </span>
</b-alert> </b-alert>
<b-row v-b-toggle:my-collapse class="text-muted shadow-sm p-3 publisherCollaps"> <b-row v-b-toggle:my-collapse class="text-muted shadow-sm p-3 publisherCollaps">
<b-col> <b-col>{{ $t('publisher.publisherId') }} {{ $store.state.publisherId }}</b-col>
{{ $t('publisher.publisherId') }} : {{ $store.state.publisherId }}
</b-col>
<b-col class="text-right"> <b-col class="text-right">
<b-icon icon="chevron-down" aria-hidden="true"></b-icon> <b-icon icon="chevron-down" aria-hidden="true"></b-icon>
</b-col> </b-col>

View File

@ -5,9 +5,11 @@
<div class="header-body text-center mb-7"> <div class="header-body text-center mb-7">
<b-row class="justify-content-center"> <b-row class="justify-content-center">
<b-col xl="5" lg="6" md="8" class="px-2"> <b-col xl="5" lg="6" md="8" class="px-2">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<h1>{{ $t(displaySetup.authenticated) }}</h1> <h1>{{ $t(displaySetup.authenticated) }}</h1>
<div class="pb-4"> <div class="pb-4">
<span> <span>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
{{ $t(displaySetup.notAuthenticated) }} {{ $t(displaySetup.notAuthenticated) }}
</span> </span>
</div> </div>
@ -26,6 +28,7 @@
<input-password-confirmation v-model="form" /> <input-password-confirmation v-model="form" />
<div class="text-center"> <div class="text-center">
<b-button type="submit" variant="primary" class="mt-4"> <b-button type="submit" variant="primary" class="mt-4">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
{{ $t(displaySetup.button) }} {{ $t(displaySetup.button) }}
</b-button> </b-button>
</div> </div>

View File

@ -4,10 +4,13 @@
<div class="header py-7 py-lg-8 pt-lg-9"> <div class="header py-7 py-lg-8 pt-lg-9">
<b-container> <b-container>
<div class="header-body text-center mb-7"> <div class="header-body text-center mb-7">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<p class="h1">{{ $t(displaySetup.headline) }}</p> <p class="h1">{{ $t(displaySetup.headline) }}</p>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<p class="h4">{{ $t(displaySetup.subtitle) }}</p> <p class="h4">{{ $t(displaySetup.subtitle) }}</p>
<hr /> <hr />
<b-button v-if="displaySetup.linkTo" :to="displaySetup.linkTo"> <b-button v-if="displaySetup.linkTo" :to="displaySetup.linkTo">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
{{ $t(displaySetup.button) }} {{ $t(displaySetup.button) }}
</b-button> </b-button>
</div> </div>

View File

@ -5,7 +5,9 @@ import { required, email, min, max, is_not } from 'vee-validate/dist/rules'
export const loadAllRules = (i18nCallback) => { export const loadAllRules = (i18nCallback) => {
configure({ configure({
defaultMessage: (field, values) => { defaultMessage: (field, values) => {
// eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
values._field_ = i18nCallback.t(`fields.${field}`) values._field_ = i18nCallback.t(`fields.${field}`)
// eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
return i18nCallback.t(`validations.messages.${values._rule_}`, values) return i18nCallback.t(`validations.messages.${values._rule_}`, values)
}, },
classes: { classes: {
@ -17,21 +19,25 @@ export const loadAllRules = (i18nCallback) => {
extend('email', { extend('email', {
...email, ...email,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.email', values), message: (_, values) => i18nCallback.t('validations.messages.email', values),
}) })
extend('required', { extend('required', {
...required, ...required,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.required', values), message: (_, values) => i18nCallback.t('validations.messages.required', values),
}) })
extend('min', { extend('min', {
...min, ...min,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.min', values), message: (_, values) => i18nCallback.t('validations.messages.min', values),
}) })
extend('max', { extend('max', {
...max, ...max,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.max', values), message: (_, values) => i18nCallback.t('validations.messages.max', values),
}) })

View File

@ -15,6 +15,7 @@ module.exports = {
fallbackLocale: 'de', fallbackLocale: 'de',
localeDir: 'locales', localeDir: 'locales',
enableInSFC: false, enableInSFC: false,
enableLegacy: false,
}, },
}, },
lintOnSave: true, lintOnSave: true,

View File

@ -1726,6 +1726,13 @@
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/runtime@^7.14.0":
version "7.17.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.7.tgz#a5f3328dc41ff39d803f311cfe17703418cf9825"
integrity sha512-L6rvG9GDxaLgFjg41K+5Yv9OMrU98sWe+Ykmc6FDJW/+vYZMhdOMKkISgzptMaERHvS2Y2lw9MDRm2gHhlQQoA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@7", "@babel/template@^7.12.13", "@babel/template@^7.16.0", "@babel/template@^7.3.3": "@babel/template@7", "@babel/template@^7.12.13", "@babel/template@^7.16.0", "@babel/template@^7.3.3":
version "7.16.0" version "7.16.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6"
@ -1875,6 +1882,21 @@
minimatch "^3.0.4" minimatch "^3.0.4"
strip-json-comments "^3.1.1" strip-json-comments "^3.1.1"
"@eslint/eslintrc@^1.2.0":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6"
integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
espree "^9.3.1"
globals "^13.9.0"
ignore "^5.2.0"
import-fresh "^3.2.1"
js-yaml "^4.1.0"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@hapi/address@2.x.x": "@hapi/address@2.x.x":
version "2.1.4" version "2.1.4"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
@ -1916,6 +1938,83 @@
cssnano-preset-default "^4.0.0" cssnano-preset-default "^4.0.0"
postcss "^7.0.0" postcss "^7.0.0"
"@intlify/core-base@^9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.1.9.tgz#e4e8c951010728e4af3a0d13d74cf3f9e7add7f6"
integrity sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==
dependencies:
"@intlify/devtools-if" "9.1.9"
"@intlify/message-compiler" "9.1.9"
"@intlify/message-resolver" "9.1.9"
"@intlify/runtime" "9.1.9"
"@intlify/shared" "9.1.9"
"@intlify/vue-devtools" "9.1.9"
"@intlify/devtools-if@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/devtools-if/-/devtools-if-9.1.9.tgz#a30e1dd1256ff2c5c98d8d75d075384fba898e5d"
integrity sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==
dependencies:
"@intlify/shared" "9.1.9"
"@intlify/eslint-plugin-vue-i18n@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@intlify/eslint-plugin-vue-i18n/-/eslint-plugin-vue-i18n-1.4.0.tgz#f8fe791892c2dce7d189a364b6a908c87e1c3ac9"
integrity sha512-anB1eBf6rpxpWyW883gi6O1hozQy4Q02VyzyodOUnohOqT07GATVSxnr2J9/qQSV47xWukV+9LiRErJcU7d/uA==
dependencies:
"@eslint/eslintrc" "^1.2.0"
"@intlify/core-base" "^9.1.9"
"@intlify/message-compiler" "^9.1.9"
debug "^4.3.1"
glob "^7.1.3"
ignore "^5.0.5"
is-language-code "^3.1.0"
js-yaml "^4.0.0"
json5 "^2.1.3"
jsonc-eslint-parser "^2.0.0"
lodash "^4.17.11"
parse5 "^6.0.0"
semver "^7.3.4"
vue-eslint-parser "^8.0.0"
yaml-eslint-parser "^0.5.0"
"@intlify/message-compiler@9.1.9", "@intlify/message-compiler@^9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.1.9.tgz#1193cbd224a71c2fb981455b8534a3c766d2948d"
integrity sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==
dependencies:
"@intlify/message-resolver" "9.1.9"
"@intlify/shared" "9.1.9"
source-map "0.6.1"
"@intlify/message-resolver@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/message-resolver/-/message-resolver-9.1.9.tgz#3155ccd2f5e6d0dc16cad8b7f1d8e97fcda05bfc"
integrity sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==
"@intlify/runtime@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/runtime/-/runtime-9.1.9.tgz#2c12ce29518a075629efed0a8ed293ee740cb285"
integrity sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==
dependencies:
"@intlify/message-compiler" "9.1.9"
"@intlify/message-resolver" "9.1.9"
"@intlify/shared" "9.1.9"
"@intlify/shared@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.1.9.tgz#0baaf96128b85560666bec784ffb01f6623cc17a"
integrity sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==
"@intlify/vue-devtools@9.1.9":
version "9.1.9"
resolved "https://registry.yarnpkg.com/@intlify/vue-devtools/-/vue-devtools-9.1.9.tgz#2be8f4dbe7f7ed4115676eb32348141d411e426b"
integrity sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==
dependencies:
"@intlify/message-resolver" "9.1.9"
"@intlify/runtime" "9.1.9"
"@intlify/shared" "9.1.9"
"@istanbuljs/load-nyc-config@^1.0.0": "@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
@ -3192,6 +3291,11 @@ acorn@^8.2.4:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.6.0.tgz#e3692ba0eb1a0c83eaa4f37f5fa7368dd7142895"
integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw== integrity sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==
acorn@^8.5.0, acorn@^8.7.0:
version "8.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
address@^1.0.3: address@^1.0.3:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6"
@ -3466,6 +3570,11 @@ argparse@^1.0.7:
dependencies: dependencies:
sprintf-js "~1.0.2" sprintf-js "~1.0.2"
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
arr-diff@^4.0.0: arr-diff@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
@ -5504,7 +5613,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
dependencies: dependencies:
ms "2.0.0" ms "2.0.0"
debug@4, debug@^4.1.0, debug@^4.3.3: debug@4, debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
version "4.3.3" version "4.3.3"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
@ -6409,6 +6518,14 @@ eslint-scope@^5.0.0, eslint-scope@^5.1.1:
esrecurse "^4.3.0" esrecurse "^4.3.0"
estraverse "^4.1.1" estraverse "^4.1.1"
eslint-scope@^7.0.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
eslint-utils@^2.0.0, eslint-utils@^2.1.0: eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
@ -6426,6 +6543,11 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
eslint@^4.19.1: eslint@^4.19.1:
version "4.19.1" version "4.19.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300"
@ -6544,6 +6666,15 @@ espree@^7.3.0, espree@^7.3.1:
acorn-jsx "^5.3.1" acorn-jsx "^5.3.1"
eslint-visitor-keys "^1.3.0" eslint-visitor-keys "^1.3.0"
espree@^9.0.0, espree@^9.3.1:
version "9.3.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
dependencies:
acorn "^8.7.0"
acorn-jsx "^5.3.1"
eslint-visitor-keys "^3.3.0"
esprima@^4.0.0, esprima@^4.0.1: esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
@ -7401,6 +7532,13 @@ globals@^13.6.0:
dependencies: dependencies:
type-fest "^0.20.2" type-fest "^0.20.2"
globals@^13.9.0:
version "13.12.1"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb"
integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==
dependencies:
type-fest "^0.20.2"
globals@^9.18.0: globals@^9.18.0:
version "9.18.0" version "9.18.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
@ -7939,16 +8077,16 @@ ignore@^4.0.3, ignore@^4.0.6:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
ignore@^5.0.5, ignore@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
ignore@^5.1.1, ignore@^5.1.4: ignore@^5.1.1, ignore@^5.1.4:
version "5.1.8" version "5.1.8"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57"
integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==
ignore@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
import-cwd@^2.0.0: import-cwd@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9"
@ -8329,6 +8467,13 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-language-code@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-language-code/-/is-language-code-3.1.0.tgz#b2386b49227e7010636f16d0c2c681ca40136ab5"
integrity sha512-zJdQ3QTeLye+iphMeK3wks+vXSRFKh68/Pnlw7aOfApFSEIOhYa8P9vwwa6QrImNNBMJTiL1PpYF0f4BxDuEgA==
dependencies:
"@babel/runtime" "^7.14.0"
is-negative-zero@^2.0.1: is-negative-zero@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
@ -9551,6 +9696,13 @@ js-yaml@^3.13.1, js-yaml@^3.9.1:
argparse "^1.0.7" argparse "^1.0.7"
esprima "^4.0.0" esprima "^4.0.0"
js-yaml@^4.0.0, js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
dependencies:
argparse "^2.0.1"
jsbn@~0.1.0: jsbn@~0.1.0:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@ -9740,7 +9892,7 @@ json3@^3.3.3:
resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81"
integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==
json5@2.x, json5@^2.1.2: json5@2.x, json5@^2.1.2, json5@^2.1.3:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
@ -9759,6 +9911,16 @@ json5@^1.0.1:
dependencies: dependencies:
minimist "^1.2.0" minimist "^1.2.0"
jsonc-eslint-parser@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/jsonc-eslint-parser/-/jsonc-eslint-parser-2.1.0.tgz#4c126b530aa583d85308d0b3041ff81ce402bbb2"
integrity sha512-qCRJWlbP2v6HbmKW7R3lFbeiVWHo+oMJ0j+MizwvauqnCV/EvtAeEeuCgoc/ErtsuoKgYB8U4Ih8AxJbXoE6/g==
dependencies:
acorn "^8.5.0"
eslint-visitor-keys "^3.0.0"
espree "^9.0.0"
semver "^7.3.5"
jsonfile@^4.0.0: jsonfile@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
@ -11104,7 +11266,7 @@ parse5@5.1.0:
resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2"
integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==
parse5@6.0.1, parse5@^6.0.1: parse5@6.0.1, parse5@^6.0.0, parse5@^6.0.1:
version "6.0.1" version "6.0.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
@ -12968,16 +13130,16 @@ source-map-url@^0.4.0:
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==
source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@^0.5.0, source-map@^0.5.6: source-map@^0.5.0, source-map@^0.5.6:
version "0.5.7" version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
source-map@^0.7.3: source-map@^0.7.3:
version "0.7.3" version "0.7.3"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
@ -14340,6 +14502,19 @@ vue-eslint-parser@^7.6.0:
esquery "^1.4.0" esquery "^1.4.0"
lodash "^4.17.15" lodash "^4.17.15"
vue-eslint-parser@^8.0.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz#5d31129a1b3dd89c0069ca0a1c88f970c360bd0d"
integrity sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==
dependencies:
debug "^4.3.2"
eslint-scope "^7.0.0"
eslint-visitor-keys "^3.1.0"
espree "^9.0.0"
esquery "^1.4.0"
lodash "^4.17.21"
semver "^7.3.5"
vue-flatpickr-component@^8.1.2: vue-flatpickr-component@^8.1.2:
version "8.1.6" version "8.1.6"
resolved "https://registry.yarnpkg.com/vue-flatpickr-component/-/vue-flatpickr-component-8.1.6.tgz#8fb25dc72946ceb1ab005b871a8151461c0883f6" resolved "https://registry.yarnpkg.com/vue-flatpickr-component/-/vue-flatpickr-component-8.1.6.tgz#8fb25dc72946ceb1ab005b871a8151461c0883f6"
@ -14979,7 +15154,16 @@ yallist@^4.0.0:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yaml@^1.10.0: yaml-eslint-parser@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/yaml-eslint-parser/-/yaml-eslint-parser-0.5.0.tgz#01d4e4d992a820769ea85ef5fd526dfc20ebc6f5"
integrity sha512-nJeyLA3YHAzhBTZbRAbu3W6xrSCucyxExmA+ZDtEdUFpGllxAZpto2Zxo2IG0r0eiuEiBM4e+wiAdxTziTq94g==
dependencies:
eslint-visitor-keys "^3.0.0"
lodash "^4.17.21"
yaml "^1.10.2"
yaml@^1.10.0, yaml@^1.10.2:
version "1.10.2" version "1.10.2"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==