Merge branch 'master' into import_production_data

This commit is contained in:
Ulf Gebhardt 2022-01-21 02:19:53 +01:00
commit 96b756227f
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
31 changed files with 276 additions and 101 deletions

View File

@ -15,7 +15,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
decayDuration: 0,
memo: 'Testing',
transactionId: 1,
name: 'Bibi',
name: 'Gradido Akademie',
email: 'bibi@bloxberg.de',
date: new Date(),
decay: {
@ -34,7 +34,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
decayDuration: 0,
memo: 'Testing 2',
transactionId: 2,
name: 'Bibi',
name: 'Gradido Akademie',
email: 'bibi@bloxberg.de',
date: new Date(),
decay: {
@ -53,6 +53,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
const toastedErrorMock = jest.fn()
const mocks = {
$d: jest.fn((t) => t),
$t: jest.fn((t) => t),
$apollo: {
query: apolloQueryMock,
@ -64,6 +65,7 @@ const mocks = {
const propsData = {
userId: 1,
fields: ['date', 'balance', 'name', 'memo', 'decay'],
}
describe('CreationTransactionListFormular', () => {

View File

@ -1,7 +1,7 @@
<template>
<div class="component-creation-transaction-list">
{{ $t('transactionlist.title') }}
<b-table striped hover :items="items"></b-table>
<b-table striped hover :fields="fields" :items="items"></b-table>
</div>
</template>
<script>
@ -13,6 +13,35 @@ export default {
},
data() {
return {
fields: [
{
key: 'date',
label: this.$t('transactionlist.date'),
formatter: (value, key, item) => {
return this.$d(new Date(value))
},
},
{
key: 'balance',
label: this.$t('transactionlist.amount'),
formatter: (value, key, item) => {
return `${value} GDD`
},
},
{ key: 'name', label: this.$t('transactionlist.community') },
{ key: 'memo', label: this.$t('transactionlist.memo') },
{
key: 'decay',
label: this.$t('transactionlist.decay'),
formatter: (value, key, item) => {
if (value && value.balance >= 0) {
return value.balance
} else {
return '0'
}
},
},
],
items: [],
}
},

View File

@ -2,7 +2,7 @@
<div class="component-nabvar">
<b-navbar toggleable="md" type="dark" variant="success" class="p-3">
<b-navbar-brand to="/">
<img src="img/brand/green.png" class="navbar-brand-img" alt="..." />
<img src="img/brand/gradido_logo_w.png" class="navbar-brand-img" alt="..." />
</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>

View File

@ -12,6 +12,9 @@
"select_value": "Betrag auswählen",
"submit_creation": "Schöpfung einreichen",
"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_default": "`Fall {event} wird nicht unterstützt`",
"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",
"update_creation": "Schöpfung aktualisieren"
},
@ -52,6 +55,11 @@
"remove": "Entfernen",
"transaction": "Transaktion",
"transactionlist": {
"amount": "Betrag",
"community": "Gemeinschaft",
"date": "Datum",
"decay": "Vergänglichkeit",
"memo": "Nachricht",
"title": "Alle geschöpften Transaktionen für den Nutzer"
},
"unregistered_emails": "Nur unregistrierte Nutzer",

View File

@ -12,6 +12,9 @@
"select_value": "Select amount",
"submit_creation": "Submit creation",
"toasted": "Open creation ({value} GDD) for {email} has been saved and is ready for confirmation.",
"toasted_created": "Creation has been successfully saved",
"toasted_default": "`Case {event} is not supported`",
"toasted_delete": "Open creation has been deleted",
"toasted_update": "Open creation {value} GDD) for {email} has been changed and is ready for confirmation.",
"update_creation": "Creation update"
},
@ -52,6 +55,11 @@
"remove": "Remove",
"transaction": "Transaction",
"transactionlist": {
"amount": "Amount",
"community": "Community",
"date": "Date",
"decay": "Decay",
"memo": "Message",
"title": "All creation-transactions for the user"
},
"unregistered_emails": "Only unregistered users",

View File

@ -44,6 +44,9 @@ Vue.use(Toasted, {
addNavigationGuards(router, store, apolloProvider.defaultClient, i18n)
i18n.locale =
store.state.moderator && store.state.moderator.language ? store.state.moderator.language : 'en'
new Vue({
moment,
router,

View File

@ -15,7 +15,15 @@ jest.mock('vue-apollo')
jest.mock('vuex')
jest.mock('vue-i18n')
jest.mock('vue-moment')
jest.mock('./store/store')
jest.mock('./store/store', () => {
return {
state: {
moderator: {
language: 'es',
},
},
}
})
jest.mock('./i18n')
jest.mock('./router/router')
@ -101,4 +109,8 @@ describe('main', () => {
}),
)
})
it('sets the locale from store', () => {
expect(i18n.locale).toBe('es')
})
})

View File

@ -127,7 +127,7 @@ describe('CreationConfirm', () => {
})
it('toasts a success message', () => {
expect(toastedSuccessMock).toBeCalledWith('Pending Creation has been deleted')
expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_delete')
})
})
@ -189,7 +189,7 @@ describe('CreationConfirm', () => {
})
it('toasts a success message', () => {
expect(toastedSuccessMock).toBeCalledWith('Pending Creation has been deleted')
expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_created')
})
})
@ -201,7 +201,7 @@ describe('CreationConfirm', () => {
})
it('toasts an error message', () => {
expect(toastedErrorMock).toBeCalledWith('Case confirm is not supported')
expect(toastedErrorMock).toBeCalledWith('creation_form.toasted_default')
})
})

View File

@ -66,7 +66,7 @@ export default {
index = this.confirmResult.indexOf(findArr)
this.confirmResult.splice(index, 1)
this.$store.commit('openCreationsMinus', 1)
this.$toasted.success('Pending Creation has been deleted')
this.$toasted.success(this.$t('creation_form.toasted_delete'))
})
.catch((error) => {
this.$toasted.error(error.message)
@ -75,10 +75,10 @@ export default {
case 'confirmed':
this.confirmResult.splice(index, 1)
this.$store.commit('openCreationsMinus', 1)
this.$toasted.success('Pending Creation has been deleted')
this.$toasted.success(this.$t('creation_form.toasted_created'))
break
default:
this.$toasted.error('Case ' + event + ' is not supported')
this.$toasted.error(this.$t('creation_form.toasted_default', { event }))
}
},
getPendingCreations() {

View File

@ -27,9 +27,9 @@ EMAIL_LINK_SETPASSWORD=$EMAIL_LINK_SETPASSWORD
#KLICKTIPP_APIKEY_DE=
#KLICKTIPP_APIKEY_EN=
#KLICKTIPP=true
COMMUNITY_NAME=
COMMUNITY_URL=
COMMUNITY_REGISTER_URL=
COMMUNITY_DESCRIPTION=
COMMUNITY_NAME=$COMMUNITY_NAME
COMMUNITY_URL=$COMMUNITY_URL
COMMUNITY_REGISTER_URL=$COMMUNITY_REGISTER_URL
COMMUNITY_DESCRIPTION=$COMMUNITY_DESCRIPTION
WEBHOOK_ELOPAGE_SECRET=$WEBHOOK_ELOPAGE_SECRET

View File

@ -8,16 +8,28 @@ import { RIGHTS } from '../../auth/RIGHTS'
import { ServerUserRepository } from '../../typeorm/repository/ServerUser'
import { getCustomRepository } from 'typeorm'
import { UserRepository } from '../../typeorm/repository/User'
import { INALIENABLE_RIGHTS } from '../../auth/INALIENABLE_RIGHTS'
const isAuthorized: AuthChecker<any> = async ({ context }, rights) => {
context.role = ROLE_UNAUTHORIZED // unauthorized user
// Do we have a token?
if (context.token) {
// Decode the token
const decoded = decode(context.token)
if (!decoded) {
// we always throw on an invalid token
throw new Error('403.13 - Client certificate revoked')
// Are all rights requested public?
const isInalienable = (<RIGHTS[]>rights).reduce(
(acc, right) => acc && INALIENABLE_RIGHTS.includes(right),
true,
)
if (isInalienable) {
// If public dont throw and permit access
return true
} else {
// Throw on a protected route
throw new Error('403.13 - Client certificate revoked')
}
}
// Set context pubKey
context.pubKey = Buffer.from(decoded.pubKey).toString('hex')

View File

@ -30,6 +30,11 @@ TYPEORM_LOGGING_RELATIVE_PATH=../deployment/bare_metal/log/typeorm.backend.log
WEBHOOK_ELOPAGE_SECRET=secret
COMMUNITY_NAME=Gradido Development Stage1
COMMUNITY_URL=https://stage1.gradido.net/
COMMUNITY_REGISTER_URL=https://stage1.gradido.net/register
COMMUNITY_DESCRIPTION=Gradido Development Stage1 Test Community
# frontend
GRAPHQL_URI=https://stage1.gradido.net/graphql
ADMIN_AUTH_URL=https://stage1.gradido.net/admin/authenticate?token={token}

View File

@ -24,8 +24,12 @@
<b-row class="mb-2">
<b-col>
<input-password
:rules="{ samePassword: value.password }"
:rules="{
required: true,
samePassword: value.password,
}"
:label="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
:immediate="true"
:name="createId(register ? $t('form.passwordRepeat') : $t('form.password_new_repeat'))"
:placeholder="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
v-model="passwordRepeat"

View File

@ -12,7 +12,6 @@
</div>
</template>
<script>
import { localeChanged } from 'vee-validate'
import locales from '../locales/'
import { updateUserInfos } from '../graphql/mutations'
@ -26,10 +25,8 @@ export default {
},
methods: {
setLocale(locale) {
this.$i18n.locale = locale
this.$store.commit('language', this.$i18n.locale)
this.$store.commit('language', locale)
this.currentLanguage = this.getLocaleObject(locale)
localeChanged(locale)
},
async saveLocale(locale) {
// if (this.$i18n.locale === locale) return

View File

@ -7,6 +7,7 @@ const propsData = {
balance: 1234,
visible: false,
elopageUri: 'https://elopage.com',
pending: false,
}
const mocks = {
@ -20,6 +21,7 @@ const mocks = {
isAdmin: true,
},
},
$n: jest.fn((n) => n),
}
describe('Navbar', () => {

View File

@ -10,7 +10,7 @@
</div>
<b-navbar-nav class="ml-auto" is-nav>
<b-nav-item>{{ balance }} GDD</b-nav-item>
<b-nav-item>{{ pending ? '—' : $n(balance, 'decimal') }} GDD</b-nav-item>
<b-nav-item to="/profile" right class="d-none d-sm-none d-md-none d-lg-flex shadow-lg">
<small>
{{ $store.state.firstName }} {{ $store.state.lastName }},
@ -87,6 +87,10 @@ export default {
type: String,
required: false,
},
pending: {
type: Boolean,
required: true,
},
},
data() {
return {

View File

@ -4,7 +4,7 @@
<p></p>
<div class="mb-6">
<b-nav vertical class="w-200">
<b-nav-item to="/overview" class="mb-3" active>
<b-nav-item to="/overview" class="mb-3">
<b-icon icon="house" aria-hidden="true"></b-icon>
{{ $t('overview') }}
</b-nav-item>
@ -52,3 +52,9 @@ export default {
},
}
</script>
<style>
#component-sidebar .active,
.component-navbar .active {
font-weight: bold;
}
</style>

View File

@ -1,5 +1,6 @@
{
"admin_area": "Adminbereich",
"advanced-calculation": "Vorausberechnung",
"back": "Zurück",
"community": {
"choose-another-community": "Eine andere Gemeinschaft auswählen",
@ -120,7 +121,6 @@
"overview": "Übersicht",
"privacy_policy": "Datenschutzerklärung",
"publisher": {
"infoNoRegister": "Dies ist für die Registrieung nicht nötig.",
"infoText": "Wenn dir dein Empfehlungsgeber seine Publisher-Id gegeben hat, trage sie hier ein, sonst lass das Feld bitte unverändert!",
"publisherId": "Publisher-Id"
},
@ -198,7 +198,7 @@
},
"thx": {
"activateEmail": "Dein Konto wurde noch nicht aktiviert. Bitte überprüfe deine E-Mail und klicke den Aktivierungslink!",
"checkEmail": "Deine E-Mail wurde erfolgreich verifiziert.",
"checkEmail": "Deine E-Mail wurde erfolgreich verifiziert. Du kannst dich jetzt anmelden.",
"email": "Wir haben dir eine E-Mail gesendet.",
"emailActivated": "Danke dass Du deine E-Mail bestätigt hast.",
"errorTitle": "Achtung!",

View File

@ -1,5 +1,6 @@
{
"admin_area": "Admin Area",
"advanced-calculation": "Advanced calculation",
"back": "Back",
"community": {
"choose-another-community": "Choose another community",
@ -120,7 +121,6 @@
"overview": "Overview",
"privacy_policy": "Privacy policy",
"publisher": {
"infoNoRegister": "This is not necessary for registration.",
"infoText": "If your referrer has given you his publisher id, enter it here, otherwise leave the field unchanged!",
"publisherId": "PublisherID"
},
@ -198,7 +198,7 @@
},
"thx": {
"activateEmail": "Your account has not been activated yet, please check your emails and click the activation link!",
"checkEmail": "Your email has been successfully verified.",
"checkEmail": "Your email has been successfully verified. You can sign in now.",
"email": "We have sent you an email.",
"emailActivated": "Thank you your email has been activated.",
"errorTitle": "Attention!",

View File

@ -28,7 +28,7 @@ Vue.toasted.register(
loadAllRules(i18n)
addNavigationGuards(router, store, apolloProvider.defaultClient, i18n)
addNavigationGuards(router, store, apolloProvider.defaultClient)
if (!store) {
setTimeout(

View File

@ -1,6 +1,6 @@
import { verifyLogin } from '../graphql/queries'
const addNavigationGuards = (router, store, apollo, i18n) => {
const addNavigationGuards = (router, store, apollo) => {
// handle publisherId
router.beforeEach((to, from, next) => {
const publisherId = to.query.pid
@ -21,7 +21,6 @@ const addNavigationGuards = (router, store, apollo, i18n) => {
fetchPolicy: 'network-only',
})
.then((result) => {
i18n.locale = result.data.verifyLogin.language
store.dispatch('login', result.data.verifyLogin)
next({ path: '/overview' })
})

View File

@ -1,11 +1,15 @@
import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import { localeChanged } from 'vee-validate'
import i18n from '../i18n.js'
Vue.use(Vuex)
export const mutations = {
language: (state, language) => {
i18n.locale = language
localeChanged(language)
state.language = language
},
email: (state, email) => {

View File

@ -1,8 +1,18 @@
import { mutations, actions } from './store'
import Vuex from 'vuex'
import Vue from 'vue'
import i18n from '../i18n.js'
import { localeChanged } from 'vee-validate'
jest.mock('vuex')
jest.mock('../i18n.js')
jest.mock('vee-validate', () => {
return {
localeChanged: jest.fn(),
}
})
i18n.locale = 'blubb'
const {
language,
@ -29,6 +39,14 @@ describe('Vuex store', () => {
language(state, 'de')
expect(state.language).toEqual('de')
})
it('sets the i18n locale', () => {
expect(i18n.locale).toBe('de')
})
it('calls localChanged of vee-validate', () => {
expect(localeChanged).toBeCalledWith('de')
})
})
describe('email', () => {

View File

@ -4,6 +4,7 @@
class="main-navbar"
:balance="balance"
:visible="visible"
:pending="pending"
:elopageUri="elopageUri"
@set-visible="setVisible"
@admin="admin"

View File

@ -214,21 +214,55 @@ describe('Register', () => {
})
*/
describe('API calls', () => {
describe('API calls when form is missing input', () => {
beforeEach(() => {
wrapper.find('#registerFirstname').setValue('Max')
wrapper.find('#registerLastname').setValue('Mustermann')
wrapper.find('.language-switch-select').findAll('option').at(1).setSelected()
wrapper.find('#publisherid').setValue('12345')
})
it('has disabled submit button when missing input checked box', () => {
wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net')
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled')
})
it('has disabled submit button when missing email input', () => {
wrapper.find('#registerCheckbox').setChecked()
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled')
})
})
describe('API calls when completely filled and missing publisherid', () => {
beforeEach(() => {
wrapper.find('#registerFirstname').setValue('Max')
wrapper.find('#registerLastname').setValue('Mustermann')
wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net')
wrapper.find('.language-switch-select').findAll('option').at(1).setSelected()
wrapper.find('#registerCheckbox').setChecked()
})
it('has enabled submit button when completely filled', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe(undefined)
})
})
describe('API calls when completely filled', () => {
beforeEach(() => {
wrapper.find('#registerFirstname').setValue('Max')
wrapper.find('#registerLastname').setValue('Mustermann')
wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net')
wrapper.find('.language-switch-select').findAll('option').at(1).setSelected()
wrapper.find('#publisherid').setValue('12345')
wrapper.find('#registerCheckbox').setChecked()
})
it('commits publisherId to store', () => {
expect(mockStoreCommit).toBeCalledWith('publisherId', 12345)
})
it('has enabled submit button when completely filled', () => {
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled')
it('has enabled submit button when completely filled', async () => {
await wrapper.vm.$nextTick()
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe(undefined)
})
describe('server sends back error', () => {

View File

@ -145,7 +145,6 @@
class="text-center mt-1 shadow-lg p-3 mb-5 rounded"
>
{{ $t('publisher.infoText') }}
<span class="text-dark">{{ $t('publisher.infoNoRegister') }}</span>
<div class="text-center">
<b-icon icon="chevron-up" aria-hidden="true"></b-icon>
</div>
@ -162,9 +161,9 @@
</b-button>
</router-link>
<b-button
:disabled="!(namesFilled && emailFilled && form.agree && !!language)"
:disabled="disabled"
type="submit"
variant="primary"
:variant="disabled ? 'outline-light' : 'primary'"
>
{{ $t('signup') }}
</b-button>
@ -192,7 +191,6 @@
import InputEmail from '../../components/Inputs/InputEmail.vue'
import LanguageSwitchSelect from '../../components/LanguageSwitchSelect.vue'
import { createUser } from '../../graphql/mutations'
import { localeChanged } from 'vee-validate'
import { getCommunityInfoMixin } from '../../mixins/getCommunityInfo'
export default {
@ -219,8 +217,6 @@ export default {
updateLanguage(e) {
this.language = e
this.$store.commit('language', this.language)
this.$i18n.locale = this.language
localeChanged(this.language)
},
getValidationState({ dirty, validated, valid = null }) {
return dirty || validated ? valid : null
@ -268,6 +264,9 @@ export default {
emailFilled() {
return this.form.email !== ''
},
disabled() {
return !(this.namesFilled && this.emailFilled && this.form.agree && !!this.language)
},
},
}
</script>

View File

@ -15,54 +15,48 @@ const stubs = {
RouterLink: RouterLinkStub,
}
const createMockObject = (comingFrom) => {
return {
localVue,
mocks: {
$i18n: {
locale: 'en',
},
$t: jest.fn((t) => t),
$route: {
params: {
optin: '123',
comingFrom,
},
path: {
includes: (t) => t,
},
},
$toasted: {
global: {
error: toasterMock,
},
},
$router: {
push: routerPushMock,
},
$loading: {
show: jest.fn(() => {
return { hide: jest.fn() }
}),
},
$apollo: {
mutate: apolloMutationMock,
},
const mocks = {
$i18n: {
locale: 'en',
},
$t: jest.fn((t) => t),
$route: {
params: {
optin: '123',
},
stubs,
}
path: {
mock: 'checkEmail',
includes: jest.fn((t) => t === mocks.$route.path.mock),
},
},
$toasted: {
global: {
error: toasterMock,
},
},
$router: {
push: routerPushMock,
},
$loading: {
show: jest.fn(() => {
return { hide: jest.fn() }
}),
},
$apollo: {
mutate: apolloMutationMock,
},
}
describe('ResetPassword', () => {
let wrapper
const Wrapper = (functionName) => {
return mount(ResetPassword, functionName)
const Wrapper = () => {
return mount(ResetPassword, { localVue, mocks, stubs })
}
describe('mount', () => {
beforeEach(() => {
wrapper = Wrapper(createMockObject())
wrapper = Wrapper()
})
describe('No valid optin', () => {
@ -86,11 +80,32 @@ describe('ResetPassword', () => {
})
describe('Register header', () => {
it('has a welcome message', async () => {
expect(wrapper.find('div.header').text()).toContain('settings.password.reset')
expect(wrapper.find('div.header').text()).toContain(
'settings.password.reset-password.text',
)
describe('from reset', () => {
beforeEach(() => {
mocks.$route.path.mock = 'reset'
wrapper = Wrapper()
})
it('has a welcome message', async () => {
expect(wrapper.find('div.header').text()).toContain('settings.password.reset')
expect(wrapper.find('div.header').text()).toContain(
'settings.password.reset-password.text',
)
})
})
describe('from checkEmail', () => {
beforeEach(() => {
mocks.$route.path.mock = 'checkEmail'
wrapper = Wrapper()
})
it('has a welcome message', async () => {
expect(wrapper.find('div.header').text()).toContain('settings.password.set')
expect(wrapper.find('div.header').text()).toContain(
'settings.password.set-password.text',
)
})
})
})
@ -128,7 +143,6 @@ describe('ResetPassword', () => {
describe('submit form', () => {
beforeEach(async () => {
// wrapper = Wrapper(createMockObject())
await wrapper.findAll('input').at(0).setValue('Aa123456_')
await wrapper.findAll('input').at(1).setValue('Aa123456_')
await flushPromises()
@ -164,14 +178,14 @@ describe('ResetPassword', () => {
})
})
describe('server response with success', () => {
describe('server response with success on /checkEmail', () => {
beforeEach(async () => {
mocks.$route.path.mock = 'checkEmail'
apolloMutationMock.mockResolvedValue({
data: {
resetPassword: 'success',
},
})
wrapper = Wrapper(createMockObject('checkEmail'))
await wrapper.findAll('input').at(0).setValue('Aa123456_')
await wrapper.findAll('input').at(1).setValue('Aa123456_')
await wrapper.find('form').trigger('submit')
@ -189,6 +203,26 @@ describe('ResetPassword', () => {
)
})
it('redirects to "/thx/checkEmail"', () => {
expect(routerPushMock).toHaveBeenCalledWith('/thx/checkEmail')
})
})
describe('server response with success on /reset', () => {
beforeEach(async () => {
mocks.$route.path.mock = 'reset'
wrapper = Wrapper()
apolloMutationMock.mockResolvedValue({
data: {
resetPassword: 'success',
},
})
await wrapper.findAll('input').at(0).setValue('Aa123456_')
await wrapper.findAll('input').at(1).setValue('Aa123456_')
await wrapper.find('form').trigger('submit')
await flushPromises()
})
it('redirects to "/thx/reset"', () => {
expect(routerPushMock).toHaveBeenCalledWith('/thx/reset')
})

View File

@ -92,7 +92,11 @@ export default {
})
.then(() => {
this.form.password = ''
this.$router.push('/thx/reset')
if (this.$route.path.includes('checkEmail')) {
this.$router.push('/thx/checkEmail')
} else {
this.$router.push('/thx/reset')
}
})
.catch((error) => {
this.$toasted.global.error(error.message)

View File

@ -34,6 +34,7 @@
</b-row>
<b-container class="bv-example-row mt-3 gray-background p-2">
<p>{{ $t('advanced-calculation') }}</p>
<b-row class="pr-3">
<b-col class="text-right">{{ $t('form.current_balance') }}</b-col>
<b-col class="text-right">{{ $n(balance, 'decimal') }}</b-col>
@ -42,18 +43,13 @@
<b-col class="text-right">
<strong>{{ $t('form.your_amount') }}</strong>
</b-col>
<b-col class="text-right">
<b-col class="text-right borderbottom">
<strong>- {{ $n(amount, 'decimal') }}</strong>
</b-col>
</b-row>
<b-row class="pr-3">
<b-col class="text-right">{{ $t('decay.decay') }}</b-col>
<b-col class="text-right" style="border-bottom: double">- {{ $n(decay, 'decimal') }}</b-col>
</b-row>
<b-row class="pr-3">
<b-col class="text-right">{{ $t('form.new_balance') }}</b-col>
<b-col class="text-right">~ {{ $n(balance - amount - decay, 'decimal') }}</b-col>
<b-col class="text-right">~ {{ $n(balance - amount, 'decimal') }}</b-col>
</b-row>
</b-container>
@ -95,5 +91,6 @@ export default {
}
.borderbottom {
border-bottom: 1px solid rgb(70, 65, 65);
border-bottom-style: double;
}
</style>

View File

@ -138,10 +138,6 @@ describe('UserCard_Language', () => {
expect(storeCommitMock).toBeCalledWith('language', 'en')
})
it('changes the i18n locale', () => {
expect(mocks.$i18n.locale).toBe('en')
})
it('has no select field anymore', () => {
expect(wrapper.find('select').exists()).toBeFalsy()
})

View File

@ -60,7 +60,6 @@
</b-card>
</template>
<script>
import { localeChanged } from 'vee-validate'
import LanguageSwitchSelect from '../../../components/LanguageSwitchSelect.vue'
import { updateUserInfos } from '../../../graphql/mutations'
@ -97,8 +96,6 @@ export default {
})
.then(() => {
this.$store.commit('language', this.language)
this.$i18n.locale = this.language
localeChanged(this.language)
this.cancelEdit()
this.$toasted.success(this.$t('settings.language.success'))
})