aboutsummaryrefslogtreecommitdiff
path: root/resources
diff options
context:
space:
mode:
authorMurtaza Sultani <sultani@data-quest.de>2025-09-23 09:03:58 +0200
committerMurtaza Sultani <sultani@data-quest.de>2025-09-23 09:03:58 +0200
commit349521e801bea9a07f1b8ec1b3261cf9077e3788 (patch)
tree2bafc06a104520099df6bcdcde55717388b259ed /resources
parent2d261197c18af19c78ea66a88877da84692c02a9 (diff)
Resolve "Forum: Bearbeitungs und Löschrechte für Dozenten und Tutoren hinzufügen"
Closes #5757 Merge request studip/studip!4393
Diffstat (limited to 'resources')
-rw-r--r--resources/vue/components/forum/ForumApp.vue5
-rw-r--r--resources/vue/components/forum/posts/Post.vue95
-rw-r--r--resources/vue/store/pinia/forum/ForumConfig.js2
3 files changed, 62 insertions, 40 deletions
diff --git a/resources/vue/components/forum/ForumApp.vue b/resources/vue/components/forum/ForumApp.vue
index dc0adc0..7a0ea35 100644
--- a/resources/vue/components/forum/ForumApp.vue
+++ b/resources/vue/components/forum/ForumApp.vue
@@ -10,8 +10,9 @@ const fetchConfigs = async () => {
forumConfig.$patch({
isModerator: response.meta['is-moderator'],
isAdmin: response.meta['is-admin'],
+ isTutor: response.meta['is-tutor'],
anonymousPost: response.meta['anonymous-post'],
- tileLayout: response.meta['tile-layout'],
+ tileLayout: response.meta['tile-layout']
});
} catch (error) {
STUDIP.Report.error(error);
@@ -26,7 +27,7 @@ onMounted(async () => {
} else {
await fetchConfigs();
}
-})
+});
</script>
<template>
diff --git a/resources/vue/components/forum/posts/Post.vue b/resources/vue/components/forum/posts/Post.vue
index ed27d6e..1c7e302 100644
--- a/resources/vue/components/forum/posts/Post.vue
+++ b/resources/vue/components/forum/posts/Post.vue
@@ -39,11 +39,12 @@ const postContent = useTemplateRef('postContent');
const userAvatarContainer = useTemplateRef('userAvatarContainer');
const selectedText = ref('');
-const editPost = ref('');
-const postCreateForm = ref(false);
+const showPostEditForm = ref(false);
+const showPostCreateForm = ref(false);
const isUnread = computed(() => (!props.post.author && props.is_unread) || (props.is_unread && props.post.author.id !== STUDIP.USER_ID))
-
+const canEditPost = computed(() => forumConfig.isTutor || (props.post.author?.id === STUDIP.USER_ID && !props.discussion.closed_at));
+const canDeletePost = computed(() => canEditPost.value);
const copyToClipboard = () => {
if (selectedText.value) {
navigator.clipboard.writeText(selectedText.value);
@@ -52,13 +53,25 @@ const copyToClipboard = () => {
}
}
-const deletePost = async (post) => {
+const editPost = () => {
+ if (!canEditPost.value) {
+ return;
+ }
+
+ showPostEditForm.value = true;
+}
+
+const deletePost = async () => {
+ if (!canDeletePost.value) {
+ return;
+ }
+
STUDIP.Dialog.confirm(
$gettext('Wollen Sie diesen Beitrag löschen?'),
async () => {
try {
- await STUDIP.jsonapi.withPromises().DELETE(`forum-postings/${post.id}`);
- forumDiscussionPost.removePost(post.id);
+ await STUDIP.jsonapi.withPromises().DELETE(`forum-postings/${props.post.id}`);
+ forumDiscussionPost.removePost(props.post.id);
STUDIP.Report.success($gettext('Der Beitrag wurde gelöscht.'));
} catch (error) {
STUDIP.Report.error(error);
@@ -69,11 +82,11 @@ const deletePost = async (post) => {
const addPost = () => {
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
- postCreateForm.value = false;
+ showPostCreateForm.value = false;
}
const addReply = post => {
- postCreateForm.value = true;
+ showPostCreateForm.value = true;
selectedText.value = post.content;
}
@@ -98,12 +111,12 @@ const forwardPost = post => {
}
const removePostHighlight = id => {
- const element = document.getElementById(id)
+ const element = document.getElementById(id);
if (!element) {
- console.error("Element not found!")
- return
+ console.error("Element not found!");
+ return;
}
- element.classList.remove('--highlight')
+ element.classList.remove('--highlight');
}
</script>
@@ -170,8 +183,8 @@ const removePostHighlight = id => {
</span>
<StudipDateTime v-else :iso="post.mkdate" :relative="true" />
</div>
- <template v-if="editPost === post.id">
- <PostEditForm :post="post" :auth_user="auth_user" class="mt-10" @canceled="editPost = ''" @updated="editPost = ''"/>
+ <template v-if="showPostEditForm">
+ <PostEditForm :post="post" :auth_user="auth_user" class="mt-10" @canceled="showPostEditForm = false" @updated="showPostEditForm = false"/>
</template>
<template v-else>
<div class="post__text">
@@ -180,8 +193,8 @@ const removePostHighlight = id => {
<a
:href="`#create_form_${post.id}`"
class="ballon-action__button"
- v-if="!forumConfig.allowGuestAccess && !postCreateForm && !discussion.closed_at"
- @click="postCreateForm = true; postContent.removeSelection()"
+ v-if="!forumConfig.allowGuestAccess && !showPostCreateForm && !discussion.closed_at"
+ @click="showPostCreateForm = true; postContent.removeSelection()"
:title="$gettext('Auswahl zitieren und antworten')"
:aria-label="$gettext('Auswahl zitieren und antworten')"
>
@@ -210,35 +223,41 @@ const removePostHighlight = id => {
<div class="post__footer">
<div></div>
<div class="inline-flex items-center gap-40">
- <div v-if="!forumConfig.allowGuestAccess && !discussion.closed_at" class="inline-flex items-center gap-10">
- <template v-if="post.author?.id === auth_user.id">
- <a
- :href="`#post_${post.id}`"
- @click="editPost = post.id"
- type="button"
- class="button button--icon-only"
- :class="{
- 'disabled': editPost === post.id
- }"
- :title="$gettext('Beitrag bearbeiten')"
- :aria-label="$gettext('Beitrag bearbeiten')"
- >
- <StudipIcon shape="edit" :size="20" aria-hidden="true" />
- </a>
- <button @click="deletePost(post)" type="button" class="button button--icon-only" :title="$gettext('Beitrag löschen')" :aria-label="$gettext('Beitrag löschen')">
- <StudipIcon shape="trash" :size="20" aria-hidden="true" />
- </button>
- </template>
+ <div v-if="!forumConfig.allowGuestAccess" class="inline-flex items-center gap-10">
+ <a
+ v-if="canEditPost"
+ :href="`#post_${post.id}`"
+ @click="editPost"
+ type="button"
+ class="button button--icon-only"
+ :class="{
+ 'disabled': showPostEditForm
+ }"
+ :title="$gettext('Beitrag bearbeiten')"
+ :aria-label="$gettext('Beitrag bearbeiten')"
+ >
+ <StudipIcon shape="edit" :size="20" aria-hidden="true" />
+ </a>
+ <button
+ v-if="canDeletePost"
+ @click="deletePost"
+ type="button" class="button button--icon-only"
+ :title="$gettext('Beitrag löschen')"
+ :aria-label="$gettext('Beitrag löschen')"
+ >
+ <StudipIcon shape="trash" :size="20" aria-hidden="true" />
+ </button>
<button type="button" @click="forwardPost(post)" class="button button--icon-only" :title="$gettext('Beitrag weiterleiten')" :aria-label="$gettext('Beitrag weiterleiten')">
<StudipIcon shape="export" :size="20" aria-hidden="true" />
</button>
<a
+ v-if="!discussion.closed_at"
:href="`#create_form_${post.id}`"
@click="addReply(post)"
type="button"
class="button button--icon-only"
:class="{
- 'disabled': postCreateForm
+ 'disabled': showPostCreateForm
}"
:title="$gettext('Zitieren und antworten')"
:aria-label="$gettext('Zitieren und Antworten')"
@@ -251,13 +270,13 @@ const removePostHighlight = id => {
</div>
</div>
</div>
- <div v-if="postCreateForm && !discussion.closed_at" :id="`create_form_${post.id}`" class="post-form-container" style="scroll-margin-top: 200px;">
+ <div v-if="showPostCreateForm && !discussion.closed_at" :id="`create_form_${post.id}`" class="post-form-container" style="scroll-margin-top: 200px;">
<PostCreateForm
:parent_id="post.id"
:discussion_id="props.discussion.discussion_id"
:auth_user="auth_user"
v-model:quote="selectedText"
- @canceled="postCreateForm = false; selectedText = ''"
+ @canceled="showPostCreateForm = false; selectedText = ''"
@created="addPost"
/>
</div>
diff --git a/resources/vue/store/pinia/forum/ForumConfig.js b/resources/vue/store/pinia/forum/ForumConfig.js
index 26b008c..16b028c 100644
--- a/resources/vue/store/pinia/forum/ForumConfig.js
+++ b/resources/vue/store/pinia/forum/ForumConfig.js
@@ -7,6 +7,7 @@ export const useForumConfig = defineStore(
const allowGuestAccess = ref(false);
const isAdmin = ref(false);
const isModerator = ref(false);
+ const isTutor = ref(false);
const anonymousPost = ref(false);
const tileLayout = ref(true);
@@ -32,6 +33,7 @@ export const useForumConfig = defineStore(
isModerator,
anonymousPost,
tileLayout,
+ isTutor,
toggleForumLayout
}
}