Create global inbox actions (#4903)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina 2024-03-08 11:59:20 +04:00 committed by GitHub
parent 0483e2ac0d
commit 5ce079cf3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 172 additions and 43 deletions

View File

@ -634,6 +634,67 @@ export function createModel (builder: Builder): void {
}, },
notification.ids.MentionCommonNotificationType 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 ( export function generateClassNotificationTypes (

View File

@ -64,7 +64,10 @@ export default mergeIds(notificationId, notification, {
}, },
groups: {}, groups: {},
action: { action: {
Unsubscribe: '' as Ref<Action> Unsubscribe: '' as Ref<Action>,
ArchiveAll: '' as Ref<Action>,
ReadAll: '' as Ref<Action>,
UnreadAll: '' as Ref<Action>
}, },
actionImpl: { actionImpl: {
Unsubscribe: '' as ViewAction, Unsubscribe: '' as ViewAction,
@ -77,6 +80,9 @@ export default mergeIds(notificationId, notification, {
UnHideDocNotifyContext: '' as ViewAction, UnHideDocNotifyContext: '' as ViewAction,
UnReadNotifyContext: '' as ViewAction, UnReadNotifyContext: '' as ViewAction,
ReadNotifyContext: '' as ViewAction, ReadNotifyContext: '' as ViewAction,
DeleteContextNotifications: '' as ViewAction DeleteContextNotifications: '' as ViewAction,
ArchiveAll: '' as ViewAction,
ReadAll: '' as ViewAction,
UnreadAll: '' as ViewAction
} }
}) })

View File

@ -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" 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"
/> />
</symbol> </symbol>
<symbol id="readAll" viewBox="0 0 28 28">
<path d="M14 0.00012207C11.2311 0.00012207 8.52431 0.821208 6.22202 2.35955C3.91973 3.89789 2.12532 6.08439 1.06569 8.64255C0.00606596 11.2007 -0.271181 14.0157 0.269012 16.7314C0.809205 19.4471 2.14258 21.9417 4.10051 23.8996C6.05845 25.8576 8.55301 27.1909 11.2687 27.7311C13.9845 28.2713 16.7994 27.9941 19.3576 26.9344C21.9157 25.8748 24.1022 24.0804 25.6406 21.7781C27.1789 19.4758 28 16.7691 28 14.0001C28 10.2871 26.525 6.72614 23.8995 4.10063C21.274 1.47512 17.713 0.00012207 14 0.00012207ZM14 26.0001C11.6266 26.0001 9.30655 25.2963 7.33316 23.9778C5.35977 22.6592 3.8217 20.785 2.91345 18.5923C2.0052 16.3996 1.76756 13.9868 2.23058 11.659C2.69361 9.33127 3.83649 7.19307 5.51472 5.51484C7.19296 3.83661 9.33115 2.69372 11.6589 2.2307C13.9867 1.76768 16.3995 2.00532 18.5922 2.91357C20.7849 3.82182 22.6591 5.35989 23.9776 7.33328C25.2962 9.30667 26 11.6267 26 14.0001C26 17.1827 24.7357 20.235 22.4853 22.4854C20.2348 24.7358 17.1826 26.0001 14 26.0001Z" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.7071 9.29326C21.0976 9.68378 21.0976 10.3169 20.7071 10.7075L12.7071 18.7075C12.3166 19.098 11.6834 19.098 11.2929 18.7075L7.29289 14.7075C6.90237 14.3169 6.90237 13.6838 7.29289 13.2933C7.68342 12.9027 8.31658 12.9027 8.70711 13.2933L12 16.5862L19.2929 9.29326C19.6834 8.90274 20.3166 8.90274 20.7071 9.29326Z" />
</symbol>
<symbol id="unreadAll" viewBox="0 0 28 28">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14 26.0004C20.6274 26.0004 26 20.6278 26 14.0004C26 7.37295 20.6274 2.00037 14 2.00037C7.37258 2.00037 2 7.37295 2 14.0004C2 20.6278 7.37258 26.0004 14 26.0004ZM14 28.0004C21.732 28.0004 28 21.7324 28 14.0004C28 6.26838 21.732 0.000366211 14 0.000366211C6.26801 0.000366211 0 6.26838 0 14.0004C0 21.7324 6.26801 28.0004 14 28.0004Z" />
</symbol>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -37,7 +37,8 @@
"FlatList": "Flat list", "FlatList": "Flat list",
"GroupedList": "Grouped list", "GroupedList": "Grouped list",
"ArchiveAll": "Archive all", "ArchiveAll": "Archive all",
"ReadAll": "Read all", "MarkReadAll": "Mark all as read",
"MarkUnreadAll": "Mark all as unread",
"ArchiveAllConfirmationTitle": "Archive all notifications?", "ArchiveAllConfirmationTitle": "Archive all notifications?",
"ArchiveAllConfirmationMessage": "Are you sure you want to archive all notifications? This operation cannot be undone." "ArchiveAllConfirmationMessage": "Are you sure you want to archive all notifications? This operation cannot be undone."
} }

View File

@ -37,7 +37,8 @@
"FlatList": "Flat list", "FlatList": "Flat list",
"GroupedList": "Grouped list", "GroupedList": "Grouped list",
"ArchiveAll": "Архивировать все", "ArchiveAll": "Архивировать все",
"ReadAll": "Прочитать все", "MarkReadAll": "Oтметить все как прочитанное",
"MarkUnreadAll": "Отметить все как непрочитанные",
"ArchiveAllConfirmationTitle": "Архивировать все уведомления?", "ArchiveAllConfirmationTitle": "Архивировать все уведомления?",
"ArchiveAllConfirmationMessage": "Вы уверены, что хотите заархивировать все уведомления? Эту операцию невозможно отменить." "ArchiveAllConfirmationMessage": "Вы уверены, что хотите заархивировать все уведомления? Эту операцию невозможно отменить."
} }

View File

@ -22,5 +22,7 @@ loadMetadata(notification.icon, {
Inbox: `${icons}#inbox`, Inbox: `${icons}#inbox`,
Track: `${icons}#track`, Track: `${icons}#track`,
Hide: `${icons}#hide`, Hide: `${icons}#hide`,
DontTrack: `${icons}#donttrack` DontTrack: `${icons}#donttrack`,
ReadAll: `${icons}#readAll`,
UnreadAll: `${icons}#unreadAll`
}) })

View File

@ -18,7 +18,7 @@
DisplayInboxNotification, DisplayInboxNotification,
DocNotifyContext DocNotifyContext
} from '@hcengineering/notification' } 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 view, { Viewlet } from '@hcengineering/view'
import { import {
AnyComponent, AnyComponent,
@ -33,9 +33,7 @@
TabList, TabList,
Location, Location,
IconDropdown, IconDropdown,
ButtonWithDropdown, ButtonWithDropdown
IconCheckAll,
showPopup
} from '@hcengineering/ui' } from '@hcengineering/ui'
import chunter, { ThreadMessage } from '@hcengineering/chunter' import chunter, { ThreadMessage } from '@hcengineering/chunter'
import { Ref, WithLookup } from '@hcengineering/core' import { Ref, WithLookup } from '@hcengineering/core'
@ -45,7 +43,14 @@
import { inboxMessagesStore, InboxNotificationsClientImpl } from '../../inboxNotificationsClient' import { inboxMessagesStore, InboxNotificationsClientImpl } from '../../inboxNotificationsClient'
import Filter from '../Filter.svelte' import Filter from '../Filter.svelte'
import { getDisplayInboxNotifications, openInboxDoc, resolveLocation } from '../../utils' import {
archiveAll,
getDisplayInboxNotifications,
openInboxDoc,
readAll,
resolveLocation,
unreadAll
} from '../../utils'
import { InboxNotificationsFilter } from '../../types' import { InboxNotificationsFilter } from '../../types'
export let visibleNav: boolean = true export let visibleNav: boolean = true
@ -255,35 +260,19 @@
{ size: 'auto', minSize: 30, maxSize: 'auto', float: undefined } { size: 'auto', minSize: 30, maxSize: 'auto', float: undefined }
]) ])
function archiveAll (): void { async function dropdownItemSelected (id: 'archive' | 'read' | 'unread'): Promise<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<void> {
if (id == null) return if (id == null) return
if (id === 'archive') { if (id === 'archive') {
archiveAll() void archiveAll()
} }
if (id === 'read') { if (id === 'read') {
readAll() void readAll()
}
if (id === 'unread') {
void unreadAll()
} }
} }
</script> </script>
@ -318,14 +307,19 @@
<ButtonWithDropdown <ButtonWithDropdown
justify="left" justify="left"
kind="regular" kind="regular"
label={notification.string.ReadAll} label={notification.string.MarkReadAll}
icon={IconCheckAll} icon={notification.icon.ReadAll}
on:click={readAll} on:click={readAll}
dropdownItems={[ dropdownItems={[
{ {
id: 'read', id: 'read',
icon: IconCheckAll, icon: notification.icon.ReadAll,
label: notification.string.ReadAll label: notification.string.MarkReadAll
},
{
id: 'unread',
icon: notification.icon.UnreadAll,
label: notification.string.MarkUnreadAll
}, },
{ {
id: 'archive', id: 'archive',

View File

@ -283,4 +283,21 @@ export class InboxNotificationsClientImpl implements InboxNotificationsClient {
await doneOp() await doneOp()
} }
} }
async unreadAllNotifications (): Promise<void> {
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()
}
}
} }

View File

@ -49,7 +49,10 @@ import {
readNotifyContext, readNotifyContext,
unReadNotifyContext, unReadNotifyContext,
deleteContextNotifications, deleteContextNotifications,
hasInboxNotifications hasInboxNotifications,
archiveAll,
readAll,
unreadAll
} from './utils' } from './utils'
import { InboxNotificationsClientImpl } from './inboxNotificationsClient' import { InboxNotificationsClientImpl } from './inboxNotificationsClient'
@ -101,7 +104,10 @@ export default async (): Promise<Resources> => ({
UnHideDocNotifyContext: unHideDocNotifyContext, UnHideDocNotifyContext: unHideDocNotifyContext,
ReadNotifyContext: readNotifyContext, ReadNotifyContext: readNotifyContext,
UnReadNotifyContext: unReadNotifyContext, UnReadNotifyContext: unReadNotifyContext,
DeleteContextNotifications: deleteContextNotifications DeleteContextNotifications: deleteContextNotifications,
ArchiveAll: archiveAll,
ReadAll: readAll,
UnreadAll: unreadAll
}, },
resolver: { resolver: {
Location: resolveLocation Location: resolveLocation

View File

@ -38,8 +38,8 @@ import notification, {
type DocNotifyContext, type DocNotifyContext,
type InboxNotification type InboxNotification
} from '@hcengineering/notification' } from '@hcengineering/notification'
import { getClient } from '@hcengineering/presentation' import { getClient, MessageBox } from '@hcengineering/presentation'
import { getLocation, navigate, type Location, type ResolvedLocation } from '@hcengineering/ui' import { getLocation, navigate, type Location, type ResolvedLocation, showPopup } from '@hcengineering/ui'
import { get } from 'svelte/store' import { get } from 'svelte/store'
import { InboxNotificationsClientImpl } from './inboxNotificationsClient' import { InboxNotificationsClientImpl } from './inboxNotificationsClient'
@ -412,6 +412,36 @@ export async function unpinDocNotifyContext (object: DocNotifyContext): Promise<
}) })
} }
export async function archiveAll (): Promise<void> {
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<void> {
const client = InboxNotificationsClientImpl.getClient()
await client.readAllNotifications()
}
export async function unreadAll (): Promise<void> {
const client = InboxNotificationsClientImpl.getClient()
await client.unreadAllNotifications()
}
export async function getDisplayInboxNotifications ( export async function getDisplayInboxNotifications (
notificationsByContext: Map<Ref<DocNotifyContext>, InboxNotification[]>, notificationsByContext: Map<Ref<DocNotifyContext>, InboxNotification[]>,
filter: InboxNotificationsFilter = 'all', filter: InboxNotificationsFilter = 'all',

View File

@ -284,6 +284,7 @@ export interface InboxNotificationsClient {
deleteNotifications: (client: TxOperations, ids: Array<Ref<InboxNotification>>) => Promise<void> deleteNotifications: (client: TxOperations, ids: Array<Ref<InboxNotification>>) => Promise<void>
deleteAllNotifications: () => Promise<void> deleteAllNotifications: () => Promise<void>
readAllNotifications: () => Promise<void> readAllNotifications: () => Promise<void>
unreadAllNotifications: () => Promise<void>
} }
/** /**
@ -374,7 +375,9 @@ const notification = plugin(notificationId, {
Inbox: '' as Asset, Inbox: '' as Asset,
Track: '' as Asset, Track: '' as Asset,
DontTrack: '' as Asset, DontTrack: '' as Asset,
Hide: '' as Asset Hide: '' as Asset,
ReadAll: '' as Asset,
UnreadAll: '' as Asset
}, },
space: { space: {
Notifications: '' as Ref<Space> Notifications: '' as Ref<Space>
@ -395,7 +398,8 @@ const notification = plugin(notificationId, {
GroupedList: '' as IntlString, GroupedList: '' as IntlString,
All: '' as IntlString, All: '' as IntlString,
ArchiveAll: '' as IntlString, ArchiveAll: '' as IntlString,
ReadAll: '' as IntlString, MarkReadAll: '' as IntlString,
MarkUnreadAll: '' as IntlString,
ArchiveAllConfirmationTitle: '' as IntlString, ArchiveAllConfirmationTitle: '' as IntlString,
ArchiveAllConfirmationMessage: '' as IntlString ArchiveAllConfirmationMessage: '' as IntlString
}, },