From 3cc68c76d26e56bdb1bb59ada2c7490208a79ccf Mon Sep 17 00:00:00 2001
From: Murtaza Sultani
Date: Wed, 16 Jul 2025 10:40:55 +0200
Subject: Resolve "Forum3: Man kann nicht mehr sehen, wer genau einen Beitrag
auf einen Beitrag reagiert hat"
Closes #5687 and #5731
Merge request studip/studip!4359
---
resources/assets/stylesheets/scss/forum.scss | 214 ++++++++++++++-------
.../stylesheets/scss/personal-notifications.scss | 4 +-
resources/assets/stylesheets/studip.scss | 1 +
resources/vue/apps/forum/categories/Index.vue | 4 +-
resources/vue/apps/forum/categories/Show.vue | 4 +-
resources/vue/apps/forum/discussions/Show.vue | 14 +-
resources/vue/apps/forum/search/Index.vue | 7 +-
resources/vue/apps/forum/topics/Index.vue | 4 +-
resources/vue/components/forum/EmptyForum.vue | 10 +-
.../vue/components/forum/SubscriptionDropdown.vue | 8 +-
.../components/forum/categories/CategoryItem.vue | 6 +-
.../vue/components/forum/categories/Create.vue | 3 +-
.../vue/components/forum/discussions/Create.vue | 4 +-
.../forum/discussions/DiscussionIndex.vue | 2 +-
resources/vue/components/forum/posts/Post.vue | 8 +-
.../vue/components/forum/posts/PostCreateForm.vue | 12 +-
.../vue/components/forum/posts/PostEditForm.vue | 12 +-
.../components/forum/posts/PostReactionShow.vue | 111 +++++++++++
.../vue/components/forum/posts/PostReactions.vue | 95 +++++++--
.../vue/components/forum/topics/CreateTopic.vue | 3 +-
.../vue/components/forum/topics/TopicItem.vue | 6 +-
templates/personal_notifications/notification.php | 2 +-
22 files changed, 397 insertions(+), 137 deletions(-)
create mode 100644 resources/vue/components/forum/posts/PostReactionShow.vue
diff --git a/resources/assets/stylesheets/scss/forum.scss b/resources/assets/stylesheets/scss/forum.scss
index 9c5efc6..4b309a4 100644
--- a/resources/assets/stylesheets/scss/forum.scss
+++ b/resources/assets/stylesheets/scss/forum.scss
@@ -60,6 +60,11 @@ $card-max-width: 300px;
.subscription-button {
background-color: transparent;
border-color: transparent;
+ justify-content: end;
+ padding: 0;
+ &:hover {
+ color: var(--color--highlight);
+ }
}
}
@@ -216,37 +221,6 @@ $card-max-width: 300px;
}
}
- .icon-button {
- display: flex;
- align-items: center;
- justify-content: center;
- background: white;
- border: 1px solid var(--color--highlight);
- color: var(--color--highlight);
- border-radius: 5px;
- padding: 7px;
- cursor: pointer;
-
- &.--with-label {
- padding-left: 10px;
- padding-right: 10px;
- }
-
- &:hover {
- background-color: $content-color-10;
- }
-
- &:disabled {
- border-color: var(--color--button-inactive-border);
- opacity: 0.5;
- cursor: not-allowed;
- }
-
- .label {
- margin-left: 5px;
- }
- }
-
button.style-less {
background: no-repeat;
border: none;
@@ -254,23 +228,21 @@ $card-max-width: 300px;
}
.button {
- &.--with-icon {
- display: inline-flex;
- gap: 10px;
+ &--icon-only {
+ min-width: unset;
+ margin: 0;
+ padding: 6px;
+ display: flex;
align-items: center;
+ justify-content: center;
}
- .icon-hover {
- display: none;
- }
-
- &:hover {
- .icon-default {
- display: none;
- }
- .icon-hover {
- display: inline-block;
- }
+ &--icon-label {
+ margin: 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
}
}
@@ -329,26 +301,21 @@ $card-max-width: 300px;
align-items: center;
}
- h3 {
- margin: 0;
- font-size: 16px;
- font-weight: normal;
- }
-
p {
margin-top: 5px;
color: var(--color--font-secondary);
}
}
- .discussion-overview {
- h3 {
- margin-top: 0;
- font-size: 16px;
- font-weight: normal;
- }
+ .topic-title,
+ .category-title,
+ .discussion-title {
+ font-size: 16px;
+ }
+ .discussion-overview {
p {
+ margin-top: 5px;
color: var(--color--font-secondary);
}
@@ -455,15 +422,20 @@ $card-max-width: 300px;
z-index: 1;
}
+ &:hover {
+ .topic-card__title {
+ color: var(--color--highlight-hover);
+ text-decoration: underline;
+ }
+ }
+
&__title {
- margin-top: 0;
- margin-bottom: 10px;
- font-size: 16px;
- font-weight: normal;
+ color: var(--color--highlight);
}
p {
- opacity: 60%;
+ margin-top: 5px;
+ color: var(--color--font-secondary);
}
&__content {
@@ -621,7 +593,12 @@ $card-max-width: 300px;
align-items: center;
justify-content: center;
- &__create-button {
+ &__button-group {
+ display: inline-flex;
+ align-items: center;
+ }
+
+ &__add-reaction {
display: inline-flex;
cursor: pointer;
background: none;
@@ -648,6 +625,11 @@ $card-max-width: 300px;
}
}
+ &__show-reactions {
+ border: none;
+ background: none;
+ }
+
&__container {
position: absolute;
top: -50px;
@@ -776,6 +758,14 @@ $card-max-width: 300px;
}
}
}
+
+ .post-form__footer {
+ margin-top: 20px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 15px;
+ }
}
.user-avatar-dropdown {
@@ -1104,10 +1094,10 @@ $card-max-width: 300px;
border-color: $base-color-60;
}
}
+ }
- .html-emoji {
- font-family: apple color emoji, segoe ui emoji, notocoloremoji, segoe ui symbol, android emoji, emojisymbols, emojione mozilla;
- }
+ .emoji-icon {
+ font-family: apple color emoji, segoe ui emoji, notocoloremoji, segoe ui symbol, android emoji, emojisymbols, emojione mozilla;
}
.forum-subscriptions-dropdown {
@@ -1176,9 +1166,8 @@ $card-max-width: 300px;
.subscription-button {
white-space: nowrap;
+ min-width: unset;
display: inline-flex;
- gap: 6px;
- align-items: center;
}
}
@@ -1488,6 +1477,95 @@ $card-max-width: 300px;
}
}
+ .tab {
+ &__buttons {
+ display: flex;
+ gap: 10px;
+ border-bottom: 2px solid var(--color--divider);
+ }
+
+ &__button {
+ label {
+ position: relative;
+ transition: color 0.3s ease;
+ color: var(--color--highlight);
+ font-weight: bold;
+ padding: 6px 12px;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+
+ &:hover {
+ color: var(--color--highlight-hover);
+
+ &::after {
+ background-color: var(--color--focus);
+ }
+ }
+
+ &:hover,
+ &.is-checked {
+ &::after {
+ content: '';
+ position: absolute;
+ left: 0;
+ bottom: -2px;
+ width: 100%;
+ height: 2px;
+ }
+ }
+
+ &.is-checked {
+ &::after {
+ background-color: var(--color--highlight);
+ }
+ }
+ }
+
+ input[type="radio"] {
+ position: absolute;
+ opacity: 0;
+ width: 0;
+ height: 0;
+ pointer-events: none;
+
+ &:focus + label {
+ outline: 2px solid var(--color--focus);
+ outline-offset: 2px;
+ border-radius: 2px;
+ }
+ }
+
+ }
+
+ &__content {
+ margin-top: 15px;
+ }
+ }
+
+ .post-reactions-dialog {
+ .user-avatar-dropdown {
+ .dropdown__content {
+ right: auto;
+ left: 0;
+ }
+ }
+ }
+
+ .user-reaction {
+ position: relative;
+ width: 35px;
+ height: 35px;
+
+ .emoji-icon {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ z-index: 1;
+ }
+ }
+
/*
vue Transition --start--
*/
diff --git a/resources/assets/stylesheets/scss/personal-notifications.scss b/resources/assets/stylesheets/scss/personal-notifications.scss
index 8d80fbb..1e63488 100644
--- a/resources/assets/stylesheets/scss/personal-notifications.scss
+++ b/resources/assets/stylesheets/scss/personal-notifications.scss
@@ -187,7 +187,7 @@
display: block;
padding: 0;
&:hover {
- color: var(--color--highlight-hover);
+ color: var(--color--highlight-hover);
text-decoration: none;
}
}
@@ -224,7 +224,7 @@
.item:hover .options.hidden { visibility: visible; }
}
- .html-emoji {
+ .emoji-icon {
font-family: apple color emoji, segoe ui emoji, notocoloremoji, segoe ui symbol, android emoji, emojisymbols, emojione mozilla;
font-size: 20px;
margin-right: 10px;
diff --git a/resources/assets/stylesheets/studip.scss b/resources/assets/stylesheets/studip.scss
index d923f64..080ca40 100644
--- a/resources/assets/stylesheets/studip.scss
+++ b/resources/assets/stylesheets/studip.scss
@@ -779,6 +779,7 @@ input.allow-plaintext-toggle {
z-index: 1;
right: 10px;
top: 10px;
+ padding: 0;
display: flex;
align-items: center;
justify-content: center;
diff --git a/resources/vue/apps/forum/categories/Index.vue b/resources/vue/apps/forum/categories/Index.vue
index 51646ba..abb98c0 100644
--- a/resources/vue/apps/forum/categories/Index.vue
+++ b/resources/vue/apps/forum/categories/Index.vue
@@ -127,14 +127,14 @@ const swapCategory = (categoryId, step) => {
v-if="forumConfig.tileLayout"
@click="forumConfig.toggleForumLayout()"
type="button"
- :title="$gettext('Tabellarische Ansicht')" class="icon-button">
+ :title="$gettext('Tabellarische Ansicht')" class="button button--icon-only">
{{ toggleLayoutMessage }}
diff --git a/resources/vue/apps/forum/categories/Show.vue b/resources/vue/apps/forum/categories/Show.vue
index 2445646..4c340cd 100644
--- a/resources/vue/apps/forum/categories/Show.vue
+++ b/resources/vue/apps/forum/categories/Show.vue
@@ -95,7 +95,7 @@ onMounted(async () => {
@click="forumConfig.toggleForumLayout()"
type="button"
:title="$gettext('Tabellarische Ansicht')"
- class="icon-button">
+ class="button button--icon-only">
{{ toggleLayoutMessage }}
diff --git a/resources/vue/apps/forum/discussions/Show.vue b/resources/vue/apps/forum/discussions/Show.vue
index ed5043c..9343047 100644
--- a/resources/vue/apps/forum/discussions/Show.vue
+++ b/resources/vue/apps/forum/discussions/Show.vue
@@ -91,7 +91,7 @@ const fetchPostings = async () => {
`forum-discussions/${props.discussion.discussion_id}/postings`,
{
data: {
- include: 'author,opengraph-urls,posting,reactions,reactions.user&fields[users]=id',
+ include: 'author,opengraph-urls,posting,reactions,reactions.user&fields[users]=id,username,formatted-name',
page: { offset }
}
}
@@ -194,7 +194,7 @@ onMounted(async () => {
-
diff --git a/resources/vue/components/forum/SubscriptionDropdown.vue b/resources/vue/components/forum/SubscriptionDropdown.vue
index c641011..422c0ae 100644
--- a/resources/vue/components/forum/SubscriptionDropdown.vue
+++ b/resources/vue/components/forum/SubscriptionDropdown.vue
@@ -128,7 +128,13 @@ const subscribe = async (notification_type = 'all') => {
-
+
{{ subscriptionButtonLabel }}
diff --git a/resources/vue/components/forum/categories/CategoryItem.vue b/resources/vue/components/forum/categories/CategoryItem.vue
index 55685a7..0035ad1 100644
--- a/resources/vue/components/forum/categories/CategoryItem.vue
+++ b/resources/vue/components/forum/categories/CategoryItem.vue
@@ -74,7 +74,7 @@ const swapCategory = event => {
class="title-with-actions__link"
:href="getCategoryURL(category.id)"
:title="$gettext('Zur Kategorie')">
- {{ category.name }}
+ {{ category.name }}
{
-
+
{{ category.name }}
-
+
diff --git a/resources/vue/components/forum/discussions/Create.vue b/resources/vue/components/forum/discussions/Create.vue
index 1d88d78..ee76c72 100644
--- a/resources/vue/components/forum/discussions/Create.vue
+++ b/resources/vue/components/forum/discussions/Create.vue
@@ -20,8 +20,8 @@ const discussionCreateURL = computed(() => {
:href="discussionCreateURL"
:title="$gettext('Neue Diskussion starten')"
data-dialog="width=900;height=750"
- type="button"
- class="icon-button">
+ role="button"
+ class="button button--icon-only">
diff --git a/resources/vue/components/forum/discussions/DiscussionIndex.vue b/resources/vue/components/forum/discussions/DiscussionIndex.vue
index 86fdf8a..2369888 100644
--- a/resources/vue/components/forum/discussions/DiscussionIndex.vue
+++ b/resources/vue/components/forum/discussions/DiscussionIndex.vue
@@ -167,7 +167,7 @@ onMounted(() => {
class="title-with-actions__link"
:href="getDiscussionURL(discussion.id, {redirect})"
:title="$gettext('Zur Diskussion')">
- {{ discussion.title }}
+ {{ discussion.title }}
{
-
+
-
+
-
+
-
+
diff --git a/resources/vue/components/forum/posts/PostCreateForm.vue b/resources/vue/components/forum/posts/PostCreateForm.vue
index 095413a..00daeba 100644
--- a/resources/vue/components/forum/posts/PostCreateForm.vue
+++ b/resources/vue/components/forum/posts/PostCreateForm.vue
@@ -133,27 +133,25 @@ const storePost = async () => {
-
+
diff --git a/resources/vue/components/forum/posts/PostEditForm.vue b/resources/vue/components/forum/posts/PostEditForm.vue
index 9c50f90..5c9c311 100644
--- a/resources/vue/components/forum/posts/PostEditForm.vue
+++ b/resources/vue/components/forum/posts/PostEditForm.vue
@@ -80,26 +80,24 @@ onUnmounted(() => {
-
+
diff --git a/resources/vue/components/forum/posts/PostReactionShow.vue b/resources/vue/components/forum/posts/PostReactionShow.vue
new file mode 100644
index 0000000..a15df91
--- /dev/null
+++ b/resources/vue/components/forum/posts/PostReactionShow.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
diff --git a/resources/vue/components/forum/posts/PostReactions.vue b/resources/vue/components/forum/posts/PostReactions.vue
index 816ed15..49d6025 100644
--- a/resources/vue/components/forum/posts/PostReactions.vue
+++ b/resources/vue/components/forum/posts/PostReactions.vue
@@ -1,5 +1,5 @@
@@ -104,21 +112,31 @@ useDetectOutsideClick(reactionCreate, () => showReactions.value = false);
:title="findUserReaction(emoji, reaction) ? $gettext('Reaktion zurücknehmen') : $gettext('Reaktion hinzufügen')"
:aria-label="findUserReaction(emoji, reaction) ? $gettext('Reaktion zurücknehmen') : $gettext('Reaktion hinzufügen')"
@click="toggleReaction(emoji, reaction)">
-
+
{{ numberFormatter(reaction.length, 1) }}
-
-
- {{ numberFormatter(reactions.length, 1) }}
-
+
+
+
+
+
+ {{ numberFormatter(reactions.length, 1) }}
+
+
@@ -131,11 +149,64 @@ useDetectOutsideClick(reactionCreate, () => showReactions.value = false);
:aria-label="$gettext('Auf diesen Beitrag mit %{emojiName} reagieren', { emojiName: emoji.value })"
@click="toggleReaction(emoji.value)"
>
-
+
+
+
+
+
+
+
diff --git a/resources/vue/components/forum/topics/CreateTopic.vue b/resources/vue/components/forum/topics/CreateTopic.vue
index d6d3d5f..03b7542 100644
--- a/resources/vue/components/forum/topics/CreateTopic.vue
+++ b/resources/vue/components/forum/topics/CreateTopic.vue
@@ -28,7 +28,8 @@ const topicCreateURL = computed(() => {
data-dialog="width=700"
:title="$gettext('Neues Thema anlegen')"
:aria-label="$gettext('Neues Thema anlegen')"
- class="icon-button"
+ class="button button--icon-only"
+ :class="label ? 'button--icon-label' : 'button--icon-only'"
role="button"
>
diff --git a/resources/vue/components/forum/topics/TopicItem.vue b/resources/vue/components/forum/topics/TopicItem.vue
index d783524..a499941 100644
--- a/resources/vue/components/forum/topics/TopicItem.vue
+++ b/resources/vue/components/forum/topics/TopicItem.vue
@@ -70,7 +70,7 @@ const swapTopic = event => {