diff options
| author | Murtaza Sultani <sultani@data-quest.de> | 2025-07-30 09:48:20 +0200 |
|---|---|---|
| committer | David Siegfried <david.siegfried@uni-vechta.de> | 2025-07-30 07:48:20 +0000 |
| commit | 8b5da1acae37d9bc983394c3f27508c24024d69b (patch) | |
| tree | 93360533b83eeff9f6c78e60cedadeb026bcad8e /resources/vue/components/forum/posts | |
| parent | d6ce47b2ea667524acafda4e539a81695158c07d (diff) | |
Resolve "Forum in freien Veranstaltungen sind nicht aufrufbar"issue-5760
Closes #5699
Merge request studip/studip!4371
Diffstat (limited to 'resources/vue/components/forum/posts')
| -rw-r--r-- | resources/vue/components/forum/posts/Post.vue | 22 | ||||
| -rw-r--r-- | resources/vue/components/forum/posts/PostReactionShow.vue | 5 | ||||
| -rw-r--r-- | resources/vue/components/forum/posts/PostReactions.vue | 45 |
3 files changed, 52 insertions, 20 deletions
diff --git a/resources/vue/components/forum/posts/Post.vue b/resources/vue/components/forum/posts/Post.vue index 7ac84f7..523fa51 100644 --- a/resources/vue/components/forum/posts/Post.vue +++ b/resources/vue/components/forum/posts/Post.vue @@ -12,7 +12,9 @@ import {$gettext} from "@/assets/javascripts/lib/gettext"; import LinksPreview from "@/vue/components/LinksPreview.vue"; import UserAvatarDropdown from "../UserAvatarDropdown.vue"; import {userProfileURL} from "../helpers/urls"; +import {useForumConfig} from "../../../store/pinia/forum/ForumConfig"; +const forumConfig = useForumConfig(); const forumDiscussionPost = useForumPost(); const props = defineProps({ discussion: { @@ -107,7 +109,7 @@ const removePostHighlight = id => { <template> <div :id="'post_'+post.id" class="post" @click="removePostHighlight('post_'+post.id)"> - <div v-if="isUnread" class="post__unread"> + <div v-if="!forumConfig.allowGuestAccess && isUnread" class="post__unread"> </div> <div class="post__body"> <div class="post__author"> @@ -178,7 +180,7 @@ const removePostHighlight = id => { <a :href="`#create_form_${post.id}`" class="ballon-action__button" - v-if="!postCreateForm && !discussion.closed_at" + v-if="!forumConfig.allowGuestAccess && !postCreateForm && !discussion.closed_at" @click="postCreateForm = true; postContent.removeSelection()" :title="$gettext('Auswahl zitieren und antworten')" :aria-label="$gettext('Auswahl zitieren und antworten')" @@ -208,7 +210,7 @@ const removePostHighlight = id => { <div class="post__footer"> <div></div> <div class="inline-flex items-center gap-40"> - <div v-if="!discussion.closed_at" class="inline-flex items-center gap-10"> + <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}`" @@ -230,9 +232,19 @@ const removePostHighlight = id => { <button type="button" @click="forwardPost(post)" class="button button--icon-only" :title="$gettext('Beitrage weiterleiten')" :aria-label="$gettext('Beitrage weiterleiten')"> <StudipIcon shape="export" :size="20" aria-hidden="true" /> </button> - <button :disabled="postCreateForm" @click="addReply(post)" type="button" class="button button--icon-only" :title="$gettext('Zitieren und antworten')" :aria-label="$gettext('Zitieren und Antworten')"> + <a + :href="`#create_form_${post.id}`" + @click="addReply(post)" + type="button" + class="button button--icon-only" + :class="{ + 'disabled': postCreateForm + }" + :title="$gettext('Zitieren und antworten')" + :aria-label="$gettext('Zitieren und Antworten')" + > <StudipIcon shape="quote" :size="20" aria-hidden="true" /> - </button> + </a> </div> </div> </div> diff --git a/resources/vue/components/forum/posts/PostReactionShow.vue b/resources/vue/components/forum/posts/PostReactionShow.vue index a15df91..8ad13a2 100644 --- a/resources/vue/components/forum/posts/PostReactionShow.vue +++ b/resources/vue/components/forum/posts/PostReactionShow.vue @@ -81,6 +81,7 @@ onMounted(() => { <div class="user-reaction"> <UserAvatarDropdown size="30px" + v-if="reaction.user.id" :user="{ id: reaction.user.id, username: reaction.user.username, @@ -94,6 +95,7 @@ onMounted(() => { </td> <td> <a + v-if="reaction.user.id" :href="userProfileURL(reaction.user.username)" :title="$gettext('Zum Profil')" :aria-label="$gettext('Zum Profil von %{name}', { name: reaction.user.formatted_name })" @@ -101,6 +103,9 @@ onMounted(() => { > {{ reaction.user.formatted_name }} </a> + <p v-else class="author-name"> + {{ $gettext('Unbekannt') }} + </p> </td> <td> <StudipDateTime :iso="reaction.mkdate" :relative="true" /> diff --git a/resources/vue/components/forum/posts/PostReactions.vue b/resources/vue/components/forum/posts/PostReactions.vue index c93bacf..eff8d6b 100644 --- a/resources/vue/components/forum/posts/PostReactions.vue +++ b/resources/vue/components/forum/posts/PostReactions.vue @@ -9,7 +9,9 @@ import {deserializeJSONAPIResponse} from "../../../../assets/javascripts/lib/jso import StudipIcon from "../../StudipIcon.vue"; import PostReactionShow from "./PostReactionShow.vue"; import StudipDialog from "../../StudipDialog.vue"; +import {useForumConfig} from "../../../store/pinia/forum/ForumConfig"; +const forumConfig = useForumConfig(); const forumDiscussionPost = useForumPost(); const props = defineProps({ posting_id: { @@ -26,7 +28,14 @@ const props = defineProps({ const showReactions = ref(false); const reactionStatusMessage = ref(null); -const groupedReactions = computed(() => Object.groupBy(props.reactions, ({ emoji }) => emoji)); +const transformedReactions = computed(() => props.reactions.map(reaction => { + return { + ...reaction, + ...(!reaction?.user ? { user: { formatted_name: $gettext('Unbekannt') } } : {}) + } +})); + +const groupedReactions = computed(() => Object.groupBy(transformedReactions.value, ({ emoji }) => emoji)); const announceToScreenReader = message => reactionStatusMessage.value.textContent = message; @@ -74,7 +83,11 @@ const deleteReaction = async (reactionId) => { } } -const toggleReaction = async (emoji, reactions = props.reactions) => { +const toggleReaction = async (emoji, reactions = transformedReactions.value) => { + if (forumConfig.allowGuestAccess) { + return; + } + const userReaction = findUserReaction(emoji, reactions); if (userReaction) { @@ -86,7 +99,7 @@ const toggleReaction = async (emoji, reactions = props.reactions) => { } } -const findUserReaction = (emoji, reactions = props.reactions) => reactions.find(reaction => reaction.user.id === STUDIP.USER_ID && reaction.emoji === emoji); +const findUserReaction = (emoji, reactions = transformedReactions.value) => reactions.find(reaction => reaction.user.id === STUDIP.USER_ID && reaction.emoji === emoji); const reactionCreate = useTemplateRef('reactionCreate'); useDetectOutsideClick(reactionCreate, () => showReactions.value = false); @@ -101,11 +114,11 @@ const reactionShowDialog = reactive({ <div class="post-reactions-container"> <div aria-live="polite" class="sr-only" role="status" ref="reactionStatusMessage"></div> - <template v-if="reactions.length"> + <template v-if="transformedReactions.length"> <template v-for="(reaction, emoji) in groupedReactions" :key="emoji"> <button type="button" - class="post-reaction as-link" + class="post-reaction" :class="{ '--active': findUserReaction(emoji, reaction) }" @@ -120,21 +133,23 @@ const reactionShowDialog = reactive({ <div ref="reactionCreate" class="post-reactions"> <div class="post-reactions__button-group"> <button + v-if="!forumConfig.allowGuestAccess" type="button" - class="post-reactions__add-reaction as-link" + class="post-reactions__add-reaction" :title="$gettext('Reagieren')" :aria-label="$gettext('Reagieren')" + :aria-pressed="showReactions" @click="showReactions = !showReactions"> <StudipIcon shape="add-reaction" class="add-reaction-icon" :size="18" /> </button> <button - v-if="reactions.length" + v-if="transformedReactions.length" type="button" - class="post-reactions__show-reactions as-link" + class="post-reactions__show-reactions" :title="$gettext('Reaktionen anzeigen')" - :aria-label="$gettext('%{count} Reaktionen anzeigen', { count: reactions.length })" + :aria-label="$gettext('%{count} Reaktionen anzeigen', { count: transformedReactions.length })" @click="reactionShowDialog.isOpen = true"> - {{ numberFormatter(reactions.length, 1) }} + {{ numberFormatter(transformedReactions.length, 1) }} </button> </div> <Transition name="fade"> @@ -158,7 +173,7 @@ const reactionShowDialog = reactive({ </div> <StudipDialog - v-if="reactionShowDialog.isOpen && reactions.length" + v-if="reactionShowDialog.isOpen && transformedReactions.length" :title="$gettext('Reaktionen anzeigen')" :closeText="$gettext('Schließen')" closeClass="cancel" @@ -178,9 +193,9 @@ const reactionShowDialog = reactive({ value="all" v-model="reactionShowDialog.emoji" /> - <label for="reaction-all" :class="{ 'is-checked': reactionShowDialog.emoji === 'all' }"> + <label class="button-base" for="reaction-all" :class="{ 'active': reactionShowDialog.emoji === 'all' }"> {{ $gettext('Alle') }} - <span>{{ numberFormatter(reactions.length, 1) }}</span> + <span>{{ numberFormatter(transformedReactions.length, 1) }}</span> </label> </div> <div @@ -195,7 +210,7 @@ const reactionShowDialog = reactive({ :value="emoji" v-model="reactionShowDialog.emoji" /> - <label :for="`reaction-${emoji}`" :class="{ 'is-checked': reactionShowDialog.emoji === emoji }"> + <label class="button-base" :for="`reaction-${emoji}`" :class="{ 'active': reactionShowDialog.emoji === emoji }"> <span class="emoji-icon" v-html="REACTION_ICONS[emoji].icon" aria-hidden="true"></span> <span class="sr-only">{{ emoji }}</span> <span>{{ numberFormatter(reaction.length, 1) }}</span> @@ -203,7 +218,7 @@ const reactionShowDialog = reactive({ </div> </div> <div class="tab__content"> - <PostReactionShow :reactions="reactions" :emoji="reactionShowDialog.emoji" /> + <PostReactionShow :reactions="transformedReactions" :emoji="reactionShowDialog.emoji" /> </div> </div> </div> |
