diff options
| author | Murtaza Sultani <sultani@data-quest.de> | 2025-09-23 09:03:58 +0200 |
|---|---|---|
| committer | Murtaza Sultani <sultani@data-quest.de> | 2025-09-23 09:03:58 +0200 |
| commit | 349521e801bea9a07f1b8ec1b3261cf9077e3788 (patch) | |
| tree | 2bafc06a104520099df6bcdcde55717388b259ed /resources | |
| parent | 2d261197c18af19c78ea66a88877da84692c02a9 (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.vue | 5 | ||||
| -rw-r--r-- | resources/vue/components/forum/posts/Post.vue | 95 | ||||
| -rw-r--r-- | resources/vue/store/pinia/forum/ForumConfig.js | 2 |
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 } } |
