diff --git a/admin/src/graphql/getCountPendingCreations.js b/admin/src/graphql/getCountPendingCreations.js new file mode 100644 index 000000000..f8593ee59 --- /dev/null +++ b/admin/src/graphql/getCountPendingCreations.js @@ -0,0 +1,7 @@ +import gql from 'graphql-tag' + +export const countPendingCreations = gql` + query { + countPendingCreations + } +` diff --git a/admin/src/graphql/getPendingCreations.js b/admin/src/graphql/getPendingCreations.js new file mode 100644 index 000000000..a94172d43 --- /dev/null +++ b/admin/src/graphql/getPendingCreations.js @@ -0,0 +1,16 @@ +import gql from 'graphql-tag' + +export const getPendingCreations = gql` + query { + getPendingCreations { + firstName + lastName + email + amount + memo + date + moderator + creation + } + } +` diff --git a/admin/src/pages/CreationConfirm.spec.js b/admin/src/pages/CreationConfirm.spec.js index caf94cd37..86f90231b 100644 --- a/admin/src/pages/CreationConfirm.spec.js +++ b/admin/src/pages/CreationConfirm.spec.js @@ -4,11 +4,47 @@ import CreationConfirm from './CreationConfirm.vue' const localVue = global.localVue const storeCommitMock = jest.fn() +const toastedErrorMock = jest.fn() +const apolloQueryMock = jest.fn().mockResolvedValue({ + data: { + getPendingCreations: [ + { + firstName: 'Bibi', + lastName: 'Bloxberg', + email: 'bibi@bloxberg.de', + amount: 500, + memo: 'Danke für alles', + date: new Date(), + moderator: 0, + }, + { + firstName: 'Räuber', + lastName: 'Hotzenplotz', + email: 'raeuber@hotzenplotz.de', + amount: 1000000, + memo: 'Gut Ergatert', + date: new Date(), + moderator: 0, + }, + ], + }, +}) const mocks = { $store: { commit: storeCommitMock, }, + $apollo: { + query: apolloQueryMock, + }, + $toasted: { + error: toastedErrorMock, + }, + $moment: jest.fn((value) => { + return { + format: jest.fn((format) => value), + } + }), } describe('CreationConfirm', () => { @@ -32,9 +68,22 @@ describe('CreationConfirm', () => { it('commits resetOpenCreations to store', () => { expect(storeCommitMock).toBeCalledWith('resetOpenCreations') }) + it('commits setOpenCreations to store', () => { + expect(storeCommitMock).toBeCalledWith('setOpenCreations', 2) + }) + }) - it('commits openCreationsPlus to store', () => { - expect(storeCommitMock).toBeCalledWith('openCreationsPlus', 5) + describe('server response is error', () => { + beforeEach(() => { + jest.clearAllMocks() + apolloQueryMock.mockRejectedValue({ + message: 'Ouch!', + }) + wrapper = Wrapper() + }) + + it('toast an error message', () => { + expect(toastedErrorMock).toBeCalledWith('Ouch!') }) }) diff --git a/admin/src/pages/CreationConfirm.vue b/admin/src/pages/CreationConfirm.vue index 0d68635e0..3aef891eb 100644 --- a/admin/src/pages/CreationConfirm.vue +++ b/admin/src/pages/CreationConfirm.vue @@ -1,9 +1,5 @@ diff --git a/admin/src/store/store.js b/admin/src/store/store.js index dc168c558..fe5629e19 100644 --- a/admin/src/store/store.js +++ b/admin/src/store/store.js @@ -18,6 +18,9 @@ export const mutations = { token: (state, token) => { state.token = token }, + setOpenCreations: (state, openCreations) => { + state.openCreations = openCreations + }, moderator: (state, moderator) => { state.moderator = moderator }, diff --git a/admin/src/store/store.test.js b/admin/src/store/store.test.js index de8a55412..4f66ef13d 100644 --- a/admin/src/store/store.test.js +++ b/admin/src/store/store.test.js @@ -1,11 +1,13 @@ import store, { mutations, actions } from './store' +import CONFIG from '../config' -const { token, openCreationsPlus, openCreationsMinus, resetOpenCreations, moderator } = mutations +jest.mock('../config') + +const { token, openCreationsPlus, openCreationsMinus, resetOpenCreations, setOpenCreations } = + mutations const { logout } = actions -const CONFIG = { - DEBUG_DISABLE_AUTH: true, -} +CONFIG.DEBUG_DISABLE_AUTH = true describe('Vuex store', () => { describe('mutations', () => { @@ -48,6 +50,14 @@ describe('Vuex store', () => { expect(state.moderator).toEqual({ id: 1 }) }) }) + + describe('setOpenCreations', () => { + it('sets the open creations to given value', () => { + const state = { openCreations: 24 } + setOpenCreations(state, 12) + expect(state.openCreations).toEqual(12) + }) + }) }) describe('actions', () => { diff --git a/backend/src/graphql/model/PendingCreation.ts b/backend/src/graphql/model/PendingCreation.ts new file mode 100644 index 000000000..f1087ea0b --- /dev/null +++ b/backend/src/graphql/model/PendingCreation.ts @@ -0,0 +1,34 @@ +import { ObjectType, Field, Int } from 'type-graphql' + +@ObjectType() +export class PendingCreation { + @Field(() => String) + firstName: string + + @Field(() => Int) + id?: number + + @Field(() => String) + lastName: string + + @Field(() => Number) + userId: number + + @Field(() => String) + email: string + + @Field(() => Date) + date: Date + + @Field(() => String) + memo: string + + @Field(() => Number) + amount: BigInt + + @Field(() => Number) + moderator: number + + @Field(() => [Number]) + creation: number[] +} diff --git a/backend/src/graphql/resolver/AdminResolver.ts b/backend/src/graphql/resolver/AdminResolver.ts index f3c9d1516..169b79250 100644 --- a/backend/src/graphql/resolver/AdminResolver.ts +++ b/backend/src/graphql/resolver/AdminResolver.ts @@ -1,7 +1,7 @@ import { Resolver, Query, Arg, Args, Authorized, Mutation } from 'type-graphql' import { getCustomRepository, Raw } from 'typeorm' import { UserAdmin } from '../model/UserAdmin' -import { LoginUserRepository } from '../../typeorm/repository/LoginUser' +import { PendingCreation } from '../model/PendingCreation' import { RIGHTS } from '../../auth/RIGHTS' import { TransactionCreationRepository } from '../../typeorm/repository/TransactionCreation' import { PendingCreationRepository } from '../../typeorm/repository/PendingCreation' @@ -14,19 +14,19 @@ export class AdminResolver { @Authorized([RIGHTS.SEARCH_USERS]) @Query(() => [UserAdmin]) async searchUsers(@Arg('searchText') searchText: string): Promise { - const loginUserRepository = getCustomRepository(LoginUserRepository) - const loginUsers = await loginUserRepository.findBySearchCriteria(searchText) - const users = await Promise.all( - loginUsers.map(async (loginUser) => { - const user = new UserAdmin() - user.firstName = loginUser.firstName - user.lastName = loginUser.lastName - user.email = loginUser.email - user.creation = await getUserCreations(loginUser.id) - return user + const userRepository = getCustomRepository(UserRepository) + const users = await userRepository.findBySearchCriteria(searchText) + const adminUsers = await Promise.all( + users.map(async (user) => { + const adminUser = new UserAdmin() + adminUser.firstName = user.firstName + adminUser.lastName = user.lastName + adminUser.email = user.email + adminUser.creation = await getUserCreations(user.id) + return adminUser }), ) - return users + return adminUsers } @Mutation(() => [Number]) @@ -52,6 +52,30 @@ export class AdminResolver { } return await getUserCreations(user.id) } + + @Query(() => [PendingCreation]) + async getPendingCreations(): Promise { + const pendingCreationRepository = getCustomRepository(PendingCreationRepository) + const pendingCreations = await pendingCreationRepository.find() + + const pendingCreationsPromise = await Promise.all( + pendingCreations.map(async (pendingCreation) => { + const userRepository = getCustomRepository(UserRepository) + const user = await userRepository.findOneOrFail({ id: pendingCreation.userId }) + + const newPendingCreation = { + ...pendingCreation, + firstName: user.firstName, + lastName: user.lastName, + email: user.email, + creation: await getUserCreations(user.id), + } + + return newPendingCreation + }), + ) + return pendingCreationsPromise + } } async function getUserCreations(id: number): Promise { diff --git a/backend/src/typeorm/repository/User.ts b/backend/src/typeorm/repository/User.ts index e127c179c..cf67c837b 100644 --- a/backend/src/typeorm/repository/User.ts +++ b/backend/src/typeorm/repository/User.ts @@ -30,4 +30,17 @@ export class UserRepository extends Repository { }) return usersIndiced } + + async findBySearchCriteria(searchCriteria: string): Promise { + return await this.createQueryBuilder('user') + .where( + 'user.firstName like :name or user.lastName like :lastName or user.email like :email', + { + name: `%${searchCriteria}%`, + lastName: `%${searchCriteria}%`, + email: `%${searchCriteria}%`, + }, + ) + .getMany() + } } diff --git a/backend/src/webhook/elopage.ts b/backend/src/webhook/elopage.ts index 9e2ddeb81..eb46b10e8 100644 --- a/backend/src/webhook/elopage.ts +++ b/backend/src/webhook/elopage.ts @@ -1,3 +1,5 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* Elopage Webhook