Indicator for user menu tabs with unread content
authorAlexander Ebert <ebert@woltlab.com>
Thu, 23 Dec 2021 16:25:13 +0000 (17:25 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Thu, 23 Dec 2021 16:25:13 +0000 (17:25 +0100)
ts/WoltLabSuite/Core/Ui/Page/Menu/User.ts
ts/WoltLabSuite/Core/Ui/User/Menu/Data/ModerationQueue.ts
ts/WoltLabSuite/Core/Ui/User/Menu/Data/Notification.ts
ts/WoltLabSuite/Core/Ui/User/Menu/Data/Provider.ts
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/Page/Menu/User.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Menu/Data/ModerationQueue.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ui/User/Menu/Data/Notification.js
wcfsetup/install/files/style/ui/pageMenu.scss

index 76232a4bf86c209990b9631e1fa80fb2873a7c4d..6996a988a426827211b97aeacc11914736921cce 100644 (file)
@@ -106,6 +106,7 @@ export class PageMenuUser implements PageMenuProvider {
       this.openNotifications();
     }
 
+    this.refreshTabUnreadIndicators();
     this.refreshUnreadIndicator();
   }
 
@@ -157,6 +158,8 @@ export class PageMenuUser implements PageMenuProvider {
     if (legacyPanel) {
       legacyPanel.close();
     }
+
+    this.refreshTabUnreadIndicators();
   }
 
   private attachViewToPanel(tab: Tab): void {
@@ -341,6 +344,7 @@ export class PageMenuUser implements PageMenuProvider {
 
     const tab = document.createElement("a");
     tab.classList.add("pageMenuUserTab");
+    tab.dataset.hasUnreadContent = "false";
     tab.dataset.origin = data.origin;
     tab.id = tabId;
     tab.setAttribute("aria-controls", panelId);
@@ -377,6 +381,16 @@ export class PageMenuUser implements PageMenuProvider {
       this.userMenu.classList.remove("pageMenuMobileButtonHasContent");
     }
   }
+
+  private refreshTabUnreadIndicators(): void {
+    this.userMenuProviders.forEach((provider, tab) => {
+      if (provider.hasUnreadContent()) {
+        tab.dataset.hasUnreadContent = "true";
+      } else {
+        tab.dataset.hasUnreadContent = "false";
+      }
+    });
+  }
 }
 
 export function hasValidUserMenu(): boolean {
index 6cca4beea7cf852b290a11efa04807d9abe83370..15da62712878d2a9a446d8d2f3e303d742b73955 100644 (file)
@@ -118,6 +118,10 @@ class UserMenuDataModerationQueue implements UserMenuProvider {
     return "com.woltlab.wcf.moderation";
   }
 
+  hasUnreadContent(): boolean {
+    return this.counter > 0;
+  }
+
   async markAsRead(objectId: number): Promise<void> {
     const response = (await dboAction("markAsRead", "wcf\\data\\moderation\\queue\\ModerationQueueAction")
       .objectIds([objectId])
index 59d7e74c267f7ce3691956f942ad704af44a74ed..783e0e73c647296a4e0692ad92159908f5005b71 100644 (file)
@@ -209,6 +209,10 @@ class UserMenuDataNotification implements UserMenuProvider {
     return this.options.noItems;
   }
 
+  hasUnreadContent(): boolean {
+    return this.counter > 0;
+  }
+
   isStale(): boolean {
     if (this.stale) {
       return true;
index c5a7e8495c4c45f8145d261d793cee89183bce59..6df7eefe1493f2bdc59d61b3a8ef62ef4e0f09b5 100644 (file)
@@ -39,6 +39,8 @@ export interface UserMenuProvider {
 
   getView(): UserMenuView;
 
+  hasUnreadContent(): boolean;
+
   isStale(): boolean;
 
   markAsRead(objectId: number): Promise<void>;
index 3813d01a83f463c639e24857b9425d5896815cc3..5f49ae28da29e8c32e21a7323e1c5f8eaf1e11eb 100644 (file)
@@ -66,6 +66,7 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../.
             else {
                 this.openNotifications();
             }
+            this.refreshTabUnreadIndicators();
             this.refreshUnreadIndicator();
         }
         openNotifications() {
@@ -103,6 +104,7 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../.
             if (legacyPanel) {
                 legacyPanel.close();
             }
+            this.refreshTabUnreadIndicators();
         }
         attachViewToPanel(tab) {
             const origin = tab.dataset.origin;
@@ -250,6 +252,7 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../.
             const panelId = Util_1.default.getUniqueId();
             const tab = document.createElement("a");
             tab.classList.add("pageMenuUserTab");
+            tab.dataset.hasUnreadContent = "false";
             tab.dataset.origin = data.origin;
             tab.id = tabId;
             tab.setAttribute("aria-controls", panelId);
@@ -281,6 +284,16 @@ define(["require", "exports", "tslib", "./Container", "../../../Language", "../.
                 this.userMenu.classList.remove("pageMenuMobileButtonHasContent");
             }
         }
+        refreshTabUnreadIndicators() {
+            this.userMenuProviders.forEach((provider, tab) => {
+                if (provider.hasUnreadContent()) {
+                    tab.dataset.hasUnreadContent = "true";
+                }
+                else {
+                    tab.dataset.hasUnreadContent = "false";
+                }
+            });
+        }
     }
     exports.PageMenuUser = PageMenuUser;
     function hasValidUserMenu() {
index 77f35a993382509d95734cbe890f816d859f4c0b..761e67d653478afdd427544369534c2fa1cb8be8 100644 (file)
@@ -80,6 +80,9 @@ define(["require", "exports", "tslib", "../../../../Ajax", "../View", "../Manage
         getIdentifier() {
             return "com.woltlab.wcf.moderation";
         }
+        hasUnreadContent() {
+            return this.counter > 0;
+        }
         async markAsRead(objectId) {
             const response = (await (0, Ajax_1.dboAction)("markAsRead", "wcf\\data\\moderation\\queue\\ModerationQueueAction")
                 .objectIds([objectId])
index 4fd33066e7678b69ff13b4650557da98a37406f8..4fd617593b3965773513dcf1d6dff21dd97593d5 100644 (file)
@@ -155,6 +155,9 @@ define(["require", "exports", "tslib", "../../../../Ajax", "../View", "../Manage
         getEmptyViewMessage() {
             return this.options.noItems;
         }
+        hasUnreadContent() {
+            return this.counter > 0;
+        }
         isStale() {
             if (this.stale) {
                 return true;
index 554bfbf2d9aac4fd71c4e563703976e161aeac47..b0a274b8a285bd3cf3c0f4814c3c5a4446c91b33 100644 (file)
        &[aria-selected="true"] {
                background-color: var(--background-color-active);
        }
+
+       &[aria-selected="false"][data-has-unread-content="true"]::after {
+               background-color: var(--color-indicator);
+               border-radius: 50%;
+               content: "";
+               height: 10px;
+               opacity: 1;
+               position: absolute;
+               right: 5px;
+               top: 5px;
+               width: 10px;
+       }
 }
 
 .pageMenuUserTabPanel {