From e3f1c929d4f2cdf4522110b74e5dfc5c5d76962c Mon Sep 17 00:00:00 2001
From: Asli Aykan <56061820+asliayk@users.noreply.github.com>
Date: Fri, 15 Nov 2024 20:37:56 +0100
Subject: [PATCH] Communication: Add unread message notification icon to
sidebar accordion (#9737)
---
.../overview/course-overview.component.html | 2 +-
.../sidebar-accordion.component.html | 3 +++
.../sidebar-accordion.component.scss | 19 +++++++++++++++++++
.../sidebar-accordion.component.ts | 15 +++++++++++++++
.../sidebar-card-item.component.scss | 1 +
.../sidebar-accordion.component.spec.ts | 16 ++++++++++++----
6 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/src/main/webapp/app/overview/course-overview.component.html b/src/main/webapp/app/overview/course-overview.component.html
index 5fac3f273643..c19fe24185bd 100644
--- a/src/main/webapp/app/overview/course-overview.component.html
+++ b/src/main/webapp/app/overview/course-overview.component.html
@@ -259,7 +259,7 @@
[id]="sidebarItem.testId ?? ''"
[ngClass]="{
'guided-tour': sidebarItem.guidedTour,
- newMessage: !communicationRouteLoaded && hasUnreadMessages && sidebarItem.title === 'Communication',
+ newMessage: hasUnreadMessages && sidebarItem.title === 'Communication',
collapsed: isNavbarCollapsed,
}"
jhiOrionFilter
diff --git a/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.html b/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.html
index a3ec25c5b6d6..92d7b034e785 100644
--- a/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.html
+++ b/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.html
@@ -14,6 +14,9 @@
({{ (groupedData[groupKey].entityData | searchFilter: ['title', 'type'] : searchValue)?.length }})
+ @if (totalUnreadMessagesPerGroup[groupKey] > 0 && collapseState[groupKey]) {
+ {{ totalUnreadMessagesPerGroup[groupKey] }}
+ }
diff --git a/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.scss b/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.scss
index 78788a1fb334..61f8e82f8193 100644
--- a/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.scss
+++ b/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.scss
@@ -5,3 +5,22 @@
hr {
border-top-color: var(--overview-light-border-color);
}
+
+.unread-count {
+ background-color: var(--bs-primary);
+ color: var(--bs-white);
+ border-radius: 50%;
+ font-size: 0.6rem;
+ width: 1.1rem;
+ height: 1.1rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ overflow: hidden;
+ white-space: nowrap;
+}
+
+.icon-container {
+ display: flex;
+ align-items: center;
+}
diff --git a/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.ts b/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.ts
index 030cdbb879ec..26f65e5258fa 100644
--- a/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.ts
+++ b/src/main/webapp/app/shared/sidebar/sidebar-accordion/sidebar-accordion.component.ts
@@ -27,6 +27,7 @@ export class SidebarAccordionComponent implements OnChanges, OnInit {
readonly faChevronRight = faChevronRight;
readonly faFile = faFile;
+ totalUnreadMessagesPerGroup: { [key: string]: number } = {};
ngOnInit() {
this.expandGroupWithSelectedItem();
@@ -39,6 +40,7 @@ export class SidebarAccordionComponent implements OnChanges, OnInit {
} else {
this.setStoredCollapseState();
}
+ this.calculateUnreadMessagesOfGroup();
}
setStoredCollapseState() {
@@ -67,6 +69,19 @@ export class SidebarAccordionComponent implements OnChanges, OnInit {
}
}
+ calculateUnreadMessagesOfGroup(): void {
+ if (!this.groupedData) {
+ this.totalUnreadMessagesPerGroup = {};
+ return;
+ }
+
+ Object.keys(this.groupedData).forEach((groupKey) => {
+ this.totalUnreadMessagesPerGroup[groupKey] = this.groupedData[groupKey].entityData
+ .filter((item: SidebarCardElement) => item.conversation?.unreadMessagesCount)
+ .reduce((sum, item) => sum + (item.conversation?.unreadMessagesCount || 0), 0);
+ });
+ }
+
toggleGroupCategoryCollapse(groupCategoryKey: string) {
this.collapseState[groupCategoryKey] = !this.collapseState[groupCategoryKey];
localStorage.setItem('sidebar.accordion.collapseState.' + this.storageId + '.byCourse.' + this.courseId, JSON.stringify(this.collapseState));
diff --git a/src/main/webapp/app/shared/sidebar/sidebar-card-item/sidebar-card-item.component.scss b/src/main/webapp/app/shared/sidebar/sidebar-card-item/sidebar-card-item.component.scss
index 64f4e5a920c0..8f36ede446dc 100644
--- a/src/main/webapp/app/shared/sidebar/sidebar-card-item/sidebar-card-item.component.scss
+++ b/src/main/webapp/app/shared/sidebar/sidebar-card-item/sidebar-card-item.component.scss
@@ -12,6 +12,7 @@
border-radius: 50%;
font-size: 0.6rem;
width: 1.1rem;
+ min-width: 1.1rem;
height: 1.1rem;
display: flex;
justify-content: center;
diff --git a/src/test/javascript/spec/component/shared/sidebar/sidebar-accordion.component.spec.ts b/src/test/javascript/spec/component/shared/sidebar/sidebar-accordion.component.spec.ts
index 9e7fe5427253..54015cb0ff41 100644
--- a/src/test/javascript/spec/component/shared/sidebar/sidebar-accordion.component.spec.ts
+++ b/src/test/javascript/spec/component/shared/sidebar/sidebar-accordion.component.spec.ts
@@ -39,22 +39,23 @@ describe('SidebarAccordionComponent', () => {
component.groupedData = {
current: {
- entityData: [{ title: 'Title 1', type: 'Type A', id: 1, size: 'M' }],
+ entityData: [{ title: 'Title 1', type: 'Type A', id: 1, size: 'M', conversation: { unreadMessagesCount: 1 } }],
},
past: {
- entityData: [{ title: 'Title 2', type: 'Type B', id: 2, size: 'M' }],
+ entityData: [{ title: 'Title 2', type: 'Type B', id: 2, size: 'M', conversation: { unreadMessagesCount: 0 } }],
},
future: {
- entityData: [{ title: 'Title 3', type: 'Type C', id: 3, size: 'M' }],
+ entityData: [{ title: 'Title 3', type: 'Type C', id: 3, size: 'M', conversation: { unreadMessagesCount: 1 } }],
},
noDate: {
- entityData: [{ title: 'Title 4', type: 'Type D', id: 4, size: 'M' }],
+ entityData: [{ title: 'Title 4', type: 'Type D', id: 4, size: 'M', conversation: { unreadMessagesCount: 0 } }],
},
};
component.routeParams = { exerciseId: 3 };
component.collapseState = { current: false, dueSoon: false, past: false, future: true, noDate: true };
fixture.componentRef.setInput('sidebarItemAlwaysShow', { current: false, dueSoon: false, past: false, future: false, noDate: false });
fixture.detectChanges();
+ component.calculateUnreadMessagesOfGroup();
});
afterEach(() => {
@@ -144,4 +145,11 @@ describe('SidebarAccordionComponent', () => {
component.expandGroupWithSelectedItem();
expect(component.collapseState['future']).toBeFalse();
});
+
+ it('should calculate unread messages of each group correctly', () => {
+ expect(component.totalUnreadMessagesPerGroup['current']).toBe(1);
+ expect(component.totalUnreadMessagesPerGroup['past']).toBe(0);
+ expect(component.totalUnreadMessagesPerGroup['future']).toBe(1);
+ expect(component.totalUnreadMessagesPerGroup['noDate']).toBe(0);
+ });
});