mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch '2131-crud-for-messages' into Contribution-Messages
This commit is contained in:
commit
95abc61964
@ -33,6 +33,7 @@ export enum RIGHTS {
|
|||||||
LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS',
|
LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS',
|
||||||
COMMUNITY_STATISTICS = 'COMMUNITY_STATISTICS',
|
COMMUNITY_STATISTICS = 'COMMUNITY_STATISTICS',
|
||||||
SEARCH_ADMIN_USERS = 'SEARCH_ADMIN_USERS',
|
SEARCH_ADMIN_USERS = 'SEARCH_ADMIN_USERS',
|
||||||
|
CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE',
|
||||||
// Admin
|
// Admin
|
||||||
SEARCH_USERS = 'SEARCH_USERS',
|
SEARCH_USERS = 'SEARCH_USERS',
|
||||||
SET_USER_ROLE = 'SET_USER_ROLE',
|
SET_USER_ROLE = 'SET_USER_ROLE',
|
||||||
@ -50,4 +51,5 @@ export enum RIGHTS {
|
|||||||
CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
|
CREATE_CONTRIBUTION_LINK = 'CREATE_CONTRIBUTION_LINK',
|
||||||
DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
|
DELETE_CONTRIBUTION_LINK = 'DELETE_CONTRIBUTION_LINK',
|
||||||
UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
|
UPDATE_CONTRIBUTION_LINK = 'UPDATE_CONTRIBUTION_LINK',
|
||||||
|
ADMIN_CREATE_CONTRIBUTION_MESSAGE = 'ADMIN_CREATE_CONTRIBUTION_MESSAGE',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ export const ROLE_USER = new Role('user', [
|
|||||||
RIGHTS.SEARCH_ADMIN_USERS,
|
RIGHTS.SEARCH_ADMIN_USERS,
|
||||||
RIGHTS.LIST_CONTRIBUTION_LINKS,
|
RIGHTS.LIST_CONTRIBUTION_LINKS,
|
||||||
RIGHTS.COMMUNITY_STATISTICS,
|
RIGHTS.COMMUNITY_STATISTICS,
|
||||||
|
RIGHTS.CREATE_CONTRIBUTION_MESSAGE,
|
||||||
])
|
])
|
||||||
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights
|
export const ROLE_ADMIN = new Role('admin', Object.values(RIGHTS)) // all rights
|
||||||
|
|
||||||
|
|||||||
11
backend/src/graphql/arg/ContributionMessageArgs.ts
Normal file
11
backend/src/graphql/arg/ContributionMessageArgs.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { ArgsType, Field, InputType } from 'type-graphql'
|
||||||
|
|
||||||
|
@InputType()
|
||||||
|
@ArgsType()
|
||||||
|
export default class ContributionMessageArgs {
|
||||||
|
@Field(() => Number)
|
||||||
|
contributionId: number
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
message: string
|
||||||
|
}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import { ObjectType, Field, Int } from 'type-graphql'
|
import { ObjectType, Field, Int } from 'type-graphql'
|
||||||
import Decimal from 'decimal.js-light'
|
import Decimal from 'decimal.js-light'
|
||||||
import { Contribution as dbContribution } from '@entity/Contribution'
|
import { Contribution as dbContribution } from '@entity/Contribution'
|
||||||
import { User } from './User'
|
import { User } from '@entity/User'
|
||||||
|
import { ContributionMessage } from './ContributionMessage'
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
export class Contribution {
|
export class Contribution {
|
||||||
@ -16,6 +17,10 @@ export class Contribution {
|
|||||||
this.confirmedAt = contribution.confirmedAt
|
this.confirmedAt = contribution.confirmedAt
|
||||||
this.confirmedBy = contribution.confirmedBy
|
this.confirmedBy = contribution.confirmedBy
|
||||||
this.contributionDate = contribution.contributionDate
|
this.contributionDate = contribution.contributionDate
|
||||||
|
this.state = contribution.contributionStatus
|
||||||
|
this.messages = contribution.messages
|
||||||
|
? contribution.messages.map((message) => new ContributionMessage(message, user))
|
||||||
|
: []
|
||||||
}
|
}
|
||||||
|
|
||||||
@Field(() => Number)
|
@Field(() => Number)
|
||||||
@ -47,6 +52,12 @@ export class Contribution {
|
|||||||
|
|
||||||
@Field(() => Date)
|
@Field(() => Date)
|
||||||
contributionDate: Date
|
contributionDate: Date
|
||||||
|
|
||||||
|
@Field(() => [ContributionMessage])
|
||||||
|
messages: ContributionMessage[]
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
state: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ObjectType()
|
@ObjectType()
|
||||||
|
|||||||
37
backend/src/graphql/model/ContributionMessage.ts
Normal file
37
backend/src/graphql/model/ContributionMessage.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { Field, ObjectType } from 'type-graphql'
|
||||||
|
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||||
|
import { User } from '@entity/User'
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class ContributionMessage {
|
||||||
|
constructor(contributionMessage: DbContributionMessage, user: User) {
|
||||||
|
this.id = contributionMessage.id
|
||||||
|
this.message = contributionMessage.message
|
||||||
|
this.createdAt = contributionMessage.createdAt
|
||||||
|
this.updatedAt = contributionMessage.updatedAt
|
||||||
|
this.type = contributionMessage.type
|
||||||
|
this.userFirstName = user.firstName
|
||||||
|
this.userLastName = user.lastName
|
||||||
|
}
|
||||||
|
|
||||||
|
@Field(() => Number)
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
message: string
|
||||||
|
|
||||||
|
@Field(() => Date)
|
||||||
|
createdAt: Date
|
||||||
|
|
||||||
|
@Field(() => Date, { nullable: true })
|
||||||
|
updatedAt?: Date | null
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
type: string
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
userFirstName: string | null
|
||||||
|
|
||||||
|
@Field(() => String, { nullable: true })
|
||||||
|
userLastName: string | null
|
||||||
|
}
|
||||||
@ -62,6 +62,10 @@ import {
|
|||||||
MEMO_MAX_CHARS,
|
MEMO_MAX_CHARS,
|
||||||
MEMO_MIN_CHARS,
|
MEMO_MIN_CHARS,
|
||||||
} from './const/const'
|
} from './const/const'
|
||||||
|
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||||
|
import ContributionMessageArgs from '@arg/ContributionMessageArgs'
|
||||||
|
import { ContributionMessageType } from '@enum/MessageType'
|
||||||
|
import { ContributionMessage } from '@model/ContributionMessage'
|
||||||
|
|
||||||
// const EMAIL_OPT_IN_REGISTER = 1
|
// const EMAIL_OPT_IN_REGISTER = 1
|
||||||
// const EMAIL_OPT_UNKNOWN = 3 // elopage?
|
// const EMAIL_OPT_UNKNOWN = 3 // elopage?
|
||||||
@ -696,4 +700,46 @@ export class AdminResolver {
|
|||||||
logger.debug(`updateContributionLink successful!`)
|
logger.debug(`updateContributionLink successful!`)
|
||||||
return new ContributionLink(dbContributionLink)
|
return new ContributionLink(dbContributionLink)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Authorized([RIGHTS.ADMIN_CREATE_CONTRIBUTION_MESSAGE])
|
||||||
|
@Mutation(() => ContributionMessage)
|
||||||
|
async adminCreateContributionMessage(
|
||||||
|
@Args() { contributionId, message }: ContributionMessageArgs,
|
||||||
|
@Ctx() context: Context,
|
||||||
|
): Promise<ContributionMessage> {
|
||||||
|
const user = getUser(context)
|
||||||
|
const queryRunner = getConnection().createQueryRunner()
|
||||||
|
await queryRunner.connect()
|
||||||
|
await queryRunner.startTransaction('READ UNCOMMITTED')
|
||||||
|
const contributionMessage = DbContributionMessage.create()
|
||||||
|
try {
|
||||||
|
const contribution = await Contribution.findOne({ id: contributionId })
|
||||||
|
if (!contribution) {
|
||||||
|
throw new Error('Contribution not found')
|
||||||
|
}
|
||||||
|
contributionMessage.contributionId = contributionId
|
||||||
|
contributionMessage.createdAt = new Date()
|
||||||
|
contributionMessage.message = message
|
||||||
|
contributionMessage.userId = user.id
|
||||||
|
contributionMessage.type = ContributionMessageType.DIALOG
|
||||||
|
await queryRunner.manager.insert(DbContributionMessage, contributionMessage)
|
||||||
|
|
||||||
|
if (
|
||||||
|
contribution.contributionStatus === ContributionStatus.DELETED ||
|
||||||
|
contribution.contributionStatus === ContributionStatus.DENIED ||
|
||||||
|
contribution.contributionStatus === ContributionStatus.PENDING
|
||||||
|
) {
|
||||||
|
contribution.contributionStatus = ContributionStatus.IN_PROGRESS
|
||||||
|
await queryRunner.manager.update(Contribution, { id: contributionId }, contribution)
|
||||||
|
}
|
||||||
|
await queryRunner.commitTransaction()
|
||||||
|
} catch (e) {
|
||||||
|
await queryRunner.rollbackTransaction()
|
||||||
|
logger.error(`ContributionMessage was not successful: ${e}`)
|
||||||
|
throw new Error(`ContributionMessage was not successful: ${e}`)
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release()
|
||||||
|
}
|
||||||
|
return new ContributionMessage(contributionMessage, user)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
backend/src/graphql/resolver/ContributionMessageResolver.ts
Normal file
56
backend/src/graphql/resolver/ContributionMessageResolver.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { backendLogger as logger } from '@/server/logger'
|
||||||
|
import { RIGHTS } from '@/auth/RIGHTS'
|
||||||
|
import { Context, getUser } from '@/server/context'
|
||||||
|
import { ContributionMessage as DbContributionMessage } from '@entity/ContributionMessage'
|
||||||
|
import { Args, Authorized, Ctx, Mutation, Resolver } from 'type-graphql'
|
||||||
|
import ContributionMessageArgs from '@arg/ContributionMessageArgs'
|
||||||
|
import { Contribution } from '@entity/Contribution'
|
||||||
|
import { ContributionMessageType } from '@enum/MessageType'
|
||||||
|
import { ContributionStatus } from '@enum/ContributionStatus'
|
||||||
|
import { getConnection } from '@dbTools/typeorm'
|
||||||
|
import { ContributionMessage } from '@model/ContributionMessage'
|
||||||
|
|
||||||
|
@Resolver()
|
||||||
|
export class ContributionMessageResolver {
|
||||||
|
@Authorized([RIGHTS.CREATE_CONTRIBUTION_MESSAGE])
|
||||||
|
@Mutation(() => ContributionMessage)
|
||||||
|
async createContributionMessage(
|
||||||
|
@Args() { contributionId, message }: ContributionMessageArgs,
|
||||||
|
@Ctx() context: Context,
|
||||||
|
): Promise<ContributionMessage> {
|
||||||
|
const user = getUser(context)
|
||||||
|
const queryRunner = getConnection().createQueryRunner()
|
||||||
|
await queryRunner.connect()
|
||||||
|
await queryRunner.startTransaction('READ UNCOMMITTED')
|
||||||
|
const contributionMessage = DbContributionMessage.create()
|
||||||
|
try {
|
||||||
|
const contribution = await Contribution.findOne({ id: contributionId })
|
||||||
|
if (!contribution) {
|
||||||
|
throw new Error('Contribution not found')
|
||||||
|
}
|
||||||
|
if (contribution.userId !== user.id) {
|
||||||
|
throw new Error('Can not send message to contribution of another user')
|
||||||
|
}
|
||||||
|
|
||||||
|
contributionMessage.contributionId = contributionId
|
||||||
|
contributionMessage.createdAt = new Date()
|
||||||
|
contributionMessage.message = message
|
||||||
|
contributionMessage.userId = user.id
|
||||||
|
contributionMessage.type = ContributionMessageType.DIALOG
|
||||||
|
await queryRunner.manager.insert(DbContributionMessage, contributionMessage)
|
||||||
|
|
||||||
|
if (contribution.contributionStatus === ContributionStatus.IN_PROGRESS) {
|
||||||
|
contribution.contributionStatus = ContributionStatus.PENDING
|
||||||
|
await queryRunner.manager.update(Contribution, { id: contributionId }, contribution)
|
||||||
|
}
|
||||||
|
await queryRunner.commitTransaction()
|
||||||
|
} catch (e) {
|
||||||
|
await queryRunner.rollbackTransaction()
|
||||||
|
logger.error(`ContributionMessage was not successful: ${e}`)
|
||||||
|
throw new Error(`ContributionMessage was not successful: ${e}`)
|
||||||
|
} finally {
|
||||||
|
await queryRunner.release()
|
||||||
|
}
|
||||||
|
return new ContributionMessage(contributionMessage, user)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -96,13 +96,14 @@ export class ContributionResolver {
|
|||||||
order: {
|
order: {
|
||||||
createdAt: order,
|
createdAt: order,
|
||||||
},
|
},
|
||||||
|
relations: ['messages'],
|
||||||
withDeleted: true,
|
withDeleted: true,
|
||||||
skip: (currentPage - 1) * pageSize,
|
skip: (currentPage - 1) * pageSize,
|
||||||
take: pageSize,
|
take: pageSize,
|
||||||
})
|
})
|
||||||
return new ContributionListResult(
|
return new ContributionListResult(
|
||||||
count,
|
count,
|
||||||
contributions.map((contribution) => new Contribution(contribution, new User(user))),
|
contributions.map((contribution) => new Contribution(contribution, user)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,9 +124,7 @@ export class ContributionResolver {
|
|||||||
.getManyAndCount()
|
.getManyAndCount()
|
||||||
return new ContributionListResult(
|
return new ContributionListResult(
|
||||||
count,
|
count,
|
||||||
dbContributions.map(
|
dbContributions.map((contribution) => new Contribution(contribution, contribution.user)),
|
||||||
(contribution) => new Contribution(contribution, new User(contribution.user)),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -206,6 +206,16 @@ export const listContributions = gql`
|
|||||||
confirmedAt
|
confirmedAt
|
||||||
confirmedBy
|
confirmedBy
|
||||||
deletedAt
|
deletedAt
|
||||||
|
state
|
||||||
|
messages {
|
||||||
|
id
|
||||||
|
message
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
type
|
||||||
|
userFirstName
|
||||||
|
userLastName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user