mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
Merge branch 'message-type-admin' into message-type-admin-frontend
This commit is contained in:
commit
c7b940d514
@ -53,4 +53,5 @@ export enum RIGHTS {
|
|||||||
ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
|
ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
|
||||||
DENY_CONTRIBUTION = 'DENY_CONTRIBUTION',
|
DENY_CONTRIBUTION = 'DENY_CONTRIBUTION',
|
||||||
ADMIN_OPEN_CREATIONS = 'ADMIN_OPEN_CREATIONS',
|
ADMIN_OPEN_CREATIONS = 'ADMIN_OPEN_CREATIONS',
|
||||||
|
ADMIN_LIST_ALL_CONTRIBUTION_MESSAGES = 'ADMIN_LIST_ALL_CONTRIBUTION_MESSAGES',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { ArgsType, Field, Int, InputType } from 'type-graphql'
|
import { ArgsType, Field, Int, InputType } from 'type-graphql'
|
||||||
|
|
||||||
|
import { ContributionMessageType } from '@enum/ContributionMessageType'
|
||||||
|
|
||||||
@InputType()
|
@InputType()
|
||||||
@ArgsType()
|
@ArgsType()
|
||||||
export class ContributionMessageArgs {
|
export class ContributionMessageArgs {
|
||||||
@ -8,4 +10,7 @@ export class ContributionMessageArgs {
|
|||||||
|
|
||||||
@Field(() => String)
|
@Field(() => String)
|
||||||
message: string
|
message: string
|
||||||
|
|
||||||
|
@Field(() => ContributionMessageType, { defaultValue: ContributionMessageType.DIALOG })
|
||||||
|
messageType: ContributionMessageType
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import { registerEnumType } from 'type-graphql'
|
|||||||
export enum ContributionMessageType {
|
export enum ContributionMessageType {
|
||||||
HISTORY = 'HISTORY',
|
HISTORY = 'HISTORY',
|
||||||
DIALOG = 'DIALOG',
|
DIALOG = 'DIALOG',
|
||||||
|
MODERATOR = 'MODERATOR', // messages for moderator communication, can only be seen by moderators
|
||||||
}
|
}
|
||||||
|
|
||||||
registerEnumType(ContributionMessageType, {
|
registerEnumType(ContributionMessageType, {
|
||||||
@ -20,7 +20,7 @@ import {
|
|||||||
createContributionMessage,
|
createContributionMessage,
|
||||||
login,
|
login,
|
||||||
} from '@/seeds/graphql/mutations'
|
} from '@/seeds/graphql/mutations'
|
||||||
import { listContributionMessages } from '@/seeds/graphql/queries'
|
import { listContributionMessages, adminListContributionMessages } from '@/seeds/graphql/queries'
|
||||||
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
import { bibiBloxberg } from '@/seeds/users/bibi-bloxberg'
|
||||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||||
|
|
||||||
@ -217,6 +217,33 @@ describe('ContributionMessageResolver', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('contribution message type MODERATOR', () => {
|
||||||
|
it('creates ContributionMessage', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: adminCreateContributionMessage,
|
||||||
|
variables: {
|
||||||
|
contributionId: result.data.createContribution.id,
|
||||||
|
message: 'Internal moderator communication',
|
||||||
|
messageType: 'MODERATOR',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
adminCreateContributionMessage: expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
message: 'Internal moderator communication',
|
||||||
|
type: 'MODERATOR',
|
||||||
|
userFirstName: 'Peter',
|
||||||
|
userLastName: 'Lustig',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -385,7 +412,7 @@ describe('ContributionMessageResolver', () => {
|
|||||||
resetToken()
|
resetToken()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns a list of contributionmessages', async () => {
|
it('returns a list of contributionmessages without type MODERATOR', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: listContributionMessages,
|
mutation: listContributionMessages,
|
||||||
@ -419,4 +446,96 @@ describe('ContributionMessageResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('adminListContributionMessages', () => {
|
||||||
|
describe('unauthenticated', () => {
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: adminListContributionMessages,
|
||||||
|
variables: { contributionId: 1 },
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authenticated as user', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'bibi@bloxberg.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns an error', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: adminListContributionMessages,
|
||||||
|
variables: { contributionId: 1 },
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('401 Unauthorized')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('authenticated', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await mutate({
|
||||||
|
mutation: login,
|
||||||
|
variables: { email: 'peter@lustig.de', password: 'Aa12345_' },
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(() => {
|
||||||
|
resetToken()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns a list of contributionmessages with type MODERATOR', async () => {
|
||||||
|
await expect(
|
||||||
|
mutate({
|
||||||
|
mutation: adminListContributionMessages,
|
||||||
|
variables: { contributionId: result.data.createContribution.id },
|
||||||
|
}),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
adminListContributionMessages: {
|
||||||
|
count: 3,
|
||||||
|
messages: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
message: 'Admin Test',
|
||||||
|
type: 'DIALOG',
|
||||||
|
userFirstName: 'Peter',
|
||||||
|
userLastName: 'Lustig',
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
message: 'User Test',
|
||||||
|
type: 'DIALOG',
|
||||||
|
userFirstName: 'Bibi',
|
||||||
|
userLastName: 'Bloxberg',
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(Number),
|
||||||
|
message: 'Internal moderator communication',
|
||||||
|
type: 'MODERATOR',
|
||||||
|
userFirstName: 'Peter',
|
||||||
|
userLastName: 'Lustig',
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -8,8 +8,8 @@ import { Arg, Args, Authorized, Ctx, Int, Mutation, Query, Resolver } from 'type
|
|||||||
|
|
||||||
import { ContributionMessageArgs } from '@arg/ContributionMessageArgs'
|
import { ContributionMessageArgs } from '@arg/ContributionMessageArgs'
|
||||||
import { Paginated } from '@arg/Paginated'
|
import { Paginated } from '@arg/Paginated'
|
||||||
|
import { ContributionMessageType } from '@enum/ContributionMessageType'
|
||||||
import { ContributionStatus } from '@enum/ContributionStatus'
|
import { ContributionStatus } from '@enum/ContributionStatus'
|
||||||
import { ContributionMessageType } from '@enum/MessageType'
|
|
||||||
import { Order } from '@enum/Order'
|
import { Order } from '@enum/Order'
|
||||||
import { ContributionMessage, ContributionMessageListResult } from '@model/ContributionMessage'
|
import { ContributionMessage, ContributionMessageListResult } from '@model/ContributionMessage'
|
||||||
|
|
||||||
@ -22,6 +22,8 @@ import {
|
|||||||
import { Context, getUser } from '@/server/context'
|
import { Context, getUser } from '@/server/context'
|
||||||
import { LogError } from '@/server/LogError'
|
import { LogError } from '@/server/LogError'
|
||||||
|
|
||||||
|
import { findContributionMessages } from './util/findContributionMessages'
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class ContributionMessageResolver {
|
export class ContributionMessageResolver {
|
||||||
@Authorized([RIGHTS.CREATE_CONTRIBUTION_MESSAGE])
|
@Authorized([RIGHTS.CREATE_CONTRIBUTION_MESSAGE])
|
||||||
@ -82,16 +84,35 @@ export class ContributionMessageResolver {
|
|||||||
@Args()
|
@Args()
|
||||||
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
|
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
|
||||||
): Promise<ContributionMessageListResult> {
|
): Promise<ContributionMessageListResult> {
|
||||||
const [contributionMessages, count] = await getConnection()
|
const [contributionMessages, count] = await findContributionMessages({
|
||||||
.createQueryBuilder()
|
contributionId,
|
||||||
.select('cm')
|
currentPage,
|
||||||
.from(DbContributionMessage, 'cm')
|
pageSize,
|
||||||
.leftJoinAndSelect('cm.user', 'u')
|
order,
|
||||||
.where({ contributionId })
|
})
|
||||||
.orderBy('cm.createdAt', order)
|
|
||||||
.limit(pageSize)
|
return {
|
||||||
.offset((currentPage - 1) * pageSize)
|
count,
|
||||||
.getManyAndCount()
|
messages: contributionMessages.map(
|
||||||
|
(message) => new ContributionMessage(message, message.user),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Authorized([RIGHTS.ADMIN_LIST_ALL_CONTRIBUTION_MESSAGES])
|
||||||
|
@Query(() => ContributionMessageListResult)
|
||||||
|
async adminListContributionMessages(
|
||||||
|
@Arg('contributionId', () => Int) contributionId: number,
|
||||||
|
@Args()
|
||||||
|
{ currentPage = 1, pageSize = 5, order = Order.DESC }: Paginated,
|
||||||
|
): Promise<ContributionMessageListResult> {
|
||||||
|
const [contributionMessages, count] = await findContributionMessages({
|
||||||
|
contributionId,
|
||||||
|
currentPage,
|
||||||
|
pageSize,
|
||||||
|
order,
|
||||||
|
showModeratorType: true,
|
||||||
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
count,
|
count,
|
||||||
@ -104,7 +125,7 @@ export class ContributionMessageResolver {
|
|||||||
@Authorized([RIGHTS.ADMIN_CREATE_CONTRIBUTION_MESSAGE])
|
@Authorized([RIGHTS.ADMIN_CREATE_CONTRIBUTION_MESSAGE])
|
||||||
@Mutation(() => ContributionMessage)
|
@Mutation(() => ContributionMessage)
|
||||||
async adminCreateContributionMessage(
|
async adminCreateContributionMessage(
|
||||||
@Args() { contributionId, message }: ContributionMessageArgs,
|
@Args() { contributionId, message, messageType }: ContributionMessageArgs,
|
||||||
@Ctx() context: Context,
|
@Ctx() context: Context,
|
||||||
): Promise<ContributionMessage> {
|
): Promise<ContributionMessage> {
|
||||||
const moderator = getUser(context)
|
const moderator = getUser(context)
|
||||||
@ -133,7 +154,7 @@ export class ContributionMessageResolver {
|
|||||||
contributionMessage.createdAt = new Date()
|
contributionMessage.createdAt = new Date()
|
||||||
contributionMessage.message = message
|
contributionMessage.message = message
|
||||||
contributionMessage.userId = moderator.id
|
contributionMessage.userId = moderator.id
|
||||||
contributionMessage.type = ContributionMessageType.DIALOG
|
contributionMessage.type = messageType
|
||||||
contributionMessage.isModerator = true
|
contributionMessage.isModerator = true
|
||||||
await queryRunner.manager.insert(DbContributionMessage, contributionMessage)
|
await queryRunner.manager.insert(DbContributionMessage, contributionMessage)
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,9 @@ import { AdminCreateContributionArgs } from '@arg/AdminCreateContributionArgs'
|
|||||||
import { AdminUpdateContributionArgs } from '@arg/AdminUpdateContributionArgs'
|
import { AdminUpdateContributionArgs } from '@arg/AdminUpdateContributionArgs'
|
||||||
import { ContributionArgs } from '@arg/ContributionArgs'
|
import { ContributionArgs } from '@arg/ContributionArgs'
|
||||||
import { Paginated } from '@arg/Paginated'
|
import { Paginated } from '@arg/Paginated'
|
||||||
|
import { ContributionMessageType } from '@enum/ContributionMessageType'
|
||||||
import { ContributionStatus } from '@enum/ContributionStatus'
|
import { ContributionStatus } from '@enum/ContributionStatus'
|
||||||
import { ContributionType } from '@enum/ContributionType'
|
import { ContributionType } from '@enum/ContributionType'
|
||||||
import { ContributionMessageType } from '@enum/MessageType'
|
|
||||||
import { Order } from '@enum/Order'
|
import { Order } from '@enum/Order'
|
||||||
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
import { TransactionTypeId } from '@enum/TransactionTypeId'
|
||||||
import { AdminUpdateContribution } from '@model/AdminUpdateContribution'
|
import { AdminUpdateContribution } from '@model/AdminUpdateContribution'
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
import { In } from '@dbTools/typeorm'
|
||||||
|
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||||
|
|
||||||
|
import { ContributionMessageType } from '@enum/ContributionMessageType'
|
||||||
|
import { Order } from '@enum/Order'
|
||||||
|
|
||||||
|
interface FindContributionMessagesOptions {
|
||||||
|
contributionId: number
|
||||||
|
pageSize: number
|
||||||
|
currentPage: number
|
||||||
|
order: Order
|
||||||
|
showModeratorType?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const findContributionMessages = async (
|
||||||
|
options: FindContributionMessagesOptions,
|
||||||
|
): Promise<[DbContributionMessage[], number]> => {
|
||||||
|
const { contributionId, pageSize, currentPage, order, showModeratorType } = options
|
||||||
|
|
||||||
|
const messageTypes = [ContributionMessageType.DIALOG, ContributionMessageType.HISTORY]
|
||||||
|
|
||||||
|
if (showModeratorType) messageTypes.push(ContributionMessageType.MODERATOR)
|
||||||
|
|
||||||
|
return DbContributionMessage.findAndCount({
|
||||||
|
where: {
|
||||||
|
contributionId,
|
||||||
|
type: In(messageTypes),
|
||||||
|
},
|
||||||
|
relations: ['user'],
|
||||||
|
order: {
|
||||||
|
createdAt: order,
|
||||||
|
},
|
||||||
|
skip: (currentPage - 1) * pageSize,
|
||||||
|
take: pageSize,
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -284,8 +284,12 @@ export const createContributionMessage = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
export const adminCreateContributionMessage = gql`
|
export const adminCreateContributionMessage = gql`
|
||||||
mutation ($contributionId: Int!, $message: String!) {
|
mutation ($contributionId: Int!, $message: String!, $messageType: ContributionMessageType) {
|
||||||
adminCreateContributionMessage(contributionId: $contributionId, message: $message) {
|
adminCreateContributionMessage(
|
||||||
|
contributionId: $contributionId
|
||||||
|
message: $message
|
||||||
|
messageType: $messageType
|
||||||
|
) {
|
||||||
id
|
id
|
||||||
message
|
message
|
||||||
createdAt
|
createdAt
|
||||||
|
|||||||
@ -349,6 +349,29 @@ export const listContributionMessages = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
export const adminListContributionMessages = gql`
|
||||||
|
query ($contributionId: Int!, $pageSize: Int = 25, $currentPage: Int = 1, $order: Order = ASC) {
|
||||||
|
adminListContributionMessages(
|
||||||
|
contributionId: $contributionId
|
||||||
|
pageSize: $pageSize
|
||||||
|
currentPage: $currentPage
|
||||||
|
order: $order
|
||||||
|
) {
|
||||||
|
count
|
||||||
|
messages {
|
||||||
|
id
|
||||||
|
message
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
type
|
||||||
|
userFirstName
|
||||||
|
userLastName
|
||||||
|
userId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
export const user = gql`
|
export const user = gql`
|
||||||
query ($identifier: String!) {
|
query ($identifier: String!) {
|
||||||
user(identifier: $identifier) {
|
user(identifier: $identifier) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user