mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge pull request #813 from gradido/585-Coin-animation-on-and-off-switchable
585 coin animation on and off switchable
This commit is contained in:
commit
fc54663cef
2
backend/.gitignore
vendored
2
backend/.gitignore
vendored
@ -1,7 +1,7 @@
|
||||
/node_modules/
|
||||
/.env
|
||||
/build/
|
||||
|
||||
package-json.lock
|
||||
coverage
|
||||
# emacs
|
||||
*~
|
||||
7120
backend/package-lock.json
generated
Normal file
7120
backend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,9 +2,6 @@ import { ArgsType, Field } from 'type-graphql'
|
||||
|
||||
@ArgsType()
|
||||
export default class UpdateUserInfosArgs {
|
||||
@Field(() => String)
|
||||
email!: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
firstName?: string
|
||||
|
||||
@ -28,4 +25,7 @@ export default class UpdateUserInfosArgs {
|
||||
|
||||
@Field({ nullable: true })
|
||||
passwordNew?: string
|
||||
|
||||
@Field({ nullable: true })
|
||||
coinanimation?: boolean
|
||||
}
|
||||
|
||||
5
backend/src/graphql/enum/Setting.ts
Normal file
5
backend/src/graphql/enum/Setting.ts
Normal file
@ -0,0 +1,5 @@
|
||||
enum Setting {
|
||||
COIN_ANIMATION = 'coinanimation',
|
||||
}
|
||||
|
||||
export { Setting }
|
||||
@ -69,6 +69,9 @@ export class User {
|
||||
@Field(() => Number)
|
||||
publisherId: number
|
||||
|
||||
@Field(() => Boolean)
|
||||
coinanimation: boolean
|
||||
|
||||
@Field(() => KlickTipp)
|
||||
klickTipp: KlickTipp
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ export class GdtResolver {
|
||||
if (!resultGDT.success) {
|
||||
throw new Error(resultGDT.data)
|
||||
}
|
||||
|
||||
return new GdtEntryList(resultGDT.data)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,6 +20,10 @@ import {
|
||||
klicktippNewsletterStateMiddleware,
|
||||
} from '../../middleware/klicktippMiddleware'
|
||||
import { CheckEmailResponse } from '../models/CheckEmailResponse'
|
||||
import { getCustomRepository } from 'typeorm'
|
||||
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
|
||||
import { Setting } from '../../graphql/enum/Setting'
|
||||
import { UserRepository } from '../../typeorm/repository/User'
|
||||
|
||||
@Resolver()
|
||||
export class UserResolver {
|
||||
@ -38,8 +42,19 @@ export class UserResolver {
|
||||
key: 'token',
|
||||
value: encode(result.data.session_id, result.data.user.public_hex),
|
||||
})
|
||||
const user = new User(result.data.user)
|
||||
// read additional settings from settings table
|
||||
const userRepository = getCustomRepository(UserRepository)
|
||||
const userEntity = await userRepository.findByPubkeyHex(user.pubkey)
|
||||
|
||||
return new User(result.data.user)
|
||||
const userSettingRepository = getCustomRepository(UserSettingRepository)
|
||||
const coinanimation = await userSettingRepository
|
||||
.readBoolean(userEntity.id, Setting.COIN_ANIMATION)
|
||||
.catch((error) => {
|
||||
throw new Error(error)
|
||||
})
|
||||
user.coinanimation = coinanimation
|
||||
return user
|
||||
}
|
||||
|
||||
@Query(() => LoginViaVerificationCode)
|
||||
@ -128,7 +143,6 @@ export class UserResolver {
|
||||
async updateUserInfos(
|
||||
@Args()
|
||||
{
|
||||
email,
|
||||
firstName,
|
||||
lastName,
|
||||
description,
|
||||
@ -137,12 +151,12 @@ export class UserResolver {
|
||||
publisherId,
|
||||
password,
|
||||
passwordNew,
|
||||
coinanimation,
|
||||
}: UpdateUserInfosArgs,
|
||||
@Ctx() context: any,
|
||||
): Promise<UpdateUserInfosResponse> {
|
||||
const payload = {
|
||||
session_id: context.sessionId,
|
||||
email,
|
||||
update: {
|
||||
'User.first_name': firstName || undefined,
|
||||
'User.last_name': lastName || undefined,
|
||||
@ -154,9 +168,42 @@ export class UserResolver {
|
||||
'User.password_old': password || undefined,
|
||||
},
|
||||
}
|
||||
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
|
||||
if (!result.success) throw new Error(result.data)
|
||||
return new UpdateUserInfosResponse(result.data)
|
||||
let response: UpdateUserInfosResponse | undefined
|
||||
if (
|
||||
firstName ||
|
||||
lastName ||
|
||||
description ||
|
||||
username ||
|
||||
language ||
|
||||
publisherId ||
|
||||
passwordNew ||
|
||||
password
|
||||
) {
|
||||
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
|
||||
if (!result.success) throw new Error(result.data)
|
||||
response = new UpdateUserInfosResponse(result.data)
|
||||
}
|
||||
if (coinanimation !== undefined) {
|
||||
// load user and balance
|
||||
const userRepository = getCustomRepository(UserRepository)
|
||||
const userEntity = await userRepository.findByPubkeyHex(context.pubKey)
|
||||
const userSettingRepository = getCustomRepository(UserSettingRepository)
|
||||
userSettingRepository
|
||||
.setOrUpdate(userEntity.id, Setting.COIN_ANIMATION, coinanimation.toString())
|
||||
.catch((error) => {
|
||||
throw new Error(error)
|
||||
})
|
||||
|
||||
if (!response) {
|
||||
response = new UpdateUserInfosResponse({ valid_values: 1 })
|
||||
} else {
|
||||
response.validValues++
|
||||
}
|
||||
}
|
||||
if (!response) {
|
||||
throw new Error('no valid response')
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
@Query(() => CheckUsernameResponse)
|
||||
|
||||
@ -22,7 +22,7 @@ import schema from './graphql/schema'
|
||||
// TODO implement
|
||||
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
||||
|
||||
const DB_VERSION = '0001-init_db'
|
||||
const DB_VERSION = '0002-add_settings'
|
||||
|
||||
async function main() {
|
||||
// open mysql connection
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
||||
|
||||
// import { Group } from "./Group"
|
||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
|
||||
import { UserSetting } from './UserSetting'
|
||||
|
||||
// Moriz: I do not like the idea of having two user tables
|
||||
@Entity('state_users')
|
||||
@ -28,4 +27,7 @@ export class User extends BaseEntity {
|
||||
|
||||
@Column()
|
||||
disabled: boolean
|
||||
|
||||
@OneToMany(() => UserSetting, (userSetting) => userSetting.user)
|
||||
settings: UserSetting[]
|
||||
}
|
||||
|
||||
20
backend/src/typeorm/entity/UserSetting.ts
Normal file
20
backend/src/typeorm/entity/UserSetting.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
|
||||
import { User } from './User'
|
||||
|
||||
@Entity()
|
||||
export class UserSetting extends BaseEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
|
||||
@Column()
|
||||
userId: number
|
||||
|
||||
@ManyToOne(() => User, (user) => user.settings)
|
||||
user: User
|
||||
|
||||
@Column()
|
||||
key: string
|
||||
|
||||
@Column()
|
||||
value: string
|
||||
}
|
||||
36
backend/src/typeorm/repository/UserSettingRepository.ts
Normal file
36
backend/src/typeorm/repository/UserSettingRepository.ts
Normal file
@ -0,0 +1,36 @@
|
||||
import { EntityRepository, Repository } from 'typeorm'
|
||||
import { UserSetting } from '../entity/UserSetting'
|
||||
import { Setting } from '../../graphql/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 })
|
||||
|
||||
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 })
|
||||
if (!entity || !isStringBoolean(entity.value)) {
|
||||
return true
|
||||
}
|
||||
return entity.value.toLowerCase() === 'true'
|
||||
}
|
||||
}
|
||||
9
backend/src/util/validate.ts
Normal file
9
backend/src/util/validate.ts
Normal file
@ -0,0 +1,9 @@
|
||||
function isStringBoolean(value: string): boolean {
|
||||
const lowerValue = value.toLowerCase()
|
||||
if (lowerValue === 'true' || lowerValue === 'false') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export { isStringBoolean }
|
||||
1112
backend/yarn.lock
1112
backend/yarn.lock
File diff suppressed because it is too large
Load Diff
26
database/migrations/0002-add_settings.ts
Normal file
26
database/migrations/0002-add_settings.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/* FIRST MIGRATION
|
||||
*
|
||||
* This migration is special since it takes into account that
|
||||
* the database can be setup already but also may not be.
|
||||
* Therefore you will find all `CREATE TABLE` statements with
|
||||
* a `IF NOT EXISTS`, all `INSERT` with an `IGNORE` and in the
|
||||
* downgrade function all `DROP TABLE` with a `IF EXISTS`.
|
||||
* This ensures compatibility for existing or non-existing
|
||||
* databases.
|
||||
*/
|
||||
|
||||
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||
await queryFn(`
|
||||
CREATE TABLE IF NOT EXISTS \`user_setting\` (
|
||||
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
\`userId\` int(11) NOT NULL,
|
||||
\`key\` varchar(255) NOT NULL,
|
||||
\`value\` varchar(255) NOT NULL,
|
||||
PRIMARY KEY (\`id\`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`)
|
||||
}
|
||||
|
||||
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||
// write downgrade logic as parameter of queryFn
|
||||
await queryFn(`DROP TABLE IF EXISTS \`user_setting\`;`)
|
||||
}
|
||||
@ -222,7 +222,6 @@ with:
|
||||
```json
|
||||
{
|
||||
"session_id": -127182,
|
||||
"email": "max.musterman@gmail.de",
|
||||
"update": {
|
||||
"User.first_name": "Max",
|
||||
"User.last_name" : "Musterman",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="app" class="font-sans text-gray-800">
|
||||
<div class="">
|
||||
<particles-bg type="custom" :config="config" :bg="true" />
|
||||
<particles-bg v-if="$store.state.coinanimation" type="custom" :config="config" :bg="true" />
|
||||
<component :is="$route.meta.requiresAuth ? 'DashboardLayout' : 'AuthLayoutGDD'" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
</b-row>
|
||||
|
||||
<!-- Message-->
|
||||
<b-row v-if="comment && gdtEntryType !== 7">
|
||||
<b-row v-if="comment && !isGlobalModificator">
|
||||
<b-col cols="6" class="text-right">
|
||||
{{ $t('form.memo') }}
|
||||
</b-col>
|
||||
@ -72,6 +72,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import TransactionCollapse from './TransactionCollapse.vue'
|
||||
import { GdtEntryType } from '../graphql/enums'
|
||||
|
||||
export default {
|
||||
name: 'Transaction',
|
||||
@ -82,42 +83,52 @@ export default {
|
||||
amount: { type: Number },
|
||||
date: { type: String },
|
||||
comment: { type: String },
|
||||
gdtEntryType: { type: Number, default: 1 },
|
||||
gdtEntryType: { type: String, default: GdtEntryType.FORM },
|
||||
factor: { type: Number },
|
||||
gdt: { type: Number },
|
||||
},
|
||||
computed: {
|
||||
isGlobalModificator: function () {
|
||||
return this.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getLinesByType(givenType) {
|
||||
if (givenType === 2 || givenType === 3 || givenType === 5 || givenType === 6) givenType = 1
|
||||
|
||||
const linesByType = {
|
||||
1: {
|
||||
icon: 'heart',
|
||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||
description: this.$t('gdt.contribution'),
|
||||
descriptiontext: this.$n(this.amount, 'decimal') + ' €',
|
||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||
},
|
||||
4: {
|
||||
icon: 'person-check',
|
||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||
description: this.$t('gdt.recruited-member'),
|
||||
descriptiontext: '5%',
|
||||
credittext: this.$n(this.amount, 'decimal') + ' GDT',
|
||||
},
|
||||
7: {
|
||||
icon: 'gift',
|
||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||
description: this.$t('gdt.gdt-received'),
|
||||
descriptiontext: this.comment,
|
||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||
},
|
||||
switch (givenType) {
|
||||
case GdtEntryType.FORM:
|
||||
case GdtEntryType.CVS:
|
||||
case GdtEntryType.ELOPAGE:
|
||||
case GdtEntryType.DIGISTORE:
|
||||
case GdtEntryType.CVS2: {
|
||||
return {
|
||||
icon: 'heart',
|
||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||
description: this.$t('gdt.contribution'),
|
||||
descriptiontext: this.$n(this.amount, 'decimal') + ' €',
|
||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.ELOPAGE_PUBLISHER: {
|
||||
return {
|
||||
icon: 'person-check',
|
||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||
description: this.$t('gdt.recruited-member'),
|
||||
descriptiontext: '5%',
|
||||
credittext: this.$n(this.amount, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.GLOBAL_MODIFICATOR: {
|
||||
return {
|
||||
icon: 'gift',
|
||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||
description: this.$t('gdt.gdt-received'),
|
||||
descriptiontext: this.comment,
|
||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error('no lines for this type: ' + givenType)
|
||||
}
|
||||
|
||||
const type = linesByType[givenType]
|
||||
|
||||
if (type) return type
|
||||
throw new Error('no lines for this type: ' + givenType)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import TransactionCollapse from './TransactionCollapse'
|
||||
import { GdtEntryType } from '../graphql/enums'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
@ -15,13 +16,13 @@ describe('TransactionCollapse', () => {
|
||||
return mount(TransactionCollapse, { localVue, mocks, propsData })
|
||||
}
|
||||
|
||||
describe('mount with gdtEntryType: 1', () => {
|
||||
describe('mount with gdtEntryType: FORM', () => {
|
||||
beforeEach(() => {
|
||||
const propsData = {
|
||||
amount: 100,
|
||||
gdt: 110,
|
||||
factor: 22,
|
||||
gdtEntryType: 1,
|
||||
gdtEntryType: GdtEntryType.FORM,
|
||||
}
|
||||
|
||||
wrapper = Wrapper(propsData)
|
||||
@ -31,8 +32,8 @@ describe('TransactionCollapse', () => {
|
||||
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('checks the prop gdtEntryType ', () => {
|
||||
expect(wrapper.props().gdtEntryType).toBe(1)
|
||||
it('checks the prop gdtEntryType', () => {
|
||||
expect(wrapper.props().gdtEntryType).toBe('FORM')
|
||||
})
|
||||
|
||||
it('renders the component collapse-header', () => {
|
||||
@ -60,13 +61,13 @@ describe('TransactionCollapse', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('mount with gdtEntryType: 7', () => {
|
||||
describe('mount with gdtEntryType: GLOBAL_MODIFICATOR', () => {
|
||||
beforeEach(() => {
|
||||
const propsData = {
|
||||
amount: 100,
|
||||
gdt: 2200,
|
||||
factor: 22,
|
||||
gdtEntryType: 7,
|
||||
gdtEntryType: GdtEntryType.GLOBAL_MODIFICATOR,
|
||||
}
|
||||
|
||||
wrapper = Wrapper(propsData)
|
||||
@ -76,8 +77,8 @@ describe('TransactionCollapse', () => {
|
||||
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('checks the prop gdtEntryType ', () => {
|
||||
expect(wrapper.props().gdtEntryType).toBe(7)
|
||||
it('checks the prop gdtEntryType', () => {
|
||||
expect(wrapper.props().gdtEntryType).toBe('GLOBAL_MODIFICATOR')
|
||||
})
|
||||
|
||||
it('renders the component collapse-header', () => {
|
||||
@ -105,13 +106,13 @@ describe('TransactionCollapse', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('mount with gdtEntryType: 4', () => {
|
||||
describe('mount with gdtEntryType: ELOPAGE_PUBLISHER', () => {
|
||||
beforeEach(() => {
|
||||
const propsData = {
|
||||
amount: 100,
|
||||
gdt: 2200,
|
||||
factor: 22,
|
||||
gdtEntryType: 4,
|
||||
gdtEntryType: GdtEntryType.ELOPAGE_PUBLISHER,
|
||||
}
|
||||
|
||||
wrapper = Wrapper(propsData)
|
||||
@ -121,8 +122,8 @@ describe('TransactionCollapse', () => {
|
||||
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('checks the prop gdtEntryType ', () => {
|
||||
expect(wrapper.props().gdtEntryType).toBe(4)
|
||||
it('checks the prop gdtEntryType', () => {
|
||||
expect(wrapper.props().gdtEntryType).toBe('ELOPAGE_PUBLISHER')
|
||||
})
|
||||
|
||||
it('renders the component collapse-header', () => {
|
||||
|
||||
@ -23,58 +23,65 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { GdtEntryType } from '../graphql/enums'
|
||||
|
||||
export default {
|
||||
name: 'TransactionCollapse',
|
||||
props: {
|
||||
amount: { type: Number },
|
||||
gdtEntryType: { type: Number, default: 1 },
|
||||
gdtEntryType: { type: String, default: GdtEntryType.FORM },
|
||||
factor: { type: Number },
|
||||
gdt: { type: Number },
|
||||
},
|
||||
methods: {
|
||||
getLinesByType(givenType) {
|
||||
if (givenType === 2 || givenType === 3 || givenType === 5 || givenType === 6) givenType = 1
|
||||
|
||||
const linesByType = {
|
||||
1: {
|
||||
headline: this.$t('gdt.calculation'),
|
||||
first: this.$t('gdt.factor'),
|
||||
firstMath: this.factor + ' GDT pro €',
|
||||
second: this.$t('gdt.formula'),
|
||||
secondMath:
|
||||
this.$n(this.amount, 'decimal') +
|
||||
' € * ' +
|
||||
this.factor +
|
||||
' GDT / € = ' +
|
||||
this.$n(this.gdt, 'decimal') +
|
||||
' GDT',
|
||||
},
|
||||
4: {
|
||||
headline: this.$t('gdt.publisher'),
|
||||
first: null,
|
||||
firstMath: null,
|
||||
second: null,
|
||||
secondMath: null,
|
||||
},
|
||||
7: {
|
||||
headline: this.$t('gdt.conversion-gdt-euro'),
|
||||
first: this.$t('gdt.raise'),
|
||||
firstMath: this.factor * 100 + ' % ',
|
||||
second: this.$t('gdt.conversion'),
|
||||
secondMath:
|
||||
this.$n(this.amount, 'decimal') +
|
||||
' GDT * ' +
|
||||
this.factor * 100 +
|
||||
' % = ' +
|
||||
this.$n(this.gdt, 'decimal') +
|
||||
' GDT',
|
||||
},
|
||||
switch (givenType) {
|
||||
case GdtEntryType.FORM:
|
||||
case GdtEntryType.CVS:
|
||||
case GdtEntryType.ELOPAGE:
|
||||
case GdtEntryType.DIGISTORE:
|
||||
case GdtEntryType.CVS2: {
|
||||
return {
|
||||
headline: this.$t('gdt.calculation'),
|
||||
first: this.$t('gdt.factor'),
|
||||
firstMath: this.factor + ' GDT pro €',
|
||||
second: this.$t('gdt.formula'),
|
||||
secondMath:
|
||||
this.$n(this.amount, 'decimal') +
|
||||
' € * ' +
|
||||
this.factor +
|
||||
' GDT / € = ' +
|
||||
this.$n(this.gdt, 'decimal') +
|
||||
' GDT',
|
||||
}
|
||||
}
|
||||
case GdtEntryType.ELOPAGE_PUBLISHER: {
|
||||
return {
|
||||
headline: this.$t('gdt.publisher'),
|
||||
first: null,
|
||||
firstMath: null,
|
||||
second: null,
|
||||
secondMath: null,
|
||||
}
|
||||
}
|
||||
case GdtEntryType.GLOBAL_MODIFICATOR: {
|
||||
return {
|
||||
headline: this.$t('gdt.conversion-gdt-euro'),
|
||||
first: this.$t('gdt.raise'),
|
||||
firstMath: this.factor * 100 + ' % ',
|
||||
second: this.$t('gdt.conversion'),
|
||||
secondMath:
|
||||
this.$n(this.amount, 'decimal') +
|
||||
' GDT * ' +
|
||||
this.factor * 100 +
|
||||
' % = ' +
|
||||
this.$n(this.gdt, 'decimal') +
|
||||
' GDT',
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw new Error('no additional transaction info for this type: ' + givenType)
|
||||
}
|
||||
|
||||
const type = linesByType[givenType]
|
||||
|
||||
if (type) return type
|
||||
throw new Error('no additional transaction info for this type: ' + givenType)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
9
frontend/src/graphql/enums.js
Normal file
9
frontend/src/graphql/enums.js
Normal file
@ -0,0 +1,9 @@
|
||||
export const GdtEntryType = {
|
||||
FORM: 'FORM',
|
||||
CVS: 'CVS',
|
||||
ELOPAGE: 'ELOPAGE',
|
||||
ELOPAGE_PUBLISHER: 'ELOPAGE_PUBLISHER',
|
||||
DIGISTORE: 'DIGISTORE',
|
||||
CVS2: 'CVS2',
|
||||
GLOBAL_MODIFICATOR: 'GLOBAL_MODIFICATOR',
|
||||
}
|
||||
@ -20,7 +20,6 @@ export const resetPassword = gql`
|
||||
|
||||
export const updateUserInfos = gql`
|
||||
mutation(
|
||||
$email: String!
|
||||
$firstName: String
|
||||
$lastName: String
|
||||
$description: String
|
||||
@ -28,9 +27,9 @@ export const updateUserInfos = gql`
|
||||
$password: String
|
||||
$passwordNew: String
|
||||
$locale: String
|
||||
$coinanimation: Boolean
|
||||
) {
|
||||
updateUserInfos(
|
||||
email: $email
|
||||
firstName: $firstName
|
||||
lastName: $lastName
|
||||
description: $description
|
||||
@ -38,6 +37,7 @@ export const updateUserInfos = gql`
|
||||
password: $password
|
||||
passwordNew: $passwordNew
|
||||
language: $locale
|
||||
coinanimation: $coinanimation
|
||||
) {
|
||||
validValues
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ export const login = gql`
|
||||
lastName
|
||||
language
|
||||
description
|
||||
coinanimation
|
||||
klickTipp {
|
||||
newsletterState
|
||||
}
|
||||
|
||||
@ -105,6 +105,11 @@
|
||||
"privacy_policy": "Datenschutzerklärung",
|
||||
"send": "Senden",
|
||||
"settings": {
|
||||
"coinanimation": {
|
||||
"coinanimation": "Münzanimation",
|
||||
"False": "Münzanimation ausgeschaltet",
|
||||
"True": "Münzanimation eingeschaltet"
|
||||
},
|
||||
"language": {
|
||||
"changeLanguage": "Sprache ändern",
|
||||
"de": "Deutsch",
|
||||
|
||||
@ -105,6 +105,11 @@
|
||||
"privacy_policy": "Privacy policy",
|
||||
"send": "Send",
|
||||
"settings": {
|
||||
"coinanimation": {
|
||||
"coinanimation": "Coin animation",
|
||||
"False": "Coin animation disabled",
|
||||
"True": "Coin animation enabled"
|
||||
},
|
||||
"language": {
|
||||
"changeLanguage": "Change language",
|
||||
"de": "Deutsch",
|
||||
|
||||
@ -67,6 +67,7 @@ export const store = new Vuex.Store({
|
||||
username: '',
|
||||
description: '',
|
||||
token: null,
|
||||
coinanimation: true,
|
||||
newsletterState: null,
|
||||
},
|
||||
getters: {},
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { GdtEntryType } from '../../../graphql/enums'
|
||||
import GdtTransactionList from './GdtTransactionList'
|
||||
|
||||
const localVue = global.localVue
|
||||
@ -14,7 +15,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
||||
factor: 17,
|
||||
comment: '',
|
||||
date: '2021-05-02T17:20:11+00:00',
|
||||
gdtEntryType: 1,
|
||||
gdtEntryType: GdtEntryType.FORM,
|
||||
},
|
||||
{
|
||||
amount: 1810,
|
||||
@ -22,7 +23,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
||||
factor: 0.2,
|
||||
comment: 'Dezember 20',
|
||||
date: '2020-12-31T12:00:00+00:00',
|
||||
gdtEntryType: 7,
|
||||
gdtEntryType: GdtEntryType.GLOBAL_MODIFICATOR,
|
||||
},
|
||||
{
|
||||
amount: 100,
|
||||
@ -30,7 +31,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
||||
factor: 17,
|
||||
comment: '',
|
||||
date: '2020-05-07T17:00:00+00:00',
|
||||
gdtEntryType: 1,
|
||||
gdtEntryType: GdtEntryType.FORM,
|
||||
},
|
||||
{
|
||||
amount: 100,
|
||||
@ -38,7 +39,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
||||
factor: 22,
|
||||
comment: '',
|
||||
date: '2020-04-10T13:28:00+00:00',
|
||||
gdtEntryType: 4,
|
||||
gdtEntryType: GdtEntryType.ELOPAGE_PUBLISHER,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import UserCardCoinAnimation from './UserCard_CoinAnimation'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
const mockAPIcall = jest.fn()
|
||||
|
||||
const toastErrorMock = jest.fn()
|
||||
const toastSuccessMock = jest.fn()
|
||||
const storeCommitMock = jest.fn()
|
||||
|
||||
describe('UserCard_CoinAnimation', () => {
|
||||
let wrapper
|
||||
|
||||
const mocks = {
|
||||
$t: jest.fn((t) => t),
|
||||
$store: {
|
||||
state: {
|
||||
language: 'de',
|
||||
},
|
||||
commit: storeCommitMock,
|
||||
},
|
||||
$toasted: {
|
||||
success: toastSuccessMock,
|
||||
error: toastErrorMock,
|
||||
},
|
||||
$apollo: {
|
||||
query: mockAPIcall,
|
||||
},
|
||||
}
|
||||
|
||||
const Wrapper = () => {
|
||||
return mount(UserCardCoinAnimation, { localVue, mocks })
|
||||
}
|
||||
|
||||
describe('mount', () => {
|
||||
beforeEach(() => {
|
||||
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()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,68 @@
|
||||
<template>
|
||||
<b-card
|
||||
id="formusercoinanimation"
|
||||
class="bg-transparent"
|
||||
style="background-color: #ebebeba3 !important; border-radius: 0px"
|
||||
>
|
||||
<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: 'FormUserCoinAnimation',
|
||||
data() {
|
||||
return {
|
||||
CoinAnimationStatus: true,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.CoinAnimationStatus = this.$store.state.coinanimation /* existiert noch nicht im store */
|
||||
},
|
||||
methods: {
|
||||
async onSubmit() {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: updateUserInfos,
|
||||
variables: {
|
||||
coinanimation: this.CoinAnimationStatus,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
this.$store.state.coinanimation = this.CoinAnimationStatus
|
||||
this.$toasted.success(
|
||||
this.CoinAnimationStatus
|
||||
? this.$t('settings.coinanimation.True')
|
||||
: this.$t('settings.coinanimation.False'),
|
||||
)
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$toasted.error(error.message)
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -8,6 +8,8 @@
|
||||
<form-user-language />
|
||||
<hr />
|
||||
<form-user-newsletter />
|
||||
<hr />
|
||||
<form-user-coin-animation />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@ -16,6 +18,7 @@ import FormUserData from './UserProfile/UserCard_FormUserData.vue'
|
||||
import FormUserPasswort from './UserProfile/UserCard_FormUserPasswort.vue'
|
||||
import FormUserLanguage from './UserProfile/UserCard_Language.vue'
|
||||
import FormUserNewsletter from './UserProfile/UserCard_Newsletter.vue'
|
||||
import FormUserCoinAnimation from './UserProfile/UserCard_CoinAnimation.vue'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -24,6 +27,7 @@ export default {
|
||||
FormUserPasswort,
|
||||
FormUserLanguage,
|
||||
FormUserNewsletter,
|
||||
FormUserCoinAnimation,
|
||||
},
|
||||
props: {
|
||||
balance: { type: Number, default: 0 },
|
||||
|
||||
@ -15,7 +15,6 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
|
||||
{
|
||||
/*
|
||||
'session_id' => $session_id,
|
||||
'email' => $email,
|
||||
'update' => ['User.first_name' => 'first_name', 'User.last_name' => 'last_name', 'User.disabled' => 0|1, 'User.language' => 'de']
|
||||
*/
|
||||
// incoming
|
||||
@ -34,8 +33,7 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
|
||||
/// not available for the given type.
|
||||
/// Throws InvalidAccessException if Var is empty.
|
||||
try {
|
||||
paramJsonObject->get("email").convert(email);
|
||||
|
||||
|
||||
auto session_id_obj = paramJsonObject->get("session_id");
|
||||
if (!session_id_obj.isEmpty()) {
|
||||
session_id_obj.convert(session_id);
|
||||
@ -66,10 +64,7 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
|
||||
}
|
||||
auto user = mSession->getNewUser();
|
||||
auto user_model = user->getModel();
|
||||
if (user_model->getEmail() != email) {
|
||||
return customStateError("not same", "email don't belong to logged in user");
|
||||
}
|
||||
|
||||
|
||||
Poco::JSON::Object* result = new Poco::JSON::Object;
|
||||
result->set("state", "success");
|
||||
Poco::JSON::Array jsonErrorsArray;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user