Merge branch 'master' into contributions-table

This commit is contained in:
Moriz Wahl 2022-06-02 08:25:09 +02:00
commit 08f72e2777
51 changed files with 263 additions and 699 deletions

View File

@ -4,7 +4,7 @@
"main": "index.js",
"author": "Moriz Wahl",
"version": "1.8.3",
"license": "MIT",
"license": "Apache-2.0",
"private": false,
"scripts": {
"start": "node run/server.js",

View File

@ -13,6 +13,14 @@
{
"type": "dateFile",
"filename": "../logs/backend/apollo.log",
"pattern": "%d{ISO8601} %p %c %m",
"keepFileExt" : true,
"fileNameSep" : "_"
},
"backend":
{
"type": "dateFile",
"filename": "../logs/backend/backend.log",
"pattern": "%d{ISO8601} %p %c %X{user} %f:%l %m",
"keepFileExt" : true,
"fileNameSep" : "_"
@ -31,24 +39,52 @@
"level": "error",
"appender": "errorFile"
},
"out":
"out":
{
"type": "stdout",
"layout":
{
"type": "pattern", "pattern": "%d{ISO8601} %p %c %X{user} %f:%l %m"
}
}
},
"apolloOut":
{
"type": "stdout",
"layout":
{
"type": "pattern", "pattern": "%d{ISO8601} %p %c %m"
}
}
},
"categories":
"categories":
{
"default":
{
"appenders":
[
"out",
"errors"
],
"level": "debug",
"enableCallStack": true
},
"apollo":
{
"appenders":
[
"apollo",
"apolloOut",
"errors"
],
"level": "debug",
"enableCallStack": true
},
"backend":
{
"appenders":
[
"backend",
"out",
"errors"
],
"level": "debug",

View File

@ -5,7 +5,7 @@
"main": "src/index.ts",
"repository": "https://github.com/gradido/gradido/backend",
"author": "Ulf Gebhardt",
"license": "MIT",
"license": "Apache-2.0",
"private": false,
"scripts": {
"build": "tsc --build",

View File

@ -3,7 +3,7 @@ import CONFIG from './index'
describe('config/index', () => {
describe('decay start block', () => {
it('has the correct date set', () => {
expect(CONFIG.DECAY_START_TIME).toEqual(new Date('2021-05-13 17:46:31'))
expect(CONFIG.DECAY_START_TIME).toEqual(new Date('2021-05-13 17:46:31-0000'))
})
})
})

View File

@ -11,7 +11,7 @@ Decimal.set({
const constants = {
DB_VERSION: '0037-contributions_table',
DECAY_START_TIME: new Date('2021-05-13 17:46:31'), // GMT+0
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL || 'info',

View File

@ -19,7 +19,4 @@ export default class UpdateUserInfosArgs {
@Field({ nullable: true })
passwordNew?: string
@Field({ nullable: true })
coinanimation?: boolean
}

View File

@ -1,5 +0,0 @@
enum Setting {
COIN_ANIMATION = 'coinanimation',
}
export { Setting }

View File

@ -15,8 +15,6 @@ export class User {
this.language = user.language
this.publisherId = user.publisherId
this.isAdmin = user.isAdmin
// TODO
this.coinanimation = null
this.klickTipp = null
this.hasElopage = null
}
@ -61,11 +59,6 @@ export class User {
@Field(() => Date, { nullable: true })
isAdmin: Date | null
// TODO this is a bit inconsistent with what we query from the database
// therefore all those fields are now nullable with default value null
@Field(() => Boolean, { nullable: true })
coinanimation: boolean | null
@Field(() => KlickTipp, { nullable: true })
klickTipp: KlickTipp | null

View File

@ -344,7 +344,6 @@ describe('UserResolver', () => {
expect.objectContaining({
data: {
login: {
coinanimation: true,
email: 'bibi@bloxberg.de',
firstName: 'Bibi',
hasElopage: false,
@ -479,7 +478,6 @@ describe('UserResolver', () => {
firstName: 'Bibi',
lastName: 'Bloxberg',
language: 'de',
coinanimation: true,
klickTipp: {
newsletterState: false,
},

View File

@ -3,7 +3,7 @@ import { backendLogger as logger } from '@/server/logger'
import { Context, getUser } from '@/server/context'
import { Resolver, Query, Args, Arg, Authorized, Ctx, UseMiddleware, Mutation } from 'type-graphql'
import { getConnection, getCustomRepository } from '@dbTools/typeorm'
import { getConnection } from '@dbTools/typeorm'
import CONFIG from '@/config'
import { User } from '@model/User'
import { User as DbUser } from '@entity/User'
@ -13,8 +13,6 @@ import CreateUserArgs from '@arg/CreateUserArgs'
import UnsecureLoginArgs from '@arg/UnsecureLoginArgs'
import UpdateUserInfosArgs from '@arg/UpdateUserInfosArgs'
import { klicktippNewsletterStateMiddleware } from '@/middleware/klicktippMiddleware'
import { UserSettingRepository } from '@repository/UserSettingRepository'
import { Setting } from '@enum/Setting'
import { OptInType } from '@enum/OptInType'
import { LoginEmailOptIn } from '@entity/LoginEmailOptIn'
import { sendResetPasswordEmail as sendResetPasswordEmailMailer } from '@/mailer/sendResetPasswordEmail'
@ -228,15 +226,6 @@ export class UserResolver {
// Elopage Status & Stored PublisherId
user.hasElopage = await this.hasElopage(context)
// coinAnimation
const userSettingRepository = getCustomRepository(UserSettingRepository)
const coinanimation = await userSettingRepository
.readBoolean(userEntity.id, Setting.COIN_ANIMATION)
.catch((error) => {
logger.error('error:', error)
throw new Error(error)
})
user.coinanimation = coinanimation
logger.debug(`verifyLogin... successful: ${user.firstName}.${user.lastName}, ${user.email}`)
return user
}
@ -294,15 +283,6 @@ export class UserResolver {
DbUser.save(dbUser)
}
// coinAnimation
const userSettingRepository = getCustomRepository(UserSettingRepository)
const coinanimation = await userSettingRepository
.readBoolean(dbUser.id, Setting.COIN_ANIMATION)
.catch((error) => {
throw new Error(error)
})
user.coinanimation = coinanimation
context.setHeaders.push({
key: 'token',
value: encode(dbUser.pubKey),
@ -598,12 +578,10 @@ export class UserResolver {
@Mutation(() => Boolean)
async updateUserInfos(
@Args()
{ firstName, lastName, language, password, passwordNew, coinanimation }: UpdateUserInfosArgs,
{ firstName, lastName, language, password, passwordNew }: UpdateUserInfosArgs,
@Ctx() context: Context,
): Promise<boolean> {
logger.info(
`updateUserInfos(${firstName}, ${lastName}, ${language}, ***, ***, ${coinanimation})...`,
)
logger.info(`updateUserInfos(${firstName}, ${lastName}, ${language}, ***, ***)...`)
const userEntity = getUser(context)
if (firstName) {
@ -655,15 +633,6 @@ export class UserResolver {
await queryRunner.startTransaction('READ UNCOMMITTED')
try {
if (coinanimation !== null && coinanimation !== undefined) {
queryRunner.manager
.getCustomRepository(UserSettingRepository)
.setOrUpdate(userEntity.id, Setting.COIN_ANIMATION, coinanimation.toString())
.catch((error) => {
throw new Error('error saving coinanimation: ' + error)
})
}
await queryRunner.manager.save(userEntity).catch((error) => {
throw new Error('error saving user: ' + error)
})

View File

@ -31,7 +31,6 @@ export const updateUserInfos = gql`
$password: String
$passwordNew: String
$locale: String
$coinanimation: Boolean
) {
updateUserInfos(
firstName: $firstName
@ -39,7 +38,6 @@ export const updateUserInfos = gql`
password: $password
passwordNew: $passwordNew
language: $locale
coinanimation: $coinanimation
)
}
`

View File

@ -8,7 +8,6 @@ export const login = gql`
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}
@ -26,7 +25,6 @@ export const verifyLogin = gql`
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}

View File

@ -12,7 +12,6 @@ log4js.configure(options)
const apolloLogger = log4js.getLogger('apollo')
const backendLogger = log4js.getLogger('backend')
apolloLogger.addContext('user', 'unknown')
backendLogger.addContext('user', 'unknown')
export { apolloLogger, backendLogger }

View File

@ -32,16 +32,16 @@ const logPlugin = {
requestDidStart(requestContext: any) {
const { logger } = requestContext
const { query, mutation, variables } = requestContext.request
logger.trace(`Request:
logger.info(`Request:
${mutation || query}variables: ${JSON.stringify(filterVariables(variables), null, 2)}`)
return {
willSendResponse(requestContext: any) {
if (requestContext.context.user) logger.trace(`User ID: ${requestContext.context.user.id}`)
if (requestContext.context.user) logger.info(`User ID: ${requestContext.context.user.id}`)
if (requestContext.response.data)
logger.trace(`Response-Data:
logger.info(`Response-Data:
${JSON.stringify(requestContext.response.data, null, 2)}`)
if (requestContext.response.errors)
logger.trace(`Response-Errors:
logger.error(`Response-Errors:
${JSON.stringify(requestContext.response.errors, null, 2)}`)
return requestContext
},

View File

@ -1,33 +1,22 @@
import { EntityRepository, Repository } from '@dbTools/typeorm'
import { UserSetting } from '@entity/UserSetting'
import { Setting } from '@enum/Setting'
import { isStringBoolean } from '@/util/validate'
@EntityRepository(UserSetting)
export class UserSettingRepository extends Repository<UserSetting> {
async setOrUpdate(userId: number, key: Setting, value: string): Promise<UserSetting> {
switch (key) {
case Setting.COIN_ANIMATION:
if (!isStringBoolean(value)) {
throw new Error("coinanimation value isn't boolean")
}
break
default:
throw new Error("key isn't defined: " + key)
}
let entity = await this.findOne({ userId: userId, key: key })
async setOrUpdate(userId: number, value: string): Promise<UserSetting> {
let entity = await this.findOne({ userId: userId })
if (!entity) {
entity = new UserSetting()
entity.userId = userId
entity.key = key
}
entity.value = value
return this.save(entity)
}
async readBoolean(userId: number, key: Setting): Promise<boolean> {
const entity = await this.findOne({ userId: userId, key: key })
async readBoolean(userId: number): Promise<boolean> {
const entity = await this.findOne({ userId: userId })
if (!entity || !isStringBoolean(entity.value)) {
return true
}

View File

@ -5,7 +5,7 @@
"main": "src/index.ts",
"repository": "https://github.com/gradido/gradido/database",
"author": "Ulf Gebhardt",
"license": "MIT",
"license": "Apache-2.0",
"private": false,
"scripts": {
"build": "mkdir -p build/src/config/ && cp src/config/*.txt build/src/config/ && tsc --build",

View File

@ -0,0 +1 @@
<mxfile host="Electron" modified="2022-05-23T15:29:00.513Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/16.0.2 Chrome/96.0.4664.55 Electron/16.0.5 Safari/537.36" etag="IpEbe50ld79E_2HLyFXN" version="16.0.2" type="device"><diagram id="LWCFUfVkWozhiXBGj4Ze" name="Page-1">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</diagram></mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@ -45,7 +45,6 @@ module.exports = {
extensions: ['.js', '.vue'],
// TODO: remove ignores
ignores: [
'/site.thx./',
'/form./',
'/time./',
'/decay.types./',
@ -55,7 +54,6 @@ module.exports = {
'settings.password.set',
'settings.password.set-password.text',
'settings.password.subtitle',
'site.login.signin',
],
enableFix: false,
},

View File

@ -99,5 +99,6 @@
"not ie <= 10"
],
"author": "Gradido-Akademie - https://www.gradido.net/",
"license": "Apache-2.0",
"description": "Gradido, the Natural Economy of Life, is a way to worldwide prosperity and peace in harmony with nature. - Gradido, die Natürliche Ökonomie des lebens, ist ein Weg zu weltweitem Wohlstand und Frieden in Harmonie mit der Natur."
}

View File

@ -15,6 +15,14 @@ body {
color: #0e79bc !important;
}
.text-gradido {
color: rgb(249 205 105 / 100%);
}
.gradient-gradido {
background-image: linear-gradient(146deg, rgb(220 167 44) 50%, rgb(197 141 56 / 100%) 100%);
}
/* Navbar */
a,
.navbar-light,
@ -32,14 +40,6 @@ a:hover,
color: rgb(35 121 188 / 90%);
}
.text-gradido {
color: rgb(249 205 105 / 100%);
}
.gradient-gradido {
background-image: linear-gradient(146deg, rgb(220 167 44) 50%, rgb(197 141 56 / 100%) 100%);
}
/* Button */
.btn {
border-radius: 25px;

View File

@ -19,13 +19,13 @@
<div class="text-center ml-3 ml-lg-0 text-lg-right pt-1">
{{ $t('followUs') }}
<b-link href="https://www.facebook.com/groups/Gradido/" target="_blank">
<b-icon-facebook class="ml-3 mr-3" font-scale="1"></b-icon-facebook>
<b-icon-facebook class="ml-3 mr-3 c-grey" font-scale="1"></b-icon-facebook>
</b-link>
<b-link href="https://twitter.com/gradido" target="_blank">
<b-icon-twitter class="mr-3" font-scale="1"></b-icon-twitter>
<b-icon-twitter class="mr-3 c-grey" font-scale="1"></b-icon-twitter>
</b-link>
<b-link href="https://www.youtube.com/c/GradidoNet" target="_blank">
<b-icon-youtube class="mr-3" font-scale="1"></b-icon-youtube>
<b-icon-youtube class="mr-3 c-grey" font-scale="1"></b-icon-youtube>
</b-link>
<b-link href="https://t.me/Gradido" target="_blank">
@ -34,7 +34,7 @@
width="16"
height="16"
fill="currentColor"
class="bi bi-telegram"
class="bi bi-telegram c-grey"
viewBox="0 0 16 16"
>
<path

View File

@ -124,4 +124,10 @@ export default {
min-width: 360px;
}
}
@media screen and (max-height: 700px) {
.mobil-start-box #img3 {
top: -104px;
}
}
</style>

View File

@ -4,8 +4,8 @@ import Message from './Message'
const localVue = global.localVue
const propsData = {
headline: 'site.thx.title',
subtitle: 'site.thx.email',
headline: 'Headline text',
subtitle: 'Subtitle text',
buttonText: 'login',
linkTo: '/login',
}
@ -32,8 +32,8 @@ describe('Message', () => {
describe('with button', () => {
it('renders title, subtitle, and button text', () => {
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.email')
expect(wrapper.find('.test-message-headline').text()).toBe('Headline text')
expect(wrapper.find('.test-message-subtitle').text()).toBe('Subtitle text')
expect(wrapper.find('.test-message-button').text()).toBe('login')
})
@ -51,8 +51,8 @@ describe('Message', () => {
})
it('renders title, subtitle, and button text', () => {
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.email')
expect(wrapper.find('.test-message-headline').text()).toBe('Headline text')
expect(wrapper.find('.test-message-subtitle').text()).toBe('Subtitle text')
})
it('button is not shown', () => {

View File

@ -1,127 +0,0 @@
import { mount } from '@vue/test-utils'
import UserCoinAnimation from './UserCoinAnimation'
import { updateUserInfos } from '@/graphql/mutations'
import { toastErrorSpy, toastSuccessSpy } from '@test/testSetup'
const localVue = global.localVue
const mockAPIcall = jest.fn()
const storeCommitMock = jest.fn()
describe('UserCard_CoinAnimation', () => {
let wrapper
const mocks = {
$t: jest.fn((t) => t),
$store: {
state: {
language: 'de',
coinanimation: true,
},
commit: storeCommitMock,
},
$apollo: {
mutate: mockAPIcall,
},
}
const Wrapper = () => {
return mount(UserCoinAnimation, { localVue, mocks })
}
describe('mount', () => {
beforeEach(() => {
jest.clearAllMocks()
wrapper = Wrapper()
})
it('renders the component', () => {
expect(wrapper.find('div#formusercoinanimation').exists()).toBeTruthy()
})
it('has an edit BFormCheckbox switch', () => {
expect(wrapper.find('.Test-BFormCheckbox').exists()).toBeTruthy()
})
describe('enable with success', () => {
beforeEach(async () => {
await wrapper.setData({ CoinAnimationStatus: false })
mockAPIcall.mockResolvedValue({
data: {
updateUserInfos: {
validValues: 1,
},
},
})
await wrapper.find('input').setChecked()
})
it('calls the updateUserInfos mutation', () => {
expect(mockAPIcall).toBeCalledWith({
mutation: updateUserInfos,
variables: {
coinanimation: true,
},
})
})
it('updates the store', () => {
expect(storeCommitMock).toBeCalledWith('coinanimation', true)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('settings.coinanimation.True')
})
})
describe('disable with success', () => {
beforeEach(async () => {
await wrapper.setData({ CoinAnimationStatus: true })
mockAPIcall.mockResolvedValue({
data: {
updateUserInfos: {
validValues: 1,
},
},
})
await wrapper.find('input').setChecked(false)
})
it('calls the subscribe mutation', () => {
expect(mockAPIcall).toBeCalledWith({
mutation: updateUserInfos,
variables: {
coinanimation: false,
},
})
})
it('updates the store', () => {
expect(storeCommitMock).toBeCalledWith('coinanimation', false)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('settings.coinanimation.False')
})
})
describe('disable with server error', () => {
beforeEach(() => {
mockAPIcall.mockRejectedValue({
message: 'Ouch',
})
wrapper.find('input').trigger('change')
})
it('resets the CoinAnimationStatus', () => {
expect(wrapper.vm.CoinAnimationStatus).toBeTruthy()
})
it('toasts an error message', () => {
expect(toastErrorSpy).toBeCalledWith('Ouch')
})
})
})
})

View File

@ -1,65 +0,0 @@
<template>
<b-card
id="formusercoinanimation"
class="bg-transparent gradido-custom-background gradido-no-border-radius"
>
<div>
<b-row class="mb-3">
<b-col class="mb-2 col-12">
<small>
<b>{{ $t('settings.coinanimation.coinanimation') }}</b>
</small>
</b-col>
<b-col class="col-12">
<b-form-checkbox
class="Test-BFormCheckbox"
v-model="CoinAnimationStatus"
name="check-button"
switch
@change="onSubmit"
>
{{
CoinAnimationStatus
? $t('settings.coinanimation.True')
: $t('settings.coinanimation.False')
}}
</b-form-checkbox>
</b-col>
</b-row>
</div>
</b-card>
</template>
<script>
import { updateUserInfos } from '@/graphql/mutations'
export default {
name: 'UserCoinAnimation',
data() {
return {
CoinAnimationStatus: this.$store.state.coinanimation,
}
},
methods: {
async onSubmit() {
this.$apollo
.mutate({
mutation: updateUserInfos,
variables: {
coinanimation: this.CoinAnimationStatus,
},
})
.then(() => {
this.$store.commit('coinanimation', this.CoinAnimationStatus)
this.toastSuccess(
this.CoinAnimationStatus
? this.$t('settings.coinanimation.True')
: this.$t('settings.coinanimation.False'),
)
})
.catch((error) => {
this.CoinAnimationStatus = this.$store.state.coinanimation
this.toastError(error.message)
})
},
},
}
</script>

View File

@ -189,7 +189,7 @@ describe('UserCard_FormUserPasswort', () => {
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('site.thx.reset')
expect(toastSuccessSpy).toBeCalledWith('message.reset')
})
it('cancels the edit process', () => {

View File

@ -89,7 +89,7 @@ export default {
},
})
.then(() => {
this.toastSuccess(this.$t('site.thx.reset'))
this.toastSuccess(this.$t('message.reset'))
this.cancelEdit()
})
.catch((error) => {

View File

@ -31,7 +31,6 @@ export const updateUserInfos = gql`
$password: String
$passwordNew: String
$locale: String
$coinanimation: Boolean
) {
updateUserInfos(
firstName: $firstName
@ -39,7 +38,6 @@ export const updateUserInfos = gql`
password: $password
passwordNew: $passwordNew
language: $locale
coinanimation: $coinanimation
)
}
`

View File

@ -7,7 +7,6 @@ export const login = gql`
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}
@ -25,7 +24,6 @@ export const verifyLogin = gql`
firstName
lastName
language
coinanimation
klickTipp {
newsletterState
}

View File

@ -16,7 +16,11 @@
<div class="h0 text-white">{{ $t('auth.left.gratitude') }}</div>
<div class="h1 text-white">{{ $t('auth.left.newCurrency') }}</div>
<div class="h2 text-white">{{ $t('auth.left.oneAnotherNature') }}</div>
<b-button variant="gradido">{{ $t('auth.left.learnMore') }}</b-button>
<b-link :href="`https://gradido.net/${$i18n.locale}`" target="_blank">
<b-button variant="gradido">
{{ $t('auth.left.learnMore') }}
</b-button>
</b-link>
</div>
</div>
<b-row class="justify-content-md-center">

View File

@ -172,6 +172,16 @@
"minus": "",
"pipe": "|"
},
"message": {
"activateEmail": "Dein Konto wurde noch nicht aktiviert. Bitte überprüfe deine E-Mail und klicke den Aktivierungslink oder fordere einen neuen Aktivierungslink über die Password Reset Seite an.",
"checkEmail": "Deine E-Mail wurde erfolgreich verifiziert. Du kannst dich jetzt anmelden.",
"email": "Wir haben dir eine E-Mail gesendet.",
"errorTitle": "Achtung!",
"register": "Du bist jetzt registriert, bitte überprüfe deine Emails und klicke auf den Aktivierungslink.",
"reset": "Dein Passwort wurde geändert.",
"title": "Danke!",
"unsetPassword": "Dein Passwort wurde noch nicht gesetzt. Bitte setze es neu."
},
"navigation": {
"admin_area": "Adminbereich",
"logout": "Abmelden",
@ -186,11 +196,6 @@
"send_gdd": "GDD versenden",
"send_per_link": "GDD versenden per Link",
"settings": {
"coinanimation": {
"coinanimation": "Münzanimation",
"False": "Münzanimation ausgeschaltet",
"True": "Münzanimation eingeschaltet"
},
"language": {
"changeLanguage": "Sprache ändern",
"de": "Deutsch",
@ -229,8 +234,7 @@
"heading": "Bitte gib deine E-Mail an mit der du bei Gradido angemeldet bist."
},
"login": {
"heading": "Melde dich mit deinen Zugangsdaten an. Bewahre sie stets sicher auf!",
"saveLogin": "Anmeldung speichern"
"heading": "Melde dich mit deinen Zugangsdaten an. Bewahre sie stets sicher auf!"
},
"resetPassword": {
"heading": "Trage bitte dein Passwort ein und wiederhole es."
@ -245,18 +249,6 @@
"one_number": "Zahl erforderlich.",
"special-char": "Sonderzeichen erforderlich (z.B. _ oder ä)",
"uppercase": "Großbuchstabe erforderlich."
},
"thx": {
"activateEmail": "Dein Konto wurde noch nicht aktiviert. Bitte überprüfe deine E-Mail und klicke den Aktivierungslink oder fordere einen neuen Aktivierungslink über die Password Reset Seite.",
"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!",
"register": "Du bist jetzt registriert, bitte überprüfe deine Emails und klicke auf den Aktivierungslink.",
"reset": "Dein Passwort wurde geändert.",
"resetPassword": "Den Code den Du genutzt hast ist zu alt bitte fordere ein neuen über die Passwort Reset Seite an.",
"title": "Danke!",
"unsetPassword": "Dein Passwort wurde noch nicht gesetzt. Bitte setze es neu."
}
},
"success": "Erfolg",

View File

@ -11,7 +11,7 @@
"hereLogin": "Log in here",
"learnMore": "Learn more …",
"newCurrency": "The new currency",
"oneAnotherNature": "FOR ONE ANOTHER, FOR ALL, FOR NATURE"
"oneAnotherNature": "FOR EACH OTHER, FOR ALL, FOR NATURE"
},
"navbar": {
"aboutGradido": "About Gradido"
@ -172,6 +172,16 @@
"minus": "",
"pipe": "|"
},
"message": {
"activateEmail": "Your account has not been activated yet. Please check your emails and click the activation link or order a new activation link over the password reset page.",
"checkEmail": "Your email has been successfully verified. You can sign in now.",
"email": "We have sent you an email.",
"errorTitle": "Attention!",
"register": "You are registered now, please check your emails and click the activation link.",
"reset": "Your password has been changed.",
"title": "Thank you!",
"unsetPassword": "Your password has not been set yet. Please set it again."
},
"navigation": {
"admin_area": "Admin Area",
"logout": "Logout",
@ -186,11 +196,6 @@
"send_gdd": "GDD send",
"send_per_link": "GDD send via link",
"settings": {
"coinanimation": {
"coinanimation": "Coin animation",
"False": "Coin animation disabled",
"True": "Coin animation enabled"
},
"language": {
"changeLanguage": "Change language",
"de": "Deutsch",
@ -229,8 +234,7 @@
"heading": "Please enter the email address by which you're registered here."
},
"login": {
"heading": "Log in with your access data. Keep them safe!",
"saveLogin": "Save login"
"heading": "Log in with your access data. Keep them safe!"
},
"resetPassword": {
"heading": "Please enter your password and repeat it."
@ -245,18 +249,6 @@
"one_number": "One number required.",
"special-char": "One special character required (e.g. _ or ä)",
"uppercase": "One uppercase letter required."
},
"thx": {
"activateEmail": "Your account has not been activated yet. Please check your emails and click the activation link or order a new activation link over the password reset page.",
"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!",
"register": "You are registered now, please check your emails and click the activation link.",
"reset": "Your password has been changed.",
"resetPassword": "The code you used was to old please order a new on over the password reset page.",
"title": "Thank you!",
"unsetPassword": "Your password has not been set yet. Please set it again."
}
},
"success": "Success",

View File

@ -50,16 +50,6 @@ describe('ForgotPassword', () => {
expect(wrapper.find('div.forgot-password').exists()).toBe(true)
})
describe('back button', () => {
it('has a "back" button', () => {
expect(wrapper.findComponent(RouterLinkStub).text()).toEqual('back')
})
it('links to login', () => {
expect(wrapper.findComponent(RouterLinkStub).props().to).toEqual('/login')
})
})
describe('input form', () => {
let form
@ -111,7 +101,7 @@ describe('ForgotPassword', () => {
it('shows error title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.errorTitle')
expect(wrapper.find('.test-message-headline').text()).toBe('message.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('error.email-already-sent')
expect(wrapper.find('.test-message-button').text()).toBe('login')
})
@ -121,6 +111,8 @@ describe('ForgotPassword', () => {
})
it.skip('click redirects to "/login"', async () => {
// wrapper.find('.test-message-button').trigger('click')
// await wrapper.vm.$nextTick()
expect(mockRouterPush).toBeCalledWith('/login')
})
@ -144,14 +136,18 @@ describe('ForgotPassword', () => {
it('shows success title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.email')
expect(wrapper.find('.test-message-headline').text()).toBe('message.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('message.email')
expect(wrapper.find('.test-message-button').text()).toBe('login')
})
it('button link redirects to "/login"', () => {
expect(wrapper.find('.test-message-button').attributes('href')).toBe('/login')
})
it.skip('click redirects to "/login"', () => {
// expect(mockRouterPush).toBeCalledWith('/login')
})
})
})
})

View File

@ -4,30 +4,23 @@
<div class="pb-5">{{ $t('site.forgotPassword.heading') }}</div>
<b-row class="justify-content-center">
<b-col>
<b-card no-body class="border-0 gradido-custom-background">
<b-card-body class="p-4">
<validation-observer ref="observer" v-slot="{ handleSubmit }">
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)">
<input-email v-model="form.email"></input-email>
<div class="text-center">
<b-button type="submit" variant="primary">
{{ $t('settings.password.send_now') }}
</b-button>
</div>
</b-form>
</validation-observer>
</b-card-body>
</b-card>
<validation-observer ref="observer" v-slot="{ handleSubmit }">
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)">
<input-email v-model="form.email"></input-email>
<div class="text-center">
<b-button type="submit" variant="gradido">
{{ $t('settings.password.send_now') }}
</b-button>
</div>
</b-form>
</validation-observer>
</b-col>
</b-row>
<div class="text-center py-lg-4">
<router-link to="/login" class="mt-3">{{ $t('back') }}</router-link>
</div>
</b-container>
<b-container v-else>
<message
:headline="success ? $t('site.thx.title') : $t('site.thx.errorTitle')"
:subtitle="success ? $t('site.thx.email') : $t('error.email-already-sent')"
:headline="success ? $t('message.title') : $t('message.errorTitle')"
:subtitle="success ? $t('message.email') : $t('error.email-already-sent')"
:buttonText="$t('login')"
linkTo="/login"
/>

View File

@ -198,8 +198,8 @@ describe('Login', () => {
it('shows error title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.activateEmail')
expect(wrapper.find('.test-message-headline').text()).toBe('message.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('message.activateEmail')
expect(wrapper.find('.test-message-button').text()).toBe('settings.password.reset')
})
@ -226,8 +226,8 @@ describe('Login', () => {
it('shows error title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.unsetPassword')
expect(wrapper.find('.test-message-headline').text()).toBe('message.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('message.unsetPassword')
expect(wrapper.find('.test-message-button').text()).toBe('settings.password.reset')
})

View File

@ -16,17 +16,6 @@
</b-col>
</b-row>
<b-row>
<b-col class="d-flex justify-content-start">
<b-form-checkbox
class="mt-3"
v-model="status"
name="checkbox-1"
value="saved"
unchecked-value="not_saved"
>
{{ $t('site.login.saveLogin') }}
</b-form-checkbox>
</b-col>
<b-col class="d-flex justify-content-end">
<router-link to="/forgot-password" class="mt-3">
{{ $t('settings.password.forgot_pwd') }}
@ -41,7 +30,7 @@
</b-container>
<b-container v-else>
<message
:headline="$t('site.thx.errorTitle')"
:headline="$t('message.errorTitle')"
:subtitle="errorSubtitle"
:buttonText="$t('settings.password.reset')"
:linkTo="errorLinkTo"
@ -70,7 +59,6 @@ export default {
password: '',
},
passwordVisible: false,
status: false,
showPageMessage: false,
errorReason: null,
errorSubtitle: '',
@ -107,12 +95,12 @@ export default {
.catch((error) => {
if (error.message.includes('User email not validated')) {
this.showPageMessage = true
this.errorSubtitle = this.$t('site.thx.activateEmail')
this.errorSubtitle = this.$t('message.activateEmail')
this.errorLinkTo = '/forgot-password'
this.toastError(this.$t('error.no-account'))
} else if (error.message.includes('User has no password set yet')) {
this.showPageMessage = true
this.errorSubtitle = this.$t('site.thx.unsetPassword')
this.errorSubtitle = this.$t('message.unsetPassword')
this.errorLinkTo = '/reset-password/login'
this.toastError(this.$t('error.no-account'))
} else if (error.message.includes('No user with this credentials')) {

View File

@ -38,9 +38,5 @@ describe('Profile', () => {
it('has a user change newsletter form', () => {
expect(wrapper.findComponent({ name: 'UserNewsletter' }).exists()).toBeTruthy()
})
it('has a user change coin animation form', () => {
expect(wrapper.findComponent({ name: 'UserCoinAnimation' }).exists()).toBeTruthy()
})
})
})

View File

@ -8,8 +8,6 @@
<user-language />
<hr />
<user-newsletter />
<hr />
<user-coin-animation />
</div>
</template>
<script>
@ -18,7 +16,6 @@ import UserData from '@/components/UserSettings/UserData.vue'
import UserPassword from '@/components/UserSettings/UserPassword.vue'
import UserLanguage from '@/components/UserSettings/UserLanguage.vue'
import UserNewsletter from '@/components/UserSettings/UserNewsletter.vue'
import UserCoinAnimation from '@/components/UserSettings/UserCoinAnimation.vue'
export default {
name: 'Profile',
@ -28,7 +25,6 @@ export default {
UserPassword,
UserLanguage,
UserNewsletter,
UserCoinAnimation,
},
props: {
balance: { type: Number, default: 0 },

View File

@ -202,8 +202,8 @@ describe('Register', () => {
it('shows success title, subtitle', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.register')
expect(wrapper.find('.test-message-headline').text()).toBe('message.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('message.register')
})
it('button is not present', () => {

View File

@ -90,7 +90,7 @@
</validation-observer>
</b-container>
<b-container v-else>
<message :headline="$t('site.thx.title')" :subtitle="$t('site.thx.register')" />
<message :headline="$t('message.title')" :subtitle="$t('message.register')" />
</b-container>
</div>
</template>

View File

@ -118,14 +118,32 @@ describe('ResetPassword', () => {
await flushPromises()
})
it('shows error title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('message.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe(
'...email was sent more than 23 hours and 10 minutes ago',
)
expect(wrapper.find('.test-message-button').text()).toBe('settings.password.reset')
})
it('button link directs to "/forgot-password/resetPassword"', () => {
expect(wrapper.find('.test-message-button').attributes('href')).toBe(
'/forgot-password/resetPassword',
)
})
it('toasts an error message', () => {
expect(toastErrorSpy).toHaveBeenCalledWith(
'...email was sent more than 23 hours and 10 minutes ago',
)
})
it('router pushes to /forgot-password/resetPassword', () => {
expect(routerPushMock).toHaveBeenCalledWith('/forgot-password/resetPassword')
it.skip('click redirects to "/forgot-password/resetPassword"', () => {
// wrapper.find('.test-message-button').trigger('click')
// await flushPromises()
// await wrapper.vm.$nextTick()
// expect(routerPushMock).toHaveBeenCalledWith('/forgot-password/resetPassword')
})
})
@ -137,9 +155,26 @@ describe('ResetPassword', () => {
await flushPromises()
})
it('shows error title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('message.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('Error')
expect(wrapper.find('.test-message-button').text()).toBe('settings.password.reset')
})
it('button link directs to "/forgot-password/resetPassword"', () => {
expect(wrapper.find('.test-message-button').attributes('href')).toBe(
'/forgot-password/resetPassword',
)
})
it('toasts an error message', () => {
expect(toastErrorSpy).toHaveBeenCalledWith('Error')
})
it.skip('click redirects to "/forgot-password/resetPassword"', () => {
// expect(routerPushMock).toHaveBeenCalledWith('/forgot-password/resetPassword')
})
})
describe('server response with success on /checkEmail', () => {
@ -168,30 +203,19 @@ describe('ResetPassword', () => {
)
})
it('redirects to "/thx/checkEmail"', () => {
expect(routerPushMock).toHaveBeenCalledWith('/thx/checkEmail')
it('shows message title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('message.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('message.checkEmail')
expect(wrapper.find('.test-message-button').text()).toBe('login')
})
describe('with param code', () => {
beforeEach(async () => {
mocks.$route.params.code = 'the-most-secret-code-ever'
apolloMutationMock.mockResolvedValue({
data: {
resetPassword: 'success',
},
})
wrapper = Wrapper()
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('button link directs to "/login"', () => {
expect(wrapper.find('.test-message-button').attributes('href')).toBe('/login')
})
it('redirects to "/thx/checkEmail/the-most-secret-code-ever"', () => {
expect(routerPushMock).toHaveBeenCalledWith(
'/thx/checkEmail/the-most-secret-code-ever',
)
})
it.skip('click redirects to "/login"', () => {
// expect(routerPushMock).toHaveBeenCalledWith('/login')
})
})
@ -210,8 +234,19 @@ describe('ResetPassword', () => {
await flushPromises()
})
it('redirects to "/thx/resetPassword"', () => {
expect(routerPushMock).toHaveBeenCalledWith('/thx/resetPassword')
it('shows message title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('message.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('message.reset')
expect(wrapper.find('.test-message-button').text()).toBe('login')
})
it('button link directs to "/login"', () => {
expect(wrapper.find('.test-message-button').attributes('href')).toBe('/login')
})
it.skip('click redirects to "/login"', () => {
// expect(routerPushMock).toHaveBeenCalledWith('/login')
})
})
})

View File

@ -1,5 +1,5 @@
<template>
<div class="resetpwd-form">
<div v-if="enterData" class="resetpwd-form">
<div class="pb-5">{{ $t('site.resetPassword.heading') }}</div>
<validation-observer ref="observer" v-slot="{ handleSubmit }">
<b-form role="form" @submit.prevent="handleSubmit(onSubmit)">
@ -13,12 +13,21 @@
</b-form>
</validation-observer>
</div>
<div v-else>
<message
:headline="messageHeadline"
:subtitle="messageSubtitle"
:buttonText="messageButtonText"
:linkTo="messageButtonLinktTo"
/>
</div>
</template>
<script>
import InputPasswordConfirmation from '@/components/Inputs/InputPasswordConfirmation'
import { setPassword } from '@/graphql/mutations'
import { queryOptIn } from '@/graphql/queries'
import InputPasswordConfirmation from '@/components/Inputs/InputPasswordConfirmation'
import Message from '@/components/Message/Message'
const textFields = {
reset: {
@ -39,6 +48,7 @@ export default {
name: 'ResetPassword',
components: {
InputPasswordConfirmation,
Message,
},
data() {
return {
@ -47,8 +57,17 @@ export default {
passwordRepeat: '',
},
displaySetup: {},
showPageMessage: false,
messageHeadline: null,
messageSubtitle: null,
messageButtonText: null,
messageButtonLinktTo: null,
}
},
created() {
this.$emit('set-mobile-start', false)
this.setDisplaySetup()
},
methods: {
async onSubmit() {
this.$apollo
@ -61,24 +80,33 @@ export default {
})
.then(() => {
this.form.password = ''
if (this.$route.path.includes('checkEmail')) {
if (this.$route.params.code) {
this.$router.push('/thx/checkEmail/' + this.$route.params.code)
} else {
this.$router.push('/thx/checkEmail')
}
} else {
this.$router.push('/thx/resetPassword')
}
this.form.passwordRepeat = ''
this.showPageMessage = true
this.messageHeadline = this.$t('message.title')
this.messageSubtitle = this.$route.path.includes('checkEmail')
? this.$t('message.checkEmail')
: this.$t('message.reset')
this.messageButtonText = this.$t('login')
this.messageButtonLinktTo = '/login'
})
.catch((error) => {
this.toastError(error.message)
let errorMessage
if (
error.message.match(
/email was sent more than ([0-9]+ hours)?( and )?([0-9]+ minutes)? ago/,
)
)
this.$router.push('/forgot-password/resetPassword')
) {
errorMessage = error.message
} else {
errorMessage = error.message
}
this.showPageMessage = true
this.messageHeadline = this.$t('message.errorTitle')
this.messageSubtitle = errorMessage
this.messageButtonText = this.$t('settings.password.reset')
this.messageButtonLinktTo = '/forgot-password/resetPassword'
this.toastError(errorMessage)
})
},
checkOptInCode() {
@ -105,9 +133,10 @@ export default {
}
},
},
created() {
this.$emit('set-mobile-start', false)
this.setDisplaySetup()
computed: {
enterData() {
return !this.showPageMessage
},
},
}
</script>

View File

@ -143,6 +143,7 @@ export default {
},
created() {
this.setTransactionLinkInformation()
this.$emit('set-mobile-start', false)
},
}
</script>

View File

@ -1,101 +0,0 @@
import { mount } from '@vue/test-utils'
import Thx from './thx'
const localVue = global.localVue
const createMockObject = (comingFrom) => {
return {
$t: jest.fn((t) => t),
$route: {
params: {
comingFrom,
},
},
}
}
describe('Thx', () => {
let wrapper
const Wrapper = (mocks) => {
return mount(Thx, { localVue, mocks })
}
describe('mount', () => {
beforeEach(() => {
wrapper = Wrapper(createMockObject('forgotPassword'))
})
it('renders the thx page', () => {
expect(wrapper.find('div.header').exists()).toBeTruthy()
})
it('renders the title', () => {
expect(wrapper.find('p.h1').text()).toBe('site.thx.title')
})
})
describe('coming from /forgot-password', () => {
beforeEach(() => {
wrapper = Wrapper(createMockObject('forgotPassword'))
})
it('renders the thanks text', () => {
expect(wrapper.find('p.h4').text()).toBe('site.thx.email')
})
it('renders the thanks redirect button', () => {
expect(wrapper.find('a.btn').text()).toBe('login')
})
it('links the redirect button to /login', () => {
expect(wrapper.find('a.btn').attributes('href')).toBe('/login')
})
})
describe('coming from /reset-password', () => {
beforeEach(() => {
wrapper = Wrapper(createMockObject('resetPassword'))
})
it('renders the thanks text', () => {
expect(wrapper.find('p.h4').text()).toBe('site.thx.reset')
})
it('renders the thanks redirect button', () => {
expect(wrapper.find('a.btn').text()).toBe('login')
})
it('links the redirect button to /login', () => {
expect(wrapper.find('a.btn').attributes('href')).toBe('/login')
})
})
describe('coming from /register', () => {
beforeEach(() => {
wrapper = Wrapper(createMockObject('register'))
})
it('renders the thanks text', () => {
expect(wrapper.find('p.h4').text()).toBe('site.thx.register')
})
})
describe('coming from /login', () => {
beforeEach(() => {
wrapper = Wrapper(createMockObject('login'))
})
it('renders the thanks text', () => {
expect(wrapper.find('p.h4').text()).toBe('site.thx.activateEmail')
})
it('renders the thanks redirect button', () => {
expect(wrapper.find('a.btn').text()).toBe('settings.password.reset')
})
it('links the redirect button to /forgot-password', () => {
expect(wrapper.find('a.btn').attributes('href')).toBe('/forgot-password')
})
})
})

View File

@ -1,76 +0,0 @@
<template>
<div>
<!-- Header -->
<div class="header py-7 py-lg-8 pt-lg-9">
<b-container>
<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>
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
<p class="h4">{{ $t(displaySetup.subtitle) }}</p>
<hr />
<b-button v-if="$route.params.code" :to="`/login/${$route.params.code}`">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
{{ $t(displaySetup.button) }}
</b-button>
<b-button v-else-if="displaySetup.linkTo" :to="displaySetup.linkTo">
<!-- eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys-->
{{ $t(displaySetup.button) }}
</b-button>
</div>
</b-container>
</div>
<!-- Page content -->
</div>
</template>
<script>
const textFields = {
forgotPassword: {
headline: 'site.thx.title',
subtitle: 'site.thx.email',
button: 'login',
linkTo: '/login',
},
resetPassword: {
headline: 'site.thx.title',
subtitle: 'site.thx.reset',
button: 'login',
linkTo: '/login',
},
register: {
headline: 'site.thx.title',
subtitle: 'site.thx.register',
button: 'signin',
// linkTo: '/login',
},
checkEmail: {
headline: 'site.thx.title',
subtitle: 'site.thx.checkEmail',
button: 'login',
linkTo: '/login',
},
login: {
headline: 'site.thx.errorTitle',
subtitle: 'site.thx.activateEmail',
button: 'settings.password.reset',
linkTo: '/forgot-password',
},
}
export default {
name: 'Thx',
data() {
return {
displaySetup: {},
}
},
methods: {
setDisplaySetup(from) {
this.displaySetup = textFields[this.$route.params.comingFrom]
},
},
created() {
this.setDisplaySetup()
},
}
</script>

View File

@ -49,8 +49,8 @@ describe('router', () => {
expect(routes.find((r) => r.path === '/').redirect()).toEqual({ path: '/login' })
})
it('has seventeen routes defined', () => {
expect(routes).toHaveLength(17)
it('has sixteen routes defined', () => {
expect(routes).toHaveLength(16)
})
describe('overview', () => {
@ -111,31 +111,6 @@ describe('router', () => {
})
})
describe('thx', () => {
const thx = routes.find((r) => r.path === '/thx/:comingFrom/:code?')
it('loads the "Thx" page', async () => {
const component = await thx.component()
expect(component.default.name).toBe('Thx')
})
describe('beforeEnter', () => {
const beforeEnter = thx.beforeEnter
const next = jest.fn()
it('redirects to login when not coming from a valid page', () => {
beforeEnter({}, { path: '' }, next)
expect(next).toBeCalledWith({ path: '/login' })
})
it('enters the page when coming from a valid page', () => {
jest.resetAllMocks()
beforeEnter({}, { path: '/forgot-password' }, next)
expect(next).toBeCalledWith()
})
})
})
describe('forgot password', () => {
it('loads the "ForgotPassword" page', async () => {
const component = await routes.find((r) => r.path === '/forgot-password').component()

View File

@ -46,18 +46,6 @@ const routes = [
path: '/register/:code?',
component: () => import('@/pages/Register.vue'),
},
{
path: '/thx/:comingFrom/:code?',
component: () => import('@/pages/thx.vue'),
beforeEnter: (to, from, next) => {
const validFrom = ['forgot-password', 'reset-password', 'register', 'login', 'checkEmail']
if (!validFrom.includes(from.path.split('/')[1])) {
next({ path: '/login' })
} else {
next()
}
},
},
{
path: '/forgot-password',
component: () => import('@/pages/ForgotPassword.vue'),

View File

@ -38,9 +38,6 @@ export const mutations = {
isAdmin: (state, isAdmin) => {
state.isAdmin = !!isAdmin
},
coinanimation: (state, coinanimation) => {
state.coinanimation = coinanimation
},
hasElopage: (state, hasElopage) => {
state.hasElopage = hasElopage
},
@ -53,7 +50,6 @@ export const actions = {
// commit('username', data.username)
commit('firstName', data.firstName)
commit('lastName', data.lastName)
commit('coinanimation', data.coinanimation)
commit('newsletterState', data.klickTipp.newsletterState)
commit('hasElopage', data.hasElopage)
commit('publisherId', data.publisherId)
@ -65,7 +61,6 @@ export const actions = {
// commit('username', '')
commit('firstName', '')
commit('lastName', '')
commit('coinanimation', true)
commit('newsletterState', null)
commit('hasElopage', false)
commit('publisherId', null)
@ -91,7 +86,6 @@ try {
// username: '',
token: null,
isAdmin: false,
coinanimation: true,
newsletterState: null,
hasElopage: false,
publisherId: null,

View File

@ -20,7 +20,6 @@ const {
token,
firstName,
lastName,
coinanimation,
newsletterState,
publisherId,
isAdmin,
@ -78,14 +77,6 @@ describe('Vuex store', () => {
})
})
describe('coinanimation', () => {
it('sets the state of coinanimation', () => {
const state = { coinanimation: true }
coinanimation(state, false)
expect(state.coinanimation).toEqual(false)
})
})
describe('newsletterState', () => {
it('sets the state of newsletterState', () => {
const state = { newsletterState: null }
@ -134,7 +125,6 @@ describe('Vuex store', () => {
language: 'de',
firstName: 'Peter',
lastName: 'Lustig',
coinanimation: false,
klickTipp: {
newsletterState: true,
},
@ -145,7 +135,7 @@ describe('Vuex store', () => {
it('calls nine commits', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenCalledTimes(9)
expect(commit).toHaveBeenCalledTimes(8)
})
it('commits email', () => {
@ -168,29 +158,24 @@ describe('Vuex store', () => {
expect(commit).toHaveBeenNthCalledWith(4, 'lastName', 'Lustig')
})
it('commits coinanimation', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(5, 'coinanimation', false)
})
it('commits newsletterState', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(6, 'newsletterState', true)
expect(commit).toHaveBeenNthCalledWith(5, 'newsletterState', true)
})
it('commits hasElopage', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(7, 'hasElopage', false)
expect(commit).toHaveBeenNthCalledWith(6, 'hasElopage', false)
})
it('commits publisherId', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(8, 'publisherId', 1234)
expect(commit).toHaveBeenNthCalledWith(7, 'publisherId', 1234)
})
it('commits isAdmin', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(9, 'isAdmin', true)
expect(commit).toHaveBeenNthCalledWith(8, 'isAdmin', true)
})
})
@ -200,7 +185,7 @@ describe('Vuex store', () => {
it('calls nine commits', () => {
logout({ commit, state })
expect(commit).toHaveBeenCalledTimes(9)
expect(commit).toHaveBeenCalledTimes(8)
})
it('commits token', () => {
@ -223,29 +208,24 @@ describe('Vuex store', () => {
expect(commit).toHaveBeenNthCalledWith(4, 'lastName', '')
})
it('commits coinanimation', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(5, 'coinanimation', true)
})
it('commits newsletterState', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(6, 'newsletterState', null)
expect(commit).toHaveBeenNthCalledWith(5, 'newsletterState', null)
})
it('commits hasElopage', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(7, 'hasElopage', false)
expect(commit).toHaveBeenNthCalledWith(6, 'hasElopage', false)
})
it('commits publisherId', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(8, 'publisherId', null)
expect(commit).toHaveBeenNthCalledWith(7, 'publisherId', null)
})
it('commits isAdmin', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(9, 'isAdmin', false)
expect(commit).toHaveBeenNthCalledWith(8, 'isAdmin', false)
})
// how to get this working?

View File

@ -5,7 +5,7 @@
"main": "index.js",
"repository": "git@github.com:gradido/gradido.git",
"author": "Ulf Gebhardt <ulf.gebhardt@webcraft-media.de>",
"license": "MIT",
"license": "Apache-2.0",
"scripts": {
"release": "scripts/release.sh"
},