feat(ModerationReports): enhance moderation reports functionality and UI
All checks were successful
Deploy to production / deploy (push) Successful in 2m3s
All checks were successful
Deploy to production / deploy (push) Successful in 2m3s
- Added topic and forum IDs to moderation report queries for better context. - Updated admin interface to include links to open reported forum messages. - Implemented methods to handle opening target messages directly from the moderation reports view. - Enhanced internationalization support for new UI elements in both German and English. - Improved scrolling behavior to focus on specific messages when navigating to them.
This commit is contained in:
@@ -95,6 +95,8 @@ class ModerationService extends BaseService {
|
|||||||
r.id,
|
r.id,
|
||||||
r.target_type AS "targetType",
|
r.target_type AS "targetType",
|
||||||
r.target_id AS "targetId",
|
r.target_id AS "targetId",
|
||||||
|
fm.title_id AS "topicId",
|
||||||
|
ft.forum_id AS "forumId",
|
||||||
r.reason,
|
r.reason,
|
||||||
r.details,
|
r.details,
|
||||||
r.status,
|
r.status,
|
||||||
@@ -106,6 +108,10 @@ class ModerationService extends BaseService {
|
|||||||
FROM community.moderation_report r
|
FROM community.moderation_report r
|
||||||
JOIN community.user reporter ON reporter.id = r.reporter_user_id
|
JOIN community.user reporter ON reporter.id = r.reporter_user_id
|
||||||
LEFT JOIN community.user reviewer ON reviewer.id = r.reviewer_user_id
|
LEFT JOIN community.user reviewer ON reviewer.id = r.reviewer_user_id
|
||||||
|
LEFT JOIN forum.message fm
|
||||||
|
ON r.target_type = 'forum_message'
|
||||||
|
AND fm.id = r.target_id
|
||||||
|
LEFT JOIN forum.title ft ON ft.id = fm.title_id
|
||||||
WHERE r.status = :status
|
WHERE r.status = :status
|
||||||
ORDER BY r.created_at DESC
|
ORDER BY r.created_at DESC
|
||||||
LIMIT :limit
|
LIMIT :limit
|
||||||
|
|||||||
@@ -547,7 +547,9 @@
|
|||||||
"in_review": "In Prüfung",
|
"in_review": "In Prüfung",
|
||||||
"resolved": "Erledigt",
|
"resolved": "Erledigt",
|
||||||
"rejected": "Abgelehnt"
|
"rejected": "Abgelehnt"
|
||||||
}
|
},
|
||||||
|
"openTarget": "Zum Beitrag",
|
||||||
|
"targetLink": "Link"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -547,7 +547,9 @@
|
|||||||
"in_review": "In review",
|
"in_review": "In review",
|
||||||
"resolved": "Resolved",
|
"resolved": "Resolved",
|
||||||
"rejected": "Rejected"
|
"rejected": "Rejected"
|
||||||
}
|
},
|
||||||
|
"openTarget": "Open post",
|
||||||
|
"targetLink": "Link"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
<th>{{ $t('admin.moderationReports.reason') }}</th>
|
<th>{{ $t('admin.moderationReports.reason') }}</th>
|
||||||
<th>{{ $t('admin.moderationReports.reporter') }}</th>
|
<th>{{ $t('admin.moderationReports.reporter') }}</th>
|
||||||
<th>{{ $t('admin.moderationReports.createdAt') }}</th>
|
<th>{{ $t('admin.moderationReports.createdAt') }}</th>
|
||||||
|
<th>{{ $t('admin.moderationReports.targetLink') }}</th>
|
||||||
<th>{{ $t('admin.moderationReports.actions') }}</th>
|
<th>{{ $t('admin.moderationReports.actions') }}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@@ -39,6 +40,15 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>{{ report.reporterUsername }}</td>
|
<td>{{ report.reporterUsername }}</td>
|
||||||
<td>{{ formatDateTimeLong(report.createdAt) }}</td>
|
<td>{{ formatDateTimeLong(report.createdAt) }}</td>
|
||||||
|
<td>
|
||||||
|
<button
|
||||||
|
v-if="canOpenTarget(report)"
|
||||||
|
type="button"
|
||||||
|
@click="openTarget(report)"
|
||||||
|
>
|
||||||
|
{{ $t('admin.moderationReports.openTarget') }}
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
<td class="actions-cell">
|
<td class="actions-cell">
|
||||||
<select v-model="draftStatus[report.id]">
|
<select v-model="draftStatus[report.id]">
|
||||||
<option value="open">{{ $t('admin.moderationReports.status.open') }}</option>
|
<option value="open">{{ $t('admin.moderationReports.status.open') }}</option>
|
||||||
@@ -111,6 +121,13 @@ export default {
|
|||||||
showApiError(this, error, this.$t('admin.moderationReports.applyError'));
|
showApiError(this, error, this.$t('admin.moderationReports.applyError'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
canOpenTarget(report) {
|
||||||
|
return report?.targetType === 'forum_message' && Number(report?.topicId) > 0;
|
||||||
|
},
|
||||||
|
openTarget(report) {
|
||||||
|
if (!this.canOpenTarget(report)) return;
|
||||||
|
this.$router.push(`/socialnetwork/forumtopic/${report.topicId}#msg-${report.targetId}`);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<section class="forum-topic-messages">
|
<section class="forum-topic-messages">
|
||||||
<ul class="messages">
|
<ul class="messages">
|
||||||
<li v-for="message in messages" :key="message.id" class="surface-card">
|
<li v-for="message in messages" :key="message.id" :id="`msg-${message.id}`" class="surface-card">
|
||||||
<div v-html="sanitizedMessage(message)"></div>
|
<div v-html="sanitizedMessage(message)"></div>
|
||||||
<div class="footer">
|
<div class="footer">
|
||||||
<span class="footer-left">
|
<span class="footer-left">
|
||||||
@@ -85,6 +85,7 @@ export default {
|
|||||||
this.forumName = data.forum.name;
|
this.forumName = data.forum.name;
|
||||||
this.forumId = data.forum.id;
|
this.forumId = data.forum.id;
|
||||||
this.messages = data.messages;
|
this.messages = data.messages;
|
||||||
|
this.$nextTick(() => this.scrollToHashIfPresent());
|
||||||
},
|
},
|
||||||
async openProfile(id) {
|
async openProfile(id) {
|
||||||
this.$root.$refs.userProfileDialog.userId = id;
|
this.$root.$refs.userProfileDialog.userId = id;
|
||||||
@@ -138,6 +139,14 @@ export default {
|
|||||||
this.$t('error.title')
|
this.$t('error.title')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
scrollToHashIfPresent() {
|
||||||
|
const hash = this.$route?.hash || '';
|
||||||
|
if (!hash || hash.length < 2) return;
|
||||||
|
const el = document.querySelector(hash);
|
||||||
|
if (el && typeof el.scrollIntoView === 'function') {
|
||||||
|
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user