From 5ce079cf3dfb3eafca6fcb79334a9fac18c66a97 Mon Sep 17 00:00:00 2001 From: Kristina Date: Fri, 8 Mar 2024 11:59:20 +0400 Subject: [PATCH] Create global inbox actions (#4903) Signed-off-by: Kristina Fefelova --- models/notification/src/index.ts | 61 +++++++++++++++++++ models/notification/src/plugin.ts | 10 ++- plugins/notification-assets/assets/icons.svg | 7 +++ plugins/notification-assets/lang/en.json | 3 +- plugins/notification-assets/lang/ru.json | 3 +- plugins/notification-assets/src/index.ts | 4 +- .../src/components/inbox/Inbox.svelte | 58 ++++++++---------- .../src/inboxNotificationsClient.ts | 17 ++++++ plugins/notification-resources/src/index.ts | 10 ++- plugins/notification-resources/src/utils.ts | 34 ++++++++++- plugins/notification/src/index.ts | 8 ++- 11 files changed, 172 insertions(+), 43 deletions(-) diff --git a/models/notification/src/index.ts b/models/notification/src/index.ts index 82b0a6a283..9834609ddd 100644 --- a/models/notification/src/index.ts +++ b/models/notification/src/index.ts @@ -634,6 +634,67 @@ export function createModel (builder: Builder): void { }, notification.ids.MentionCommonNotificationType ) + + createAction( + builder, + { + action: notification.actionImpl.ArchiveAll, + label: notification.string.ArchiveAll, + icon: view.icon.Archive, + keyBinding: [], + input: 'none', + category: notification.category.Notification, + target: core.class.Doc, + context: { + mode: ['browser'], + group: 'edit' + } + }, + notification.action.ArchiveAll + ) + + createAction( + builder, + { + action: notification.actionImpl.ReadAll, + label: notification.string.MarkReadAll, + icon: notification.icon.ReadAll, + keyBinding: [], + input: 'none', + category: notification.category.Notification, + target: core.class.Doc, + context: { + mode: ['browser'], + group: 'edit' + } + }, + notification.action.ReadAll + ) + + createAction( + builder, + { + action: notification.actionImpl.UnreadAll, + label: notification.string.MarkUnreadAll, + icon: notification.icon.UnreadAll, + keyBinding: [], + input: 'none', + category: notification.category.Notification, + target: core.class.Doc, + context: { + mode: ['browser'], + group: 'edit' + } + }, + notification.action.UnreadAll + ) + + builder.createDoc( + view.class.ActionCategory, + core.space.Model, + { label: notification.string.Inbox, visible: true }, + notification.category.Notification + ) } export function generateClassNotificationTypes ( diff --git a/models/notification/src/plugin.ts b/models/notification/src/plugin.ts index 81e737fefe..5a199b9d40 100644 --- a/models/notification/src/plugin.ts +++ b/models/notification/src/plugin.ts @@ -64,7 +64,10 @@ export default mergeIds(notificationId, notification, { }, groups: {}, action: { - Unsubscribe: '' as Ref + Unsubscribe: '' as Ref, + ArchiveAll: '' as Ref, + ReadAll: '' as Ref, + UnreadAll: '' as Ref }, actionImpl: { Unsubscribe: '' as ViewAction, @@ -77,6 +80,9 @@ export default mergeIds(notificationId, notification, { UnHideDocNotifyContext: '' as ViewAction, UnReadNotifyContext: '' as ViewAction, ReadNotifyContext: '' as ViewAction, - DeleteContextNotifications: '' as ViewAction + DeleteContextNotifications: '' as ViewAction, + ArchiveAll: '' as ViewAction, + ReadAll: '' as ViewAction, + UnreadAll: '' as ViewAction } }) diff --git a/plugins/notification-assets/assets/icons.svg b/plugins/notification-assets/assets/icons.svg index 883e122054..1bb20ca57f 100644 --- a/plugins/notification-assets/assets/icons.svg +++ b/plugins/notification-assets/assets/icons.svg @@ -20,4 +20,11 @@ d="M8.8,12c0-1.8,1.5-3.2,3.2-3.2s3.2,1.5,3.2,3.2s-1.5,3.2-3.2,3.2S8.8,13.8,8.8,12z M12,10.2c-1,0-1.8,0.8-1.8,1.8s0.8,1.8,1.8,1.8s1.8-0.8,1.8-1.8S13,10.2,12,10.2z" /> + + + + + + + diff --git a/plugins/notification-assets/lang/en.json b/plugins/notification-assets/lang/en.json index c7a43dcc84..070d26dd73 100644 --- a/plugins/notification-assets/lang/en.json +++ b/plugins/notification-assets/lang/en.json @@ -37,7 +37,8 @@ "FlatList": "Flat list", "GroupedList": "Grouped list", "ArchiveAll": "Archive all", - "ReadAll": "Read all", + "MarkReadAll": "Mark all as read", + "MarkUnreadAll": "Mark all as unread", "ArchiveAllConfirmationTitle": "Archive all notifications?", "ArchiveAllConfirmationMessage": "Are you sure you want to archive all notifications? This operation cannot be undone." } diff --git a/plugins/notification-assets/lang/ru.json b/plugins/notification-assets/lang/ru.json index 1427faa418..6f756e1499 100644 --- a/plugins/notification-assets/lang/ru.json +++ b/plugins/notification-assets/lang/ru.json @@ -37,7 +37,8 @@ "FlatList": "Flat list", "GroupedList": "Grouped list", "ArchiveAll": "Архивировать все", - "ReadAll": "Прочитать все", + "MarkReadAll": "Oтметить все как прочитанное", + "MarkUnreadAll": "Отметить все как непрочитанные", "ArchiveAllConfirmationTitle": "Архивировать все уведомления?", "ArchiveAllConfirmationMessage": "Вы уверены, что хотите заархивировать все уведомления? Эту операцию невозможно отменить." } diff --git a/plugins/notification-assets/src/index.ts b/plugins/notification-assets/src/index.ts index 9d8fbbcd9b..0e5fc478a6 100644 --- a/plugins/notification-assets/src/index.ts +++ b/plugins/notification-assets/src/index.ts @@ -22,5 +22,7 @@ loadMetadata(notification.icon, { Inbox: `${icons}#inbox`, Track: `${icons}#track`, Hide: `${icons}#hide`, - DontTrack: `${icons}#donttrack` + DontTrack: `${icons}#donttrack`, + ReadAll: `${icons}#readAll`, + UnreadAll: `${icons}#unreadAll` }) diff --git a/plugins/notification-resources/src/components/inbox/Inbox.svelte b/plugins/notification-resources/src/components/inbox/Inbox.svelte index 666db1efeb..bc15c6b2f2 100644 --- a/plugins/notification-resources/src/components/inbox/Inbox.svelte +++ b/plugins/notification-resources/src/components/inbox/Inbox.svelte @@ -18,7 +18,7 @@ DisplayInboxNotification, DocNotifyContext } from '@hcengineering/notification' - import { ActionContext, createQuery, getClient, MessageBox } from '@hcengineering/presentation' + import { ActionContext, createQuery, getClient } from '@hcengineering/presentation' import view, { Viewlet } from '@hcengineering/view' import { AnyComponent, @@ -33,9 +33,7 @@ TabList, Location, IconDropdown, - ButtonWithDropdown, - IconCheckAll, - showPopup + ButtonWithDropdown } from '@hcengineering/ui' import chunter, { ThreadMessage } from '@hcengineering/chunter' import { Ref, WithLookup } from '@hcengineering/core' @@ -45,7 +43,14 @@ import { inboxMessagesStore, InboxNotificationsClientImpl } from '../../inboxNotificationsClient' import Filter from '../Filter.svelte' - import { getDisplayInboxNotifications, openInboxDoc, resolveLocation } from '../../utils' + import { + archiveAll, + getDisplayInboxNotifications, + openInboxDoc, + readAll, + resolveLocation, + unreadAll + } from '../../utils' import { InboxNotificationsFilter } from '../../types' export let visibleNav: boolean = true @@ -255,35 +260,19 @@ { size: 'auto', minSize: 30, maxSize: 'auto', float: undefined } ]) - function archiveAll (): void { - showPopup( - MessageBox, - { - label: notification.string.ArchiveAllConfirmationTitle, - message: notification.string.ArchiveAllConfirmationMessage - }, - 'top', - (result?: boolean) => { - if (result === true) { - void inboxClient.deleteAllNotifications() - } - } - ) - } - - function readAll (): void { - void inboxClient.readAllNotifications() - } - - async function dropdownItemSelected (id: 'archive' | 'read'): Promise { + async function dropdownItemSelected (id: 'archive' | 'read' | 'unread'): Promise { if (id == null) return if (id === 'archive') { - archiveAll() + void archiveAll() } if (id === 'read') { - readAll() + void readAll() + } + + if (id === 'unread') { + void unreadAll() } } @@ -318,14 +307,19 @@ { + const doneOp = await getClient().measure('unreadAllNotifications') + const ops = getClient().apply(generateId()) + + try { + const inboxNotifications = get(this.inboxNotifications) ?? [] + for (const notification of inboxNotifications) { + if (notification.isViewed) { + await ops.update(notification, { isViewed: false }) + } + } + } finally { + await ops.commit() + await doneOp() + } + } } diff --git a/plugins/notification-resources/src/index.ts b/plugins/notification-resources/src/index.ts index e6eec197c7..280fd572c5 100644 --- a/plugins/notification-resources/src/index.ts +++ b/plugins/notification-resources/src/index.ts @@ -49,7 +49,10 @@ import { readNotifyContext, unReadNotifyContext, deleteContextNotifications, - hasInboxNotifications + hasInboxNotifications, + archiveAll, + readAll, + unreadAll } from './utils' import { InboxNotificationsClientImpl } from './inboxNotificationsClient' @@ -101,7 +104,10 @@ export default async (): Promise => ({ UnHideDocNotifyContext: unHideDocNotifyContext, ReadNotifyContext: readNotifyContext, UnReadNotifyContext: unReadNotifyContext, - DeleteContextNotifications: deleteContextNotifications + DeleteContextNotifications: deleteContextNotifications, + ArchiveAll: archiveAll, + ReadAll: readAll, + UnreadAll: unreadAll }, resolver: { Location: resolveLocation diff --git a/plugins/notification-resources/src/utils.ts b/plugins/notification-resources/src/utils.ts index 0490ae07e6..5201e59124 100644 --- a/plugins/notification-resources/src/utils.ts +++ b/plugins/notification-resources/src/utils.ts @@ -38,8 +38,8 @@ import notification, { type DocNotifyContext, type InboxNotification } from '@hcengineering/notification' -import { getClient } from '@hcengineering/presentation' -import { getLocation, navigate, type Location, type ResolvedLocation } from '@hcengineering/ui' +import { getClient, MessageBox } from '@hcengineering/presentation' +import { getLocation, navigate, type Location, type ResolvedLocation, showPopup } from '@hcengineering/ui' import { get } from 'svelte/store' import { InboxNotificationsClientImpl } from './inboxNotificationsClient' @@ -412,6 +412,36 @@ export async function unpinDocNotifyContext (object: DocNotifyContext): Promise< }) } +export async function archiveAll (): Promise { + const client = InboxNotificationsClientImpl.getClient() + + showPopup( + MessageBox, + { + label: notification.string.ArchiveAllConfirmationTitle, + message: notification.string.ArchiveAllConfirmationMessage + }, + 'top', + (result?: boolean) => { + if (result === true) { + void client.deleteAllNotifications() + } + } + ) +} + +export async function readAll (): Promise { + const client = InboxNotificationsClientImpl.getClient() + + await client.readAllNotifications() +} + +export async function unreadAll (): Promise { + const client = InboxNotificationsClientImpl.getClient() + + await client.unreadAllNotifications() +} + export async function getDisplayInboxNotifications ( notificationsByContext: Map, InboxNotification[]>, filter: InboxNotificationsFilter = 'all', diff --git a/plugins/notification/src/index.ts b/plugins/notification/src/index.ts index 29278f6c77..a802a04152 100644 --- a/plugins/notification/src/index.ts +++ b/plugins/notification/src/index.ts @@ -284,6 +284,7 @@ export interface InboxNotificationsClient { deleteNotifications: (client: TxOperations, ids: Array>) => Promise deleteAllNotifications: () => Promise readAllNotifications: () => Promise + unreadAllNotifications: () => Promise } /** @@ -374,7 +375,9 @@ const notification = plugin(notificationId, { Inbox: '' as Asset, Track: '' as Asset, DontTrack: '' as Asset, - Hide: '' as Asset + Hide: '' as Asset, + ReadAll: '' as Asset, + UnreadAll: '' as Asset }, space: { Notifications: '' as Ref @@ -395,7 +398,8 @@ const notification = plugin(notificationId, { GroupedList: '' as IntlString, All: '' as IntlString, ArchiveAll: '' as IntlString, - ReadAll: '' as IntlString, + MarkReadAll: '' as IntlString, + MarkUnreadAll: '' as IntlString, ArchiveAllConfirmationTitle: '' as IntlString, ArchiveAllConfirmationMessage: '' as IntlString },