aboutsummaryrefslogtreecommitdiff
path: root/resources/vue/components/forum/posts
diff options
context:
space:
mode:
Diffstat (limited to 'resources/vue/components/forum/posts')
-rw-r--r--resources/vue/components/forum/posts/Post.vue22
-rw-r--r--resources/vue/components/forum/posts/PostReactionShow.vue5
-rw-r--r--resources/vue/components/forum/posts/PostReactions.vue45
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>