Merge branch 'develop' of https://github.com/hcengineering/platform into staging-new

This commit is contained in:
Artem Savchenko
2025-11-21 22:23:50 +07:00
4 changed files with 62 additions and 108 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ export function createModel (builder: Builder): void {
label: inbox.string.Inbox,
icon: inbox.icon.Inbox,
alias: inboxId,
hidden: false,
hidden: true,
component: inbox.component.InboxApplication,
position: 'top',
order: 100
+6 -84
View File
@@ -44,12 +44,9 @@ import notification, {
type BrowserNotification,
type DocNotifyContext,
type InboxNotification,
type OldCollaborators,
type ReactionInboxNotification,
type ActivityInboxNotification
type OldCollaborators
} from '@hcengineering/notification'
import { DOMAIN_PREFERENCE } from '@hcengineering/preference'
import activity, { type ActivityMessage, type DocUpdateMessage, type Reaction } from '@hcengineering/activity'
import {
DOMAIN_SPACE,
@@ -59,7 +56,6 @@ import {
getSocialIdFromOldAccount
} from '@hcengineering/model-core'
import { DOMAIN_DOC_NOTIFY, DOMAIN_NOTIFICATION, DOMAIN_USER_NOTIFY } from './index'
import { DOMAIN_ACTIVITY, DOMAIN_REACTION } from '@hcengineering/model-activity'
export async function removeNotifications (
client: MigrationClient,
@@ -316,85 +312,11 @@ async function migrateCollaborators (client: MigrationClient): Promise<void> {
}
async function migrateReactionNotifications (client: MigrationClient): Promise<void> {
const hierarchy = client.hierarchy
const iterator = await client.traverse<DocNotifyContext>(DOMAIN_DOC_NOTIFY, {
_class: notification.class.DocNotifyContext
})
try {
while (true) {
const contexts = await iterator.next(500)
const res: ReactionInboxNotification[] = []
const removeIds: Ref<InboxNotification>[] = []
if (contexts == null || contexts.length === 0) break
const filtered = contexts.filter((it) => hierarchy.isDerived(it.objectClass, activity.class.ActivityMessage))
if (filtered.length === 0) continue
for (const context of filtered) {
const notifications = await client.find<ActivityInboxNotification>(DOMAIN_NOTIFICATION, {
docNotifyContext: context._id,
_class: notification.class.ActivityInboxNotification,
attachedToClass: activity.class.DocUpdateMessage
})
if (notifications.length === 0) continue
const messages = await client.find<DocUpdateMessage>(DOMAIN_ACTIVITY, {
_id: { $in: notifications.map((it) => it.attachedTo) as Ref<DocUpdateMessage>[] },
_class: activity.class.DocUpdateMessage,
objectClass: activity.class.Reaction
})
const contextMessage = (
await client.find<ActivityMessage>(DOMAIN_ACTIVITY, { _id: context.objectId as any })
)[0]
if (contextMessage == null) continue
const newContext = (
await client.find<DocNotifyContext>(DOMAIN_DOC_NOTIFY, {
user: context.user,
objectId: contextMessage.attachedTo
})
)[0]
if (newContext == null) {
continue
}
for (const it of notifications) {
const reactionMessage = messages.find((m) => m._id === it.attachedTo)
if (reactionMessage == null) continue
const emoji =
it.data ??
(await client.find<Reaction>(DOMAIN_REACTION, { _id: reactionMessage.objectId as Ref<Reaction> }))[0].emoji
if (emoji == null || emoji.trim() === '') continue
res.push({
_id: it._id as Ref<ReactionInboxNotification>,
_class: notification.class.ReactionInboxNotification,
space: it.space,
emoji,
user: it.user,
docNotifyContext: newContext._id,
objectId: newContext.objectId,
objectClass: newContext.objectClass,
ref: reactionMessage.objectId as Ref<Reaction>,
attachedTo: reactionMessage.attachedTo as Ref<ActivityMessage>,
attachedToClass: reactionMessage.attachedToClass as Ref<Class<ActivityMessage>>,
isViewed: it.isViewed,
archived: it.archived,
modifiedOn: it.modifiedOn,
createdBy: it.createdBy,
createdOn: it.createdOn,
modifiedBy: it.modifiedBy
})
}
}
if (removeIds.length > 0) {
await client.deleteMany(DOMAIN_NOTIFICATION, { _id: { $in: removeIds } })
}
if (res.length > 0) {
await client.create(DOMAIN_NOTIFICATION, res)
}
}
} catch (e) {
console.error(e)
}
/*
Do nothing for now, since previous implementation was very slow and caused issues in production.
Old inbox is used in production now, so later add a tool to migrate old reaction notifications if needed.
TODO: UBERF-14185
*/
}
/**
@@ -64,7 +64,7 @@
const groups =
paymentUrl != null && paymentUrl !== '' ? baseGroups : baseGroups.filter((g) => g.key !== 'subscriptions')
let currentGroupKey = groups[0].key
let currentGroupKey = groups[0]?.key
let currentGroup = groups[0]
const unsubscribeLocation = resolvedLocationStore.subscribe((loc) => {
@@ -29,11 +29,13 @@
import login, { loginId } from '@hcengineering/login'
import notification, { DocNotifyContext, InboxNotification, notificationId } from '@hcengineering/notification'
import { BrowserNotificatator, InboxNotificationsClientImpl } from '@hcengineering/notification-resources'
import inbox, { inboxId } from '@hcengineering/inbox'
import { broadcastEvent, getMetadata, getResource, IntlString, translate } from '@hcengineering/platform'
import {
ActionContext,
ComponentExtensions,
createQuery,
createNotificationsQuery,
getClient,
isAdminUser,
reduceCalls
@@ -282,6 +284,17 @@
hasInboxNotifications = res
})
let hasNewInboxNotifications = false
$: if (isCommunicationEnabled) {
const notificationCountQuery = createNotificationsQuery()
notificationCountQuery.query({ read: false, limit: 1 }, (res) => {
hasNewInboxNotifications = res.getResult().length > 0
})
} else {
hasNewInboxNotifications = false
}
const doSyncLoc = reduceCalls(async (loc: Location): Promise<void> => {
if (workspaceId !== $location.path[1]) {
tabs = []
@@ -759,15 +772,17 @@
let inboxPopup: PopupResult | undefined = undefined
let lastLoc: Location | undefined = undefined
$: activeInboxId = isCommunicationEnabled ? inboxId : notificationId
$: inboxProps = {
selected: currentAppAlias === notificationId || inboxPopup !== undefined,
navigator: (currentAppAlias === notificationId || inboxPopup !== undefined) && $deviceInfo.navigator.visible,
notify: hasInboxNotifications,
selected: currentAppAlias === activeInboxId || inboxPopup !== undefined,
navigator: (currentAppAlias === activeInboxId || inboxPopup !== undefined) && $deviceInfo.navigator.visible,
notify: isCommunicationEnabled ? hasInboxNotifications || hasNewInboxNotifications : hasInboxNotifications,
onClick: (e: MouseEvent) => {
if (e.metaKey || e.ctrlKey) return
if (!$deviceInfo.navigator.visible && $deviceInfo.navigator.float && currentAppAlias === notificationId) {
if (!$deviceInfo.navigator.visible && $deviceInfo.navigator.float && currentAppAlias === activeInboxId) {
toggleNav()
} else if (currentAppAlias === notificationId && lastLoc !== undefined) {
} else if (currentAppAlias === activeInboxId && lastLoc !== undefined) {
e.preventDefault()
e.stopPropagation()
navigate(lastLoc)
@@ -778,7 +793,10 @@
}
}
$: customAppProps = new Map([[notificationId, inboxProps]])
$: customAppProps = new Map([
[notificationId, inboxProps],
[inboxId, inboxProps]
])
defineSeparators('workbench', workbenchSeparators)
defineSeparators('main', mainSeparators)
@@ -859,22 +877,36 @@
on:click={toggleNav}
/>
</div>
<!-- <ActivityStatus status="active" /> -->
{#if !isExcludedApp(notificationId) && !isCommunicationEnabled}
<NavLink
app={notificationId}
shrink={0}
disabled={!$deviceInfo.navigator.visible &&
$deviceInfo.navigator.float &&
currentAppAlias === notificationId}
>
<AppItem
icon={notification.icon.Notifications}
label={notification.string.Inbox}
{...inboxProps}
on:click={inboxProps.onClick}
/>
</NavLink>
{#if !isExcludedApp(activeInboxId)}
{#if !isCommunicationEnabled}
<NavLink
app={notificationId}
shrink={0}
disabled={!$deviceInfo.navigator.visible &&
$deviceInfo.navigator.float &&
currentAppAlias === notificationId}
>
<AppItem
icon={notification.icon.Notifications}
label={notification.string.Inbox}
{...inboxProps}
on:click={inboxProps.onClick}
/>
</NavLink>
{:else}
<NavLink
app={inboxId}
shrink={0}
disabled={!$deviceInfo.navigator.visible && $deviceInfo.navigator.float && currentAppAlias === inboxId}
>
<AppItem
icon={inbox.icon.Inbox}
label={inbox.string.Inbox}
{...inboxProps}
on:click={inboxProps.onClick}
/>
</NavLink>
{/if}
{/if}
<Applications
{apps}