mirror of
https://github.com/IT4Change/gradido.git
synced 2026-03-01 12:44:43 +00:00
request the name of contribution changer (deniedBy, deletedBy, confirmedBy, updatedBy) and show them in admin frontend
This commit is contained in:
parent
f64b37b273
commit
c3acd21a67
@ -6,7 +6,7 @@
|
||||
:icon="type === 'PageCreationConfirm' ? 'x' : 'eye-slash-fill'"
|
||||
aria-label="Help"
|
||||
></b-icon>
|
||||
{{ $t('hide_details') }} {{ row.item.user.firstName }} {{ row.item.user.lastName }}
|
||||
{{ $t('hide_details') }}
|
||||
</b-button>
|
||||
</b-card>
|
||||
</template>
|
||||
|
||||
@ -30,9 +30,9 @@
|
||||
</template>
|
||||
<template #cell(memo)="row">
|
||||
{{ row.value }}
|
||||
<small v-if="row.item.updatedBy > 0">
|
||||
<small v-if="isAddCommentToMemo(row.item)">
|
||||
<hr />
|
||||
{{ $t('moderator.memo-modified') }}
|
||||
{{ getMemoComment(row.item) }}
|
||||
</small>
|
||||
</template>
|
||||
<template #cell(editCreation)="row">
|
||||
@ -229,6 +229,27 @@ export default {
|
||||
this.creationUserData = row.item
|
||||
}
|
||||
},
|
||||
isAddCommentToMemo(item) {
|
||||
return item.updatedBy > 0 || item.confirmedBy > 0 || item.deletedBy > 0 || item.deniedBy > 0
|
||||
},
|
||||
getMemoComment(item) {
|
||||
let comment = ''
|
||||
if (item.confirmedBy > 0) {
|
||||
comment = this.$t('contribution.confirmedBy', { name: item.confirmedByUserName })
|
||||
} else if (item.deletedBy > 0) {
|
||||
comment = this.$t('contribution.deletedBy', { name: item.deletedByUserName })
|
||||
} else if (item.deniedBy > 0) {
|
||||
comment = this.$t('contribution.deniedBy', { name: item.deniedByUserName })
|
||||
}
|
||||
|
||||
if (item.updatedBy > 0) {
|
||||
if (comment.length) {
|
||||
comment += ' '
|
||||
}
|
||||
comment += this.$t('moderator.memo-modified', { name: item.updatedByUserName })
|
||||
}
|
||||
return comment
|
||||
},
|
||||
addClipboardListener() {
|
||||
document.addEventListener('copy', this.handleCopy)
|
||||
},
|
||||
|
||||
@ -23,15 +23,20 @@ query adminListContributions(
|
||||
contributionDate
|
||||
confirmedAt
|
||||
confirmedBy
|
||||
confirmedByUserName
|
||||
updatedAt
|
||||
updatedBy
|
||||
updatedBy
|
||||
updatedByUserName
|
||||
contributionStatus
|
||||
messagesCount
|
||||
deniedAt
|
||||
deniedBy
|
||||
deniedByUserName
|
||||
deletedAt
|
||||
deletedBy
|
||||
deletedByUserName
|
||||
moderatorId
|
||||
moderatorUserName
|
||||
userId
|
||||
resubmissionAt
|
||||
}
|
||||
|
||||
@ -16,6 +16,11 @@
|
||||
"back": "zurück",
|
||||
"change_user_role": "Nutzerrolle ändern",
|
||||
"close": "Schließen",
|
||||
"contribution": {
|
||||
"confirmedBy": "Bestätigt von {name}.",
|
||||
"deletedBy": "Gelöscht von {name}.",
|
||||
"deniedBy": "Abgelehnt von {name}."
|
||||
},
|
||||
"contributionLink": {
|
||||
"amount": "Betrag",
|
||||
"changeSaved": "Änderungen gespeichert",
|
||||
@ -171,10 +176,11 @@
|
||||
"notice-tooltip": "Die Notiz ist nur für Moderatoren sichtbar",
|
||||
"memo": "Text ändern",
|
||||
"memo-tooltip": "Den Beitragstext bearbeiten",
|
||||
"memo-modified": "Text vom Moderator bearbeitet.",
|
||||
"memo-modified": "Text von {name} bearbeitet.",
|
||||
"message": "Nachricht",
|
||||
"message-tooltip": "Nachricht an Benutzer schreiben",
|
||||
"request": "Diese Nachricht ist nur für die Moderatoren sichtbar!"
|
||||
"request": "Diese Nachricht ist nur für die Moderatoren sichtbar!",
|
||||
"who": "Wer?"
|
||||
},
|
||||
"name": "Name",
|
||||
"navbar": {
|
||||
|
||||
@ -16,6 +16,11 @@
|
||||
"back": "back",
|
||||
"change_user_role": "Change user role",
|
||||
"close": "Close",
|
||||
"contribution": {
|
||||
"confirmedBy": "Confirmed by {name}.",
|
||||
"deletedBy": "Deleted by {name}.",
|
||||
"deniedBy": "Denied by {name}."
|
||||
},
|
||||
"contributionLink": {
|
||||
"amount": "Amount",
|
||||
"changeSaved": "Changes saved",
|
||||
@ -171,10 +176,11 @@
|
||||
"notice-tooltip": "The note is only visible to moderators",
|
||||
"memo": "Edit text",
|
||||
"memo-tooltip": "Edit the text of the contribution",
|
||||
"memo-modified": "Text edited by moderator",
|
||||
"memo-modified": "Text edited by {name}",
|
||||
"message": "Message",
|
||||
"message-tooltip": "Write message to user",
|
||||
"request": "This message is only visible to the moderators!"
|
||||
"request": "This message is only visible to the moderators!",
|
||||
"who": "Who?"
|
||||
},
|
||||
"name": "Name",
|
||||
"navbar": {
|
||||
|
||||
@ -159,7 +159,11 @@ const baseFields = {
|
||||
class: 'no-select',
|
||||
formatter: formatDateOrDash,
|
||||
},
|
||||
confirmedBy: { key: 'confirmedBy', label: t('moderator.moderator'), class: 'no-select' },
|
||||
confirmedByUserName: {
|
||||
key: 'confirmedByUserName',
|
||||
label: t('moderator.who'),
|
||||
class: 'no-select',
|
||||
},
|
||||
}
|
||||
|
||||
const fields = computed(
|
||||
@ -174,7 +178,7 @@ const fields = computed(
|
||||
baseFields.amount,
|
||||
baseFields.memo,
|
||||
baseFields.contributionDate,
|
||||
{ key: 'moderatorId', label: t('moderator.moderator'), class: 'no-select' },
|
||||
{ key: 'moderatorUserName', label: t('moderator.who'), class: 'no-select' },
|
||||
{ key: 'editCreation', label: t('details') },
|
||||
{ key: 'confirm', label: t('save') },
|
||||
],
|
||||
@ -187,7 +191,7 @@ const fields = computed(
|
||||
baseFields.contributionDate,
|
||||
baseFields.createdAt,
|
||||
baseFields.confirmedAt,
|
||||
baseFields.confirmedBy,
|
||||
baseFields.confirmedByUserName,
|
||||
{ key: 'chatCreation', label: t('details') },
|
||||
],
|
||||
// denied contributions
|
||||
@ -203,7 +207,7 @@ const fields = computed(
|
||||
label: t('contributions.denied'),
|
||||
formatter: formatDateOrDash,
|
||||
},
|
||||
{ key: 'deniedBy', label: t('moderator.moderator') },
|
||||
{ key: 'deniedByUserName', label: t('moderator.who') },
|
||||
{ key: 'chatCreation', label: t('details') },
|
||||
],
|
||||
// deleted contributions
|
||||
@ -219,7 +223,7 @@ const fields = computed(
|
||||
label: t('contributions.deleted'),
|
||||
formatter: formatDateOrDash,
|
||||
},
|
||||
{ key: 'deletedBy', label: t('moderator.moderator') },
|
||||
{ key: 'deletedByUserName', label: t('moderator.who') },
|
||||
{ key: 'chatCreation', label: t('details') },
|
||||
],
|
||||
// all contributions
|
||||
@ -232,7 +236,7 @@ const fields = computed(
|
||||
baseFields.contributionDate,
|
||||
baseFields.createdAt,
|
||||
baseFields.confirmedAt,
|
||||
baseFields.confirmedBy,
|
||||
baseFields.confirmedByUserName,
|
||||
{ key: 'chatCreation', label: t('details') },
|
||||
],
|
||||
][tabIndex.value],
|
||||
|
||||
@ -60,6 +60,7 @@
|
||||
"core": "*",
|
||||
"cors": "^2.8.5",
|
||||
"database": "*",
|
||||
"dataloader": "^2.2.3",
|
||||
"decimal.js-light": "^2.5.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"esbuild": "^0.25.2",
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Contribution as DbContribution } from 'database'
|
||||
import { Field, Int, ObjectType } from 'type-graphql'
|
||||
|
||||
import { UnconfirmedContribution } from './UnconfirmedContribution'
|
||||
|
||||
@ObjectType()
|
||||
@ -8,6 +7,7 @@ export class Contribution extends UnconfirmedContribution {
|
||||
constructor(dbContribution: DbContribution) {
|
||||
super(dbContribution)
|
||||
this.createdAt = dbContribution.createdAt
|
||||
this.moderatorId = dbContribution.moderatorId
|
||||
this.confirmedAt = dbContribution.confirmedAt
|
||||
this.confirmedBy = dbContribution.confirmedBy
|
||||
this.contributionDate = dbContribution.contributionDate
|
||||
@ -24,30 +24,48 @@ export class Contribution extends UnconfirmedContribution {
|
||||
@Field(() => Date)
|
||||
createdAt: Date
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
moderatorId: number | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
moderatorUserName?: string | null
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
confirmedAt: Date | null
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
confirmedBy: number | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
confirmedByUserName?: string | null
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deniedAt: Date | null
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
deniedBy: number | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
deniedByUserName?: string | null
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt: Date | null
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
deletedBy: number | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
deletedByUserName?: string | null
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
updatedAt: Date | null
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
updatedBy: number | null
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
updatedByUserName?: string | null
|
||||
|
||||
@Field(() => Date)
|
||||
contributionDate: Date
|
||||
|
||||
|
||||
@ -23,9 +23,11 @@ import {
|
||||
Contribution as DbContribution,
|
||||
Transaction as DbTransaction,
|
||||
User as DbUser,
|
||||
findUserNamesByIds,
|
||||
getLastTransaction,
|
||||
UserContact,
|
||||
} from 'database'
|
||||
import DataLoader from 'dataloader'
|
||||
import { Decimal } from 'decimal.js-light'
|
||||
import { GraphQLResolveInfo } from 'graphql'
|
||||
import { getLogger } from 'log4js'
|
||||
@ -348,6 +350,7 @@ export class ContributionResolver {
|
||||
): Promise<ContributionListResult> {
|
||||
// Check if only count was requested (without contributionList)
|
||||
const fields = Object.keys(extractGraphQLFields(info))
|
||||
// console.log(`fields: ${fields}`)
|
||||
const countOnly: boolean = fields.includes('contributionCount') && fields.length === 1
|
||||
// check if related user was requested
|
||||
const userRequested =
|
||||
@ -370,8 +373,32 @@ export class ContributionResolver {
|
||||
},
|
||||
countOnly,
|
||||
)
|
||||
const result = new ContributionListResult(count, dbContributions)
|
||||
|
||||
return new ContributionListResult(count, dbContributions)
|
||||
const dataLoader = new DataLoader(async (userIds: readonly number[]) => {
|
||||
const uniqueUserIds = new Set<number>()
|
||||
userIds.forEach((userId) => uniqueUserIds.add(userId))
|
||||
const users = await findUserNamesByIds(Array.from(uniqueUserIds))
|
||||
return userIds.map((userId) => users.get(userId))
|
||||
})
|
||||
for (const contribution of result.contributionList) {
|
||||
if (contribution.confirmedBy) {
|
||||
contribution.confirmedByUserName = await dataLoader.load(contribution.confirmedBy)
|
||||
}
|
||||
if (contribution.updatedBy) {
|
||||
contribution.updatedByUserName = await dataLoader.load(contribution.updatedBy)
|
||||
}
|
||||
if (contribution.moderatorId) {
|
||||
contribution.moderatorUserName = await dataLoader.load(contribution.moderatorId)
|
||||
}
|
||||
if (contribution.deletedBy) {
|
||||
contribution.deletedByUserName = await dataLoader.load(contribution.deletedBy)
|
||||
}
|
||||
if (contribution.deniedBy) {
|
||||
contribution.deniedByUserName = await dataLoader.load(contribution.deniedBy)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@Authorized([RIGHTS.ADMIN_DELETE_CONTRIBUTION])
|
||||
|
||||
3
bun.lock
3
bun.lock
@ -122,6 +122,7 @@
|
||||
"core": "*",
|
||||
"cors": "^2.8.5",
|
||||
"database": "*",
|
||||
"dataloader": "^2.2.3",
|
||||
"decimal.js-light": "^2.5.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"esbuild": "^0.25.2",
|
||||
@ -1808,6 +1809,8 @@
|
||||
|
||||
"database": ["database@workspace:database"],
|
||||
|
||||
"dataloader": ["dataloader@2.2.3", "", {}, "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA=="],
|
||||
|
||||
"date-fns": ["date-fns@2.30.0", "", { "dependencies": { "@babel/runtime": "^7.21.0" } }, "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw=="],
|
||||
|
||||
"date-format": ["date-format@4.0.14", "", {}, "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg=="],
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getLogger } from 'log4js'
|
||||
import { aliasSchema, emailSchema, uuidv4Schema } from 'shared'
|
||||
import { Raw } from 'typeorm'
|
||||
import { In, Raw } from 'typeorm'
|
||||
import { User as DbUser, UserContact as DbUserContact } from '../entity'
|
||||
import { findWithCommunityIdentifier, LOG4JS_QUERIES_CATEGORY_NAME } from './index'
|
||||
|
||||
@ -81,3 +81,19 @@ export async function findForeignUserByUuids(
|
||||
where: { foreign: true, communityUuid, gradidoID },
|
||||
})
|
||||
}
|
||||
|
||||
export async function findUserNamesByIds(userIds: number[]): Promise<Map<number, string>> {
|
||||
const users = await DbUser.find({
|
||||
select: { id: true, firstName: true, lastName: true, alias: true },
|
||||
where: { id: In(userIds) },
|
||||
})
|
||||
return new Map(
|
||||
users.map((user) => {
|
||||
let name = `${user.firstName} ${user.lastName}`
|
||||
if (user.alias && user.alias.length > 2) {
|
||||
name = user.alias
|
||||
}
|
||||
return [user.id, name]
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user