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/
|
/node_modules/
|
||||||
/.env
|
/.env
|
||||||
/build/
|
/build/
|
||||||
|
package-json.lock
|
||||||
coverage
|
coverage
|
||||||
# emacs
|
# 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()
|
@ArgsType()
|
||||||
export default class UpdateUserInfosArgs {
|
export default class UpdateUserInfosArgs {
|
||||||
@Field(() => String)
|
|
||||||
email!: string
|
|
||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
firstName?: string
|
firstName?: string
|
||||||
|
|
||||||
@ -28,4 +25,7 @@ export default class UpdateUserInfosArgs {
|
|||||||
|
|
||||||
@Field({ nullable: true })
|
@Field({ nullable: true })
|
||||||
passwordNew?: string
|
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)
|
@Field(() => Number)
|
||||||
publisherId: number
|
publisherId: number
|
||||||
|
|
||||||
|
@Field(() => Boolean)
|
||||||
|
coinanimation: boolean
|
||||||
|
|
||||||
@Field(() => KlickTipp)
|
@Field(() => KlickTipp)
|
||||||
klickTipp: KlickTipp
|
klickTipp: KlickTipp
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,6 @@ export class GdtResolver {
|
|||||||
if (!resultGDT.success) {
|
if (!resultGDT.success) {
|
||||||
throw new Error(resultGDT.data)
|
throw new Error(resultGDT.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GdtEntryList(resultGDT.data)
|
return new GdtEntryList(resultGDT.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,10 @@ import {
|
|||||||
klicktippNewsletterStateMiddleware,
|
klicktippNewsletterStateMiddleware,
|
||||||
} from '../../middleware/klicktippMiddleware'
|
} from '../../middleware/klicktippMiddleware'
|
||||||
import { CheckEmailResponse } from '../models/CheckEmailResponse'
|
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()
|
@Resolver()
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
@ -38,8 +42,19 @@ export class UserResolver {
|
|||||||
key: 'token',
|
key: 'token',
|
||||||
value: encode(result.data.session_id, result.data.user.public_hex),
|
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)
|
@Query(() => LoginViaVerificationCode)
|
||||||
@ -128,7 +143,6 @@ export class UserResolver {
|
|||||||
async updateUserInfos(
|
async updateUserInfos(
|
||||||
@Args()
|
@Args()
|
||||||
{
|
{
|
||||||
email,
|
|
||||||
firstName,
|
firstName,
|
||||||
lastName,
|
lastName,
|
||||||
description,
|
description,
|
||||||
@ -137,12 +151,12 @@ export class UserResolver {
|
|||||||
publisherId,
|
publisherId,
|
||||||
password,
|
password,
|
||||||
passwordNew,
|
passwordNew,
|
||||||
|
coinanimation,
|
||||||
}: UpdateUserInfosArgs,
|
}: UpdateUserInfosArgs,
|
||||||
@Ctx() context: any,
|
@Ctx() context: any,
|
||||||
): Promise<UpdateUserInfosResponse> {
|
): Promise<UpdateUserInfosResponse> {
|
||||||
const payload = {
|
const payload = {
|
||||||
session_id: context.sessionId,
|
session_id: context.sessionId,
|
||||||
email,
|
|
||||||
update: {
|
update: {
|
||||||
'User.first_name': firstName || undefined,
|
'User.first_name': firstName || undefined,
|
||||||
'User.last_name': lastName || undefined,
|
'User.last_name': lastName || undefined,
|
||||||
@ -154,9 +168,42 @@ export class UserResolver {
|
|||||||
'User.password_old': password || undefined,
|
'User.password_old': password || undefined,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
let response: UpdateUserInfosResponse | undefined
|
||||||
|
if (
|
||||||
|
firstName ||
|
||||||
|
lastName ||
|
||||||
|
description ||
|
||||||
|
username ||
|
||||||
|
language ||
|
||||||
|
publisherId ||
|
||||||
|
passwordNew ||
|
||||||
|
password
|
||||||
|
) {
|
||||||
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
|
const result = await apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
|
||||||
if (!result.success) throw new Error(result.data)
|
if (!result.success) throw new Error(result.data)
|
||||||
return new UpdateUserInfosResponse(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)
|
@Query(() => CheckUsernameResponse)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ import schema from './graphql/schema'
|
|||||||
// TODO implement
|
// TODO implement
|
||||||
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
||||||
|
|
||||||
const DB_VERSION = '0001-init_db'
|
const DB_VERSION = '0002-add_settings'
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
// open mysql connection
|
// open mysql connection
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
|
||||||
|
import { UserSetting } from './UserSetting'
|
||||||
// import { Group } from "./Group"
|
|
||||||
|
|
||||||
// Moriz: I do not like the idea of having two user tables
|
// Moriz: I do not like the idea of having two user tables
|
||||||
@Entity('state_users')
|
@Entity('state_users')
|
||||||
@ -28,4 +27,7 @@ export class User extends BaseEntity {
|
|||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
disabled: boolean
|
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
|
```json
|
||||||
{
|
{
|
||||||
"session_id": -127182,
|
"session_id": -127182,
|
||||||
"email": "max.musterman@gmail.de",
|
|
||||||
"update": {
|
"update": {
|
||||||
"User.first_name": "Max",
|
"User.first_name": "Max",
|
||||||
"User.last_name" : "Musterman",
|
"User.last_name" : "Musterman",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app" class="font-sans text-gray-800">
|
<div id="app" class="font-sans text-gray-800">
|
||||||
<div class="">
|
<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'" />
|
<component :is="$route.meta.requiresAuth ? 'DashboardLayout' : 'AuthLayoutGDD'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
</b-row>
|
</b-row>
|
||||||
|
|
||||||
<!-- Message-->
|
<!-- Message-->
|
||||||
<b-row v-if="comment && gdtEntryType !== 7">
|
<b-row v-if="comment && !isGlobalModificator">
|
||||||
<b-col cols="6" class="text-right">
|
<b-col cols="6" class="text-right">
|
||||||
{{ $t('form.memo') }}
|
{{ $t('form.memo') }}
|
||||||
</b-col>
|
</b-col>
|
||||||
@ -72,6 +72,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import TransactionCollapse from './TransactionCollapse.vue'
|
import TransactionCollapse from './TransactionCollapse.vue'
|
||||||
|
import { GdtEntryType } from '../graphql/enums'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Transaction',
|
name: 'Transaction',
|
||||||
@ -82,42 +83,52 @@ export default {
|
|||||||
amount: { type: Number },
|
amount: { type: Number },
|
||||||
date: { type: String },
|
date: { type: String },
|
||||||
comment: { type: String },
|
comment: { type: String },
|
||||||
gdtEntryType: { type: Number, default: 1 },
|
gdtEntryType: { type: String, default: GdtEntryType.FORM },
|
||||||
factor: { type: Number },
|
factor: { type: Number },
|
||||||
gdt: { type: Number },
|
gdt: { type: Number },
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
isGlobalModificator: function () {
|
||||||
|
return this.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getLinesByType(givenType) {
|
getLinesByType(givenType) {
|
||||||
if (givenType === 2 || givenType === 3 || givenType === 5 || givenType === 6) givenType = 1
|
switch (givenType) {
|
||||||
|
case GdtEntryType.FORM:
|
||||||
const linesByType = {
|
case GdtEntryType.CVS:
|
||||||
1: {
|
case GdtEntryType.ELOPAGE:
|
||||||
|
case GdtEntryType.DIGISTORE:
|
||||||
|
case GdtEntryType.CVS2: {
|
||||||
|
return {
|
||||||
icon: 'heart',
|
icon: 'heart',
|
||||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||||
description: this.$t('gdt.contribution'),
|
description: this.$t('gdt.contribution'),
|
||||||
descriptiontext: this.$n(this.amount, 'decimal') + ' €',
|
descriptiontext: this.$n(this.amount, 'decimal') + ' €',
|
||||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||||
},
|
}
|
||||||
4: {
|
}
|
||||||
|
case GdtEntryType.ELOPAGE_PUBLISHER: {
|
||||||
|
return {
|
||||||
icon: 'person-check',
|
icon: 'person-check',
|
||||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||||
description: this.$t('gdt.recruited-member'),
|
description: this.$t('gdt.recruited-member'),
|
||||||
descriptiontext: '5%',
|
descriptiontext: '5%',
|
||||||
credittext: this.$n(this.amount, 'decimal') + ' GDT',
|
credittext: this.$n(this.amount, 'decimal') + ' GDT',
|
||||||
},
|
}
|
||||||
7: {
|
}
|
||||||
|
case GdtEntryType.GLOBAL_MODIFICATOR: {
|
||||||
|
return {
|
||||||
icon: 'gift',
|
icon: 'gift',
|
||||||
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
iconclasses: 'gradido-global-color-accent m-mb-1 font2em',
|
||||||
description: this.$t('gdt.gdt-received'),
|
description: this.$t('gdt.gdt-received'),
|
||||||
descriptiontext: this.comment,
|
descriptiontext: this.comment,
|
||||||
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
credittext: this.$n(this.gdt, 'decimal') + ' GDT',
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const type = linesByType[givenType]
|
default:
|
||||||
|
|
||||||
if (type) return type
|
|
||||||
throw new Error('no lines for this type: ' + givenType)
|
throw new Error('no lines for this type: ' + givenType)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { mount } from '@vue/test-utils'
|
import { mount } from '@vue/test-utils'
|
||||||
import TransactionCollapse from './TransactionCollapse'
|
import TransactionCollapse from './TransactionCollapse'
|
||||||
|
import { GdtEntryType } from '../graphql/enums'
|
||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
@ -15,13 +16,13 @@ describe('TransactionCollapse', () => {
|
|||||||
return mount(TransactionCollapse, { localVue, mocks, propsData })
|
return mount(TransactionCollapse, { localVue, mocks, propsData })
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('mount with gdtEntryType: 1', () => {
|
describe('mount with gdtEntryType: FORM', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const propsData = {
|
const propsData = {
|
||||||
amount: 100,
|
amount: 100,
|
||||||
gdt: 110,
|
gdt: 110,
|
||||||
factor: 22,
|
factor: 22,
|
||||||
gdtEntryType: 1,
|
gdtEntryType: GdtEntryType.FORM,
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper = Wrapper(propsData)
|
wrapper = Wrapper(propsData)
|
||||||
@ -31,8 +32,8 @@ describe('TransactionCollapse', () => {
|
|||||||
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('checks the prop gdtEntryType ', () => {
|
it('checks the prop gdtEntryType', () => {
|
||||||
expect(wrapper.props().gdtEntryType).toBe(1)
|
expect(wrapper.props().gdtEntryType).toBe('FORM')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders the component collapse-header', () => {
|
it('renders the component collapse-header', () => {
|
||||||
@ -60,13 +61,13 @@ describe('TransactionCollapse', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('mount with gdtEntryType: 7', () => {
|
describe('mount with gdtEntryType: GLOBAL_MODIFICATOR', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const propsData = {
|
const propsData = {
|
||||||
amount: 100,
|
amount: 100,
|
||||||
gdt: 2200,
|
gdt: 2200,
|
||||||
factor: 22,
|
factor: 22,
|
||||||
gdtEntryType: 7,
|
gdtEntryType: GdtEntryType.GLOBAL_MODIFICATOR,
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper = Wrapper(propsData)
|
wrapper = Wrapper(propsData)
|
||||||
@ -76,8 +77,8 @@ describe('TransactionCollapse', () => {
|
|||||||
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('checks the prop gdtEntryType ', () => {
|
it('checks the prop gdtEntryType', () => {
|
||||||
expect(wrapper.props().gdtEntryType).toBe(7)
|
expect(wrapper.props().gdtEntryType).toBe('GLOBAL_MODIFICATOR')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders the component collapse-header', () => {
|
it('renders the component collapse-header', () => {
|
||||||
@ -105,13 +106,13 @@ describe('TransactionCollapse', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('mount with gdtEntryType: 4', () => {
|
describe('mount with gdtEntryType: ELOPAGE_PUBLISHER', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const propsData = {
|
const propsData = {
|
||||||
amount: 100,
|
amount: 100,
|
||||||
gdt: 2200,
|
gdt: 2200,
|
||||||
factor: 22,
|
factor: 22,
|
||||||
gdtEntryType: 4,
|
gdtEntryType: GdtEntryType.ELOPAGE_PUBLISHER,
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapper = Wrapper(propsData)
|
wrapper = Wrapper(propsData)
|
||||||
@ -121,8 +122,8 @@ describe('TransactionCollapse', () => {
|
|||||||
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
expect(wrapper.find('div.gdt-transaction-collapse').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('checks the prop gdtEntryType ', () => {
|
it('checks the prop gdtEntryType', () => {
|
||||||
expect(wrapper.props().gdtEntryType).toBe(4)
|
expect(wrapper.props().gdtEntryType).toBe('ELOPAGE_PUBLISHER')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('renders the component collapse-header', () => {
|
it('renders the component collapse-header', () => {
|
||||||
|
|||||||
@ -23,20 +23,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import { GdtEntryType } from '../graphql/enums'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TransactionCollapse',
|
name: 'TransactionCollapse',
|
||||||
props: {
|
props: {
|
||||||
amount: { type: Number },
|
amount: { type: Number },
|
||||||
gdtEntryType: { type: Number, default: 1 },
|
gdtEntryType: { type: String, default: GdtEntryType.FORM },
|
||||||
factor: { type: Number },
|
factor: { type: Number },
|
||||||
gdt: { type: Number },
|
gdt: { type: Number },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getLinesByType(givenType) {
|
getLinesByType(givenType) {
|
||||||
if (givenType === 2 || givenType === 3 || givenType === 5 || givenType === 6) givenType = 1
|
switch (givenType) {
|
||||||
|
case GdtEntryType.FORM:
|
||||||
const linesByType = {
|
case GdtEntryType.CVS:
|
||||||
1: {
|
case GdtEntryType.ELOPAGE:
|
||||||
|
case GdtEntryType.DIGISTORE:
|
||||||
|
case GdtEntryType.CVS2: {
|
||||||
|
return {
|
||||||
headline: this.$t('gdt.calculation'),
|
headline: this.$t('gdt.calculation'),
|
||||||
first: this.$t('gdt.factor'),
|
first: this.$t('gdt.factor'),
|
||||||
firstMath: this.factor + ' GDT pro €',
|
firstMath: this.factor + ' GDT pro €',
|
||||||
@ -48,15 +53,19 @@ export default {
|
|||||||
' GDT / € = ' +
|
' GDT / € = ' +
|
||||||
this.$n(this.gdt, 'decimal') +
|
this.$n(this.gdt, 'decimal') +
|
||||||
' GDT',
|
' GDT',
|
||||||
},
|
}
|
||||||
4: {
|
}
|
||||||
|
case GdtEntryType.ELOPAGE_PUBLISHER: {
|
||||||
|
return {
|
||||||
headline: this.$t('gdt.publisher'),
|
headline: this.$t('gdt.publisher'),
|
||||||
first: null,
|
first: null,
|
||||||
firstMath: null,
|
firstMath: null,
|
||||||
second: null,
|
second: null,
|
||||||
secondMath: null,
|
secondMath: null,
|
||||||
},
|
}
|
||||||
7: {
|
}
|
||||||
|
case GdtEntryType.GLOBAL_MODIFICATOR: {
|
||||||
|
return {
|
||||||
headline: this.$t('gdt.conversion-gdt-euro'),
|
headline: this.$t('gdt.conversion-gdt-euro'),
|
||||||
first: this.$t('gdt.raise'),
|
first: this.$t('gdt.raise'),
|
||||||
firstMath: this.factor * 100 + ' % ',
|
firstMath: this.factor * 100 + ' % ',
|
||||||
@ -68,13 +77,11 @@ export default {
|
|||||||
' % = ' +
|
' % = ' +
|
||||||
this.$n(this.gdt, 'decimal') +
|
this.$n(this.gdt, 'decimal') +
|
||||||
' GDT',
|
' GDT',
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
const type = linesByType[givenType]
|
default:
|
||||||
|
|
||||||
if (type) return type
|
|
||||||
throw new Error('no additional transaction info for this type: ' + givenType)
|
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`
|
export const updateUserInfos = gql`
|
||||||
mutation(
|
mutation(
|
||||||
$email: String!
|
|
||||||
$firstName: String
|
$firstName: String
|
||||||
$lastName: String
|
$lastName: String
|
||||||
$description: String
|
$description: String
|
||||||
@ -28,9 +27,9 @@ export const updateUserInfos = gql`
|
|||||||
$password: String
|
$password: String
|
||||||
$passwordNew: String
|
$passwordNew: String
|
||||||
$locale: String
|
$locale: String
|
||||||
|
$coinanimation: Boolean
|
||||||
) {
|
) {
|
||||||
updateUserInfos(
|
updateUserInfos(
|
||||||
email: $email
|
|
||||||
firstName: $firstName
|
firstName: $firstName
|
||||||
lastName: $lastName
|
lastName: $lastName
|
||||||
description: $description
|
description: $description
|
||||||
@ -38,6 +37,7 @@ export const updateUserInfos = gql`
|
|||||||
password: $password
|
password: $password
|
||||||
passwordNew: $passwordNew
|
passwordNew: $passwordNew
|
||||||
language: $locale
|
language: $locale
|
||||||
|
coinanimation: $coinanimation
|
||||||
) {
|
) {
|
||||||
validValues
|
validValues
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export const login = gql`
|
|||||||
lastName
|
lastName
|
||||||
language
|
language
|
||||||
description
|
description
|
||||||
|
coinanimation
|
||||||
klickTipp {
|
klickTipp {
|
||||||
newsletterState
|
newsletterState
|
||||||
}
|
}
|
||||||
|
|||||||
@ -105,6 +105,11 @@
|
|||||||
"privacy_policy": "Datenschutzerklärung",
|
"privacy_policy": "Datenschutzerklärung",
|
||||||
"send": "Senden",
|
"send": "Senden",
|
||||||
"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",
|
||||||
|
|||||||
@ -105,6 +105,11 @@
|
|||||||
"privacy_policy": "Privacy policy",
|
"privacy_policy": "Privacy policy",
|
||||||
"send": "Send",
|
"send": "Send",
|
||||||
"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",
|
||||||
|
|||||||
@ -67,6 +67,7 @@ export const store = new Vuex.Store({
|
|||||||
username: '',
|
username: '',
|
||||||
description: '',
|
description: '',
|
||||||
token: null,
|
token: null,
|
||||||
|
coinanimation: true,
|
||||||
newsletterState: null,
|
newsletterState: null,
|
||||||
},
|
},
|
||||||
getters: {},
|
getters: {},
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { mount } from '@vue/test-utils'
|
import { mount } from '@vue/test-utils'
|
||||||
|
import { GdtEntryType } from '../../../graphql/enums'
|
||||||
import GdtTransactionList from './GdtTransactionList'
|
import GdtTransactionList from './GdtTransactionList'
|
||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
@ -14,7 +15,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
|||||||
factor: 17,
|
factor: 17,
|
||||||
comment: '',
|
comment: '',
|
||||||
date: '2021-05-02T17:20:11+00:00',
|
date: '2021-05-02T17:20:11+00:00',
|
||||||
gdtEntryType: 1,
|
gdtEntryType: GdtEntryType.FORM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount: 1810,
|
amount: 1810,
|
||||||
@ -22,7 +23,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
|||||||
factor: 0.2,
|
factor: 0.2,
|
||||||
comment: 'Dezember 20',
|
comment: 'Dezember 20',
|
||||||
date: '2020-12-31T12:00:00+00:00',
|
date: '2020-12-31T12:00:00+00:00',
|
||||||
gdtEntryType: 7,
|
gdtEntryType: GdtEntryType.GLOBAL_MODIFICATOR,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount: 100,
|
amount: 100,
|
||||||
@ -30,7 +31,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
|||||||
factor: 17,
|
factor: 17,
|
||||||
comment: '',
|
comment: '',
|
||||||
date: '2020-05-07T17:00:00+00:00',
|
date: '2020-05-07T17:00:00+00:00',
|
||||||
gdtEntryType: 1,
|
gdtEntryType: GdtEntryType.FORM,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
amount: 100,
|
amount: 100,
|
||||||
@ -38,7 +39,7 @@ const apolloMock = jest.fn().mockResolvedValue({
|
|||||||
factor: 22,
|
factor: 22,
|
||||||
comment: '',
|
comment: '',
|
||||||
date: '2020-04-10T13:28:00+00:00',
|
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 />
|
<form-user-language />
|
||||||
<hr />
|
<hr />
|
||||||
<form-user-newsletter />
|
<form-user-newsletter />
|
||||||
|
<hr />
|
||||||
|
<form-user-coin-animation />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -16,6 +18,7 @@ import FormUserData from './UserProfile/UserCard_FormUserData.vue'
|
|||||||
import FormUserPasswort from './UserProfile/UserCard_FormUserPasswort.vue'
|
import FormUserPasswort from './UserProfile/UserCard_FormUserPasswort.vue'
|
||||||
import FormUserLanguage from './UserProfile/UserCard_Language.vue'
|
import FormUserLanguage from './UserProfile/UserCard_Language.vue'
|
||||||
import FormUserNewsletter from './UserProfile/UserCard_Newsletter.vue'
|
import FormUserNewsletter from './UserProfile/UserCard_Newsletter.vue'
|
||||||
|
import FormUserCoinAnimation from './UserProfile/UserCard_CoinAnimation.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -24,6 +27,7 @@ export default {
|
|||||||
FormUserPasswort,
|
FormUserPasswort,
|
||||||
FormUserLanguage,
|
FormUserLanguage,
|
||||||
FormUserNewsletter,
|
FormUserNewsletter,
|
||||||
|
FormUserCoinAnimation,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
balance: { type: Number, default: 0 },
|
balance: { type: Number, default: 0 },
|
||||||
|
|||||||
@ -15,7 +15,6 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
'session_id' => $session_id,
|
'session_id' => $session_id,
|
||||||
'email' => $email,
|
|
||||||
'update' => ['User.first_name' => 'first_name', 'User.last_name' => 'last_name', 'User.disabled' => 0|1, 'User.language' => 'de']
|
'update' => ['User.first_name' => 'first_name', 'User.last_name' => 'last_name', 'User.disabled' => 0|1, 'User.language' => 'de']
|
||||||
*/
|
*/
|
||||||
// incoming
|
// incoming
|
||||||
@ -34,7 +33,6 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
|
|||||||
/// not available for the given type.
|
/// not available for the given type.
|
||||||
/// Throws InvalidAccessException if Var is empty.
|
/// Throws InvalidAccessException if Var is empty.
|
||||||
try {
|
try {
|
||||||
paramJsonObject->get("email").convert(email);
|
|
||||||
|
|
||||||
auto session_id_obj = paramJsonObject->get("session_id");
|
auto session_id_obj = paramJsonObject->get("session_id");
|
||||||
if (!session_id_obj.isEmpty()) {
|
if (!session_id_obj.isEmpty()) {
|
||||||
@ -66,9 +64,6 @@ Poco::JSON::Object* JsonUpdateUserInfos::handle(Poco::Dynamic::Var params)
|
|||||||
}
|
}
|
||||||
auto user = mSession->getNewUser();
|
auto user = mSession->getNewUser();
|
||||||
auto user_model = user->getModel();
|
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;
|
Poco::JSON::Object* result = new Poco::JSON::Object;
|
||||||
result->set("state", "success");
|
result->set("state", "success");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user