Merge pull request #1946 from gradido/1883-remove-the-animated-coins-in-the-profile-settings

1883 remove the animated coins in the profile settings
This commit is contained in:
Alexander Friedland 2022-05-30 11:32:01 +02:00 committed by GitHub
commit afde83e2cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 17 additions and 320 deletions

View File

@ -19,7 +19,4 @@ export default class UpdateUserInfosArgs {
@Field({ nullable: true }) @Field({ nullable: true })
passwordNew?: string 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.language = user.language
this.publisherId = user.publisherId this.publisherId = user.publisherId
this.isAdmin = user.isAdmin this.isAdmin = user.isAdmin
// TODO
this.coinanimation = null
this.klickTipp = null this.klickTipp = null
this.hasElopage = null this.hasElopage = null
} }
@ -61,11 +59,6 @@ export class User {
@Field(() => Date, { nullable: true }) @Field(() => Date, { nullable: true })
isAdmin: Date | null 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 }) @Field(() => KlickTipp, { nullable: true })
klickTipp: KlickTipp | null klickTipp: KlickTipp | null

View File

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

View File

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

View File

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

View File

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

View File

@ -1,33 +1,22 @@
import { EntityRepository, Repository } from '@dbTools/typeorm' import { EntityRepository, Repository } from '@dbTools/typeorm'
import { UserSetting } from '@entity/UserSetting' import { UserSetting } from '@entity/UserSetting'
import { Setting } from '@enum/Setting'
import { isStringBoolean } from '@/util/validate' import { isStringBoolean } from '@/util/validate'
@EntityRepository(UserSetting) @EntityRepository(UserSetting)
export class UserSettingRepository extends Repository<UserSetting> { export class UserSettingRepository extends Repository<UserSetting> {
async setOrUpdate(userId: number, key: Setting, value: string): Promise<UserSetting> { async setOrUpdate(userId: number, value: string): Promise<UserSetting> {
switch (key) { let entity = await this.findOne({ userId: userId })
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 })
if (!entity) { if (!entity) {
entity = new UserSetting() entity = new UserSetting()
entity.userId = userId entity.userId = userId
entity.key = key
} }
entity.value = value entity.value = value
return this.save(entity) return this.save(entity)
} }
async readBoolean(userId: number, key: Setting): Promise<boolean> { async readBoolean(userId: number): Promise<boolean> {
const entity = await this.findOne({ userId: userId, key: key }) const entity = await this.findOne({ userId: userId })
if (!entity || !isStringBoolean(entity.value)) { if (!entity || !isStringBoolean(entity.value)) {
return true return true
} }

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

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

View File

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

View File

@ -186,11 +186,6 @@
"send_gdd": "GDD versenden", "send_gdd": "GDD versenden",
"send_per_link": "GDD versenden per Link", "send_per_link": "GDD versenden per Link",
"settings": { "settings": {
"coinanimation": {
"coinanimation": "Münzanimation",
"False": "Münzanimation ausgeschaltet",
"True": "Münzanimation eingeschaltet"
},
"language": { "language": {
"changeLanguage": "Sprache ändern", "changeLanguage": "Sprache ändern",
"de": "Deutsch", "de": "Deutsch",

View File

@ -186,11 +186,6 @@
"send_gdd": "GDD send", "send_gdd": "GDD send",
"send_per_link": "GDD send via link", "send_per_link": "GDD send via link",
"settings": { "settings": {
"coinanimation": {
"coinanimation": "Coin animation",
"False": "Coin animation disabled",
"True": "Coin animation enabled"
},
"language": { "language": {
"changeLanguage": "Change language", "changeLanguage": "Change language",
"de": "Deutsch", "de": "Deutsch",

View File

@ -38,9 +38,5 @@ describe('Profile', () => {
it('has a user change newsletter form', () => { it('has a user change newsletter form', () => {
expect(wrapper.findComponent({ name: 'UserNewsletter' }).exists()).toBeTruthy() 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 /> <user-language />
<hr /> <hr />
<user-newsletter /> <user-newsletter />
<hr />
<user-coin-animation />
</div> </div>
</template> </template>
<script> <script>
@ -18,7 +16,6 @@ import UserData from '@/components/UserSettings/UserData.vue'
import UserPassword from '@/components/UserSettings/UserPassword.vue' import UserPassword from '@/components/UserSettings/UserPassword.vue'
import UserLanguage from '@/components/UserSettings/UserLanguage.vue' import UserLanguage from '@/components/UserSettings/UserLanguage.vue'
import UserNewsletter from '@/components/UserSettings/UserNewsletter.vue' import UserNewsletter from '@/components/UserSettings/UserNewsletter.vue'
import UserCoinAnimation from '@/components/UserSettings/UserCoinAnimation.vue'
export default { export default {
name: 'Profile', name: 'Profile',
@ -28,7 +25,6 @@ export default {
UserPassword, UserPassword,
UserLanguage, UserLanguage,
UserNewsletter, UserNewsletter,
UserCoinAnimation,
}, },
props: { props: {
balance: { type: Number, default: 0 }, balance: { type: Number, default: 0 },

View File

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

View File

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