diff --git a/client/src/components/ActivityBar/ActivityBar.vue b/client/src/components/ActivityBar/ActivityBar.vue index 9dc3cf03f173..f1aec81e937f 100644 --- a/client/src/components/ActivityBar/ActivityBar.vue +++ b/client/src/components/ActivityBar/ActivityBar.vue @@ -17,8 +17,9 @@ import NotificationItem from "./Items/NotificationItem.vue"; import UploadItem from "./Items/UploadItem.vue"; import ContextMenu from "@/components/Common/ContextMenu.vue"; import FlexPanel from "@/components/Panels/FlexPanel.vue"; +import NotificationsPanel from "@/components/Panels/NotificationsPanel.vue"; import ToolPanel from "@/components/Panels/ToolPanel.vue"; -import WorkflowBox from "@/components/Panels/WorkflowBox.vue"; +import WorkflowPanel from "@/components/Panels/WorkflowPanel.vue"; const { config, isConfigLoaded } = useConfig(); @@ -196,10 +197,9 @@ function toggleContextMenu(evt: MouseEvent) { v-if="!isAnonymous && isConfigLoaded && config.enable_notification_system" id="activity-notifications" icon="bell" - :is-active="isActiveRoute('/user/notifications')" + :is-active="isActiveSideBar('notifications')" title="Notifications" - to="/user/notifications" - @click="onToggleSidebar()" /> + @click="onToggleSidebar('notifications')" /> - + + + + diff --git a/client/src/components/ActivityBar/Items/NotificationItem.vue b/client/src/components/ActivityBar/Items/NotificationItem.vue index 1e2f6fd1b65e..84e5a05bceda 100644 --- a/client/src/components/ActivityBar/Items/NotificationItem.vue +++ b/client/src/components/ActivityBar/Items/NotificationItem.vue @@ -13,7 +13,6 @@ export interface Props { title: string; icon: string; isActive: boolean; - to: string; } defineProps(); @@ -37,6 +36,5 @@ const tooltip = computed(() => :is-active="isActive" :title="title" :tooltip="tooltip" - :to="to" @click="emit('click')" /> diff --git a/client/src/components/Notifications/Categories/Categories.test.ts b/client/src/components/Notifications/Categories/Categories.test.ts index f471dbaa6149..1e3664fe8375 100644 --- a/client/src/components/Notifications/Categories/Categories.test.ts +++ b/client/src/components/Notifications/Categories/Categories.test.ts @@ -52,11 +52,8 @@ describe("Notifications categories", () => { notification, }); - expect(wrapper.text()).toContain( - `${capitalizeFirstLetter(notification.content.item_type)} shared with you by ${ - notification.content.owner_name - }` - ); + expect(wrapper.text()).toContain(`${capitalizeFirstLetter(notification.content.item_type)}`); + expect(wrapper.text()).toContain(`shared with you by ${notification.content.owner_name}`); expect(wrapper.find("#notification-message").text()).toContain( `The user ${notification.content.owner_name} shared` diff --git a/client/src/components/Notifications/Categories/MessageNotification.vue b/client/src/components/Notifications/Categories/MessageNotification.vue index ca62f44d8511..b313b961454b 100644 --- a/client/src/components/Notifications/Categories/MessageNotification.vue +++ b/client/src/components/Notifications/Categories/MessageNotification.vue @@ -2,13 +2,11 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faInbox } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; -import { BCol, BRow } from "bootstrap-vue"; import { computed } from "vue"; import { type MessageNotification } from "@/api/notifications"; import { useMarkdown } from "@/composables/markdown"; -import Heading from "@/components/Common/Heading.vue"; import NotificationActions from "@/components/Notifications/NotificationActions.vue"; library.add(faInbox); @@ -42,16 +40,26 @@ const notificationVariant = computed(() => { + + diff --git a/client/src/components/Notifications/Categories/SharedItemNotification.vue b/client/src/components/Notifications/Categories/SharedItemNotification.vue index 8b1ba9495bc6..b141c87ed308 100644 --- a/client/src/components/Notifications/Categories/SharedItemNotification.vue +++ b/client/src/components/Notifications/Categories/SharedItemNotification.vue @@ -2,14 +2,13 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faExternalLinkAlt, faRetweet } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; -import { BCol, BLink, BRow } from "bootstrap-vue"; +import { BLink } from "bootstrap-vue"; import { computed } from "vue"; import type { SharedItemNotification } from "@/api/notifications"; import { useNotificationsStore } from "@/stores/notificationsStore"; import { absPath } from "@/utils/redirect"; -import Heading from "@/components/Common/Heading.vue"; import NotificationActions from "@/components/Notifications/NotificationActions.vue"; library.add(faExternalLinkAlt, faRetweet); @@ -35,6 +34,7 @@ const sharedItemType = computed(() => { return "Item"; } }); + const notificationVariant = computed(() => { switch (props.notification.variant) { case "urgent": @@ -54,32 +54,37 @@ function markNotificationAsSeen() { + + diff --git a/client/src/components/Notifications/Categories/style.scss b/client/src/components/Notifications/Categories/style.scss new file mode 100644 index 000000000000..d00b1c48a8bd --- /dev/null +++ b/client/src/components/Notifications/Categories/style.scss @@ -0,0 +1,39 @@ +.notification-container { + container: notification-content / inline-size; + + width: 100%; + display: grid; + align-items: center; + grid-template-rows: auto auto auto; + + .notification-title { + display: flex; + gap: 0.2rem; + font-size: 1rem; + flex-flow: wrap; + align-items: center; + } + + @container notification-content (min-width: 576px) { + .notification-header { + .notification-title { + font-size: 1.25rem; + } + } + + .notification-actions { + grid-area: 1/2; + justify-self: end; + } + + .notification-message { + grid-column: 1/3; + } + } + + @container notification-content (max-width: 576px) { + .notification-message { + margin-bottom: 0.5rem; + } + } +} diff --git a/client/src/components/Notifications/NotificationActions.vue b/client/src/components/Notifications/NotificationActions.vue index 438fafec1712..ebcd9a469893 100644 --- a/client/src/components/Notifications/NotificationActions.vue +++ b/client/src/components/Notifications/NotificationActions.vue @@ -2,7 +2,7 @@ import { library } from "@fortawesome/fontawesome-svg-core"; import { faHourglassHalf } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; -import { BButton, BCol, BInputGroup, BRow } from "bootstrap-vue"; +import { BButton, BButtonGroup } from "bootstrap-vue"; import { formatDistanceToNow, parseISO } from "date-fns"; import type { UserNotification } from "@/api/notifications"; @@ -34,30 +34,60 @@ function getNotificationExpirationTitle(notification: UserNotification) { + + diff --git a/client/src/components/Notifications/NotificationCard.vue b/client/src/components/Notifications/NotificationCard.vue new file mode 100644 index 000000000000..303fe41a1e2e --- /dev/null +++ b/client/src/components/Notifications/NotificationCard.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/client/src/components/Notifications/NotificationItem.vue b/client/src/components/Notifications/NotificationItem.vue deleted file mode 100644 index bf05199476ae..000000000000 --- a/client/src/components/Notifications/NotificationItem.vue +++ /dev/null @@ -1,18 +0,0 @@ - - - diff --git a/client/src/components/Notifications/NotificationsList.test.ts b/client/src/components/Notifications/NotificationsList.test.ts index 4df924464e02..7c8d54a91ecb 100644 --- a/client/src/components/Notifications/NotificationsList.test.ts +++ b/client/src/components/Notifications/NotificationsList.test.ts @@ -1,6 +1,6 @@ import { createTestingPinia } from "@pinia/testing"; import { getLocalVue } from "@tests/jest/helpers"; -import { shallowMount } from "@vue/test-utils"; +import { mount } from "@vue/test-utils"; import flushPromises from "flush-promises"; import { setActivePinia } from "pinia"; @@ -22,9 +22,12 @@ async function mountNotificationsList() { const notificationsStore = useNotificationsStore(pinia); notificationsStore.notifications = mergeObjectListsById(FAKE_NOTIFICATIONS, []); - const wrapper = shallowMount(NotificationsList, { + const wrapper = mount(NotificationsList, { localVue, pinia, + stubs: { + FontAwesomeIcon: true, + }, }); await flushPromises(); @@ -34,9 +37,10 @@ async function mountNotificationsList() { describe("NotificationsList", () => { it("render and count unread notifications", async () => { const wrapper = await mountNotificationsList(); + expect(wrapper.findAll(".notification-card")).toHaveLength(messageCount + sharedItemCount); - const unreadNotification = wrapper.findAll(".unread-status"); + const unreadNotification = wrapper.findAll(".unread-notification"); expect(unreadNotification).toHaveLength(FAKE_NOTIFICATIONS.filter((n) => !n.seen_time).length); }); diff --git a/client/src/components/Notifications/NotificationsList.vue b/client/src/components/Notifications/NotificationsList.vue index 978c8e253349..945141215d9b 100644 --- a/client/src/components/Notifications/NotificationsList.vue +++ b/client/src/components/Notifications/NotificationsList.vue @@ -1,19 +1,20 @@