mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
Qfix sidebar (#6708)
This commit is contained in:
parent
3662f1f8ee
commit
822731c23c
@ -105,6 +105,10 @@ export class TBrowserNotification extends TDoc implements BrowserNotification {
|
||||
onClickLocation?: Location | undefined
|
||||
user!: Ref<Account>
|
||||
status!: NotificationStatus
|
||||
messageId?: Ref<ActivityMessage>
|
||||
messageClass?: Ref<Class<ActivityMessage>>
|
||||
objectId!: Ref<Doc>
|
||||
objectClass!: Ref<Class<Doc>>
|
||||
}
|
||||
|
||||
@Model(notification.class.PushSubscription, core.class.Doc, DOMAIN_USER_NOTIFY)
|
||||
|
@ -34,7 +34,6 @@ export default mergeIds(timeId, time, {
|
||||
EditToDo: '' as IntlString,
|
||||
GotoTimePlaning: '' as IntlString,
|
||||
GotoTimeTeamPlaning: '' as IntlString,
|
||||
NewToDo: '' as IntlString,
|
||||
Priority: '' as IntlString,
|
||||
MarkedAsDone: '' as IntlString
|
||||
},
|
||||
|
@ -31,14 +31,15 @@
|
||||
export let isAsideOpened = false
|
||||
export let syncLocation = true
|
||||
export let freeze = false
|
||||
export let selectedMessageId: Ref<ActivityMessage> | undefined = undefined
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
let dataProvider: ChannelDataProvider | undefined
|
||||
let selectedMessageId: Ref<ActivityMessage> | undefined = undefined
|
||||
|
||||
const unsubscribe = messageInFocus.subscribe((id) => {
|
||||
if (!syncLocation) return
|
||||
if (id !== undefined && id !== selectedMessageId) {
|
||||
selectedMessageId = id
|
||||
}
|
||||
@ -47,9 +48,7 @@
|
||||
})
|
||||
|
||||
const unsubscribeLocation = locationStore.subscribe((newLocation) => {
|
||||
if (!syncLocation) {
|
||||
return
|
||||
}
|
||||
if (!syncLocation) return
|
||||
const id = getMessageFromLoc(newLocation)
|
||||
selectedMessageId = id
|
||||
messageInFocus.set(id)
|
||||
|
@ -582,13 +582,13 @@
|
||||
}
|
||||
|
||||
async function restoreScroll () {
|
||||
if (!scrollElement || !scroller) {
|
||||
await wait()
|
||||
|
||||
if (!scrollElement || !scroller || scrollToRestore === 0) {
|
||||
scrollToRestore = 0
|
||||
return
|
||||
}
|
||||
|
||||
await wait()
|
||||
|
||||
const delta = scrollElement.scrollHeight - scrollToRestore
|
||||
|
||||
scroller.scrollBy(delta)
|
||||
|
@ -18,7 +18,9 @@
|
||||
import { DocNotifyContext } from '@hcengineering/notification'
|
||||
import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources'
|
||||
import { Widget } from '@hcengineering/workbench'
|
||||
import { ActivityMessage } from '@hcengineering/activity'
|
||||
import { ChatWidgetTab } from '@hcengineering/chunter'
|
||||
import { updateTabData } from '@hcengineering/workbench-resources'
|
||||
|
||||
import Channel from './Channel.svelte'
|
||||
import { closeThreadInSidebarChannel } from '../navigation'
|
||||
@ -36,12 +38,18 @@
|
||||
|
||||
let object: Doc | undefined = undefined
|
||||
let context: DocNotifyContext | undefined = undefined
|
||||
let selectedMessageId: Ref<ActivityMessage> | undefined = tab.data.selectedMessageId
|
||||
|
||||
$: context = object ? $contextByDocStore.get(object._id) : undefined
|
||||
$: void loadObject(tab.data._id, tab.data._class)
|
||||
|
||||
$: threadId = tab.data.thread
|
||||
|
||||
$: if (tab.data.selectedMessageId !== undefined && tab.data.selectedMessageId !== '') {
|
||||
selectedMessageId = tab.data.selectedMessageId
|
||||
updateTabData(widget._id, tab.id, { selectedMessageId: '' })
|
||||
}
|
||||
|
||||
async function loadObject (_id?: Ref<Doc>, _class?: Ref<Class<Doc>>): Promise<void> {
|
||||
if (_id === undefined || _class === undefined) {
|
||||
object = undefined
|
||||
@ -80,13 +88,19 @@
|
||||
on:close
|
||||
/>
|
||||
{#key object._id}
|
||||
<Channel {object} {context} syncLocation={false} freeze={threadId !== undefined} />
|
||||
<Channel {object} {context} syncLocation={false} freeze={threadId !== undefined} {selectedMessageId} />
|
||||
{/key}
|
||||
</div>
|
||||
{/if}
|
||||
{#if threadId}
|
||||
<div class="thread" style:height style:width>
|
||||
<ThreadView _id={threadId} on:channel={() => closeThreadInSidebarChannel(widget, tab)} on:close />
|
||||
<ThreadView
|
||||
_id={threadId}
|
||||
{selectedMessageId}
|
||||
syncLocation={false}
|
||||
on:channel={() => closeThreadInSidebarChannel(widget, tab)}
|
||||
on:close
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
@ -0,0 +1,79 @@
|
||||
<script lang="ts">
|
||||
import activity, { ActivityMessage } from '@hcengineering/activity'
|
||||
import ThreadParentMessage from './ThreadParentPresenter.svelte'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import ChannelScrollView from '../ChannelScrollView.svelte'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { ChannelDataProvider } from '../../channelDataProvider'
|
||||
import chunter from '../../plugin'
|
||||
|
||||
export let selectedMessageId: Ref<ActivityMessage> | undefined = undefined
|
||||
export let message: ActivityMessage
|
||||
|
||||
let dataProvider: ChannelDataProvider | undefined = undefined
|
||||
|
||||
$: if (message !== undefined && dataProvider === undefined) {
|
||||
dataProvider = new ChannelDataProvider(
|
||||
undefined,
|
||||
message.space,
|
||||
message._id,
|
||||
chunter.class.ThreadMessage,
|
||||
selectedMessageId,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
$: messagesStore = dataProvider?.messagesStore
|
||||
</script>
|
||||
|
||||
<div class="hulyComponent-content hulyComponent-content__container noShrink">
|
||||
{#if dataProvider !== undefined}
|
||||
<ChannelScrollView
|
||||
bind:selectedMessageId
|
||||
embedded
|
||||
skipLabels
|
||||
object={message}
|
||||
provider={dataProvider}
|
||||
fullHeight={false}
|
||||
fixedInput={false}
|
||||
>
|
||||
<svelte:fragment slot="header">
|
||||
<div class="mt-3">
|
||||
<ThreadParentMessage {message} />
|
||||
</div>
|
||||
|
||||
{#if (message.replies ?? $messagesStore?.length ?? 0) > 0}
|
||||
<div class="separator">
|
||||
<div class="label lower">
|
||||
<Label
|
||||
label={activity.string.RepliesCount}
|
||||
params={{ replies: message.replies ?? $messagesStore?.length ?? 1 }}
|
||||
/>
|
||||
</div>
|
||||
<div class="line" />
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</ChannelScrollView>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.separator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0.5rem 0;
|
||||
|
||||
.label {
|
||||
white-space: nowrap;
|
||||
margin: 0 0.5rem;
|
||||
color: var(--theme-halfcontent-color);
|
||||
}
|
||||
|
||||
.line {
|
||||
background: var(--theme-refinput-border);
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import { Doc, Ref } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Breadcrumbs, Label, location as locationStore, Header, BreadcrumbItem } from '@hcengineering/ui'
|
||||
import { Breadcrumbs, location as locationStore, Header, BreadcrumbItem, Loading } from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||
import activity, { ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
|
||||
import { getMessageFromLoc, messageInFocus } from '@hcengineering/activity-resources'
|
||||
@ -23,14 +23,14 @@
|
||||
import attachment from '@hcengineering/attachment'
|
||||
|
||||
import chunter from '../../plugin'
|
||||
import ThreadParentMessage from './ThreadParentPresenter.svelte'
|
||||
import { getObjectIcon, getChannelName } from '../../utils'
|
||||
import ChannelScrollView from '../ChannelScrollView.svelte'
|
||||
import { ChannelDataProvider } from '../../channelDataProvider'
|
||||
import { threadMessagesStore } from '../../stores'
|
||||
import ThreadContent from './ThreadContent.svelte'
|
||||
|
||||
export let _id: Ref<ActivityMessage>
|
||||
export let selectedMessageId: Ref<ActivityMessage> | undefined = undefined
|
||||
export let showHeader: boolean = true
|
||||
export let syncLocation = true
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
@ -40,12 +40,12 @@
|
||||
const channelQuery = createQuery()
|
||||
|
||||
let channel: Doc | undefined = undefined
|
||||
let message: DisplayActivityMessage | undefined = undefined
|
||||
|
||||
let message: DisplayActivityMessage | undefined = $threadMessagesStore?._id === _id ? $threadMessagesStore : undefined
|
||||
let isLoading = true
|
||||
let channelName: string | undefined = undefined
|
||||
let dataProvider: ChannelDataProvider | undefined = undefined
|
||||
|
||||
const unsubscribe = messageInFocus.subscribe((id) => {
|
||||
if (!syncLocation) return
|
||||
if (id !== undefined && id !== selectedMessageId) {
|
||||
selectedMessageId = id
|
||||
}
|
||||
@ -54,6 +54,7 @@
|
||||
})
|
||||
|
||||
const unsubscribeLocation = locationStore.subscribe((newLocation) => {
|
||||
if (!syncLocation) return
|
||||
const id = getMessageFromLoc(newLocation)
|
||||
selectedMessageId = id
|
||||
messageInFocus.set(id)
|
||||
@ -64,12 +65,17 @@
|
||||
unsubscribeLocation()
|
||||
})
|
||||
|
||||
$: if (message && message._id !== _id) {
|
||||
message = $threadMessagesStore?._id === _id ? $threadMessagesStore : undefined
|
||||
isLoading = message === undefined
|
||||
}
|
||||
|
||||
$: messageQuery.query(
|
||||
activity.class.ActivityMessage,
|
||||
{ _id },
|
||||
(result: ActivityMessage[]) => {
|
||||
message = result[0] as DisplayActivityMessage
|
||||
|
||||
isLoading = false
|
||||
if (message === undefined) {
|
||||
dispatch('close')
|
||||
}
|
||||
@ -88,42 +94,26 @@
|
||||
channel = res[0]
|
||||
})
|
||||
|
||||
$: if (message !== undefined && dataProvider === undefined) {
|
||||
dataProvider = new ChannelDataProvider(
|
||||
undefined,
|
||||
message.space,
|
||||
message._id,
|
||||
chunter.class.ThreadMessage,
|
||||
selectedMessageId,
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
$: message &&
|
||||
getChannelName(message.attachedTo, message.attachedToClass, channel).then((res) => {
|
||||
channelName = res
|
||||
})
|
||||
|
||||
let breadcrumbs: BreadcrumbItem[] = []
|
||||
$: breadcrumbs = showHeader ? getBreadcrumbsItems(channel, message, channelName) : []
|
||||
$: breadcrumbs = showHeader ? getBreadcrumbsItems(channel, channelName) : []
|
||||
|
||||
function getBreadcrumbsItems (
|
||||
channel?: Doc,
|
||||
message?: DisplayActivityMessage,
|
||||
channelName?: string
|
||||
): BreadcrumbItem[] {
|
||||
if (message === undefined) {
|
||||
function getBreadcrumbsItems (channel?: Doc, channelName?: string): BreadcrumbItem[] {
|
||||
if (channel === undefined) {
|
||||
return []
|
||||
}
|
||||
|
||||
const isPersonAvatar =
|
||||
message.attachedToClass === chunter.class.DirectMessage ||
|
||||
hierarchy.isDerived(message.attachedToClass, contact.class.Person)
|
||||
channel._class === chunter.class.DirectMessage || hierarchy.isDerived(channel._class, contact.class.Person)
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'channel',
|
||||
icon: getObjectIcon(message.attachedToClass),
|
||||
icon: getObjectIcon(channel._class),
|
||||
iconProps: { value: channel },
|
||||
iconWidth: isPersonAvatar ? 'auto' : undefined,
|
||||
withoutIconBackground: isPersonAvatar,
|
||||
@ -143,8 +133,6 @@
|
||||
|
||||
dispatch('channel')
|
||||
}
|
||||
|
||||
$: messagesStore = dataProvider?.messagesStore
|
||||
</script>
|
||||
|
||||
{#if showHeader}
|
||||
@ -153,54 +141,10 @@
|
||||
</Header>
|
||||
{/if}
|
||||
|
||||
<div class="hulyComponent-content hulyComponent-content__container noShrink">
|
||||
{#if message && dataProvider !== undefined}
|
||||
<ChannelScrollView
|
||||
bind:selectedMessageId
|
||||
embedded
|
||||
skipLabels
|
||||
object={message}
|
||||
provider={dataProvider}
|
||||
fullHeight={false}
|
||||
fixedInput={false}
|
||||
>
|
||||
<svelte:fragment slot="header">
|
||||
<div class="mt-3">
|
||||
<ThreadParentMessage {message} />
|
||||
</div>
|
||||
|
||||
{#if (message.replies ?? $messagesStore?.length ?? 0) > 0}
|
||||
<div class="separator">
|
||||
<div class="label lower">
|
||||
<Label
|
||||
label={activity.string.RepliesCount}
|
||||
params={{ replies: message.replies ?? $messagesStore?.length ?? 1 }}
|
||||
/>
|
||||
</div>
|
||||
<div class="line" />
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
</ChannelScrollView>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.separator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0.5rem 0;
|
||||
|
||||
.label {
|
||||
white-space: nowrap;
|
||||
margin: 0 0.5rem;
|
||||
color: var(--theme-halfcontent-color);
|
||||
}
|
||||
|
||||
.line {
|
||||
background: var(--theme-refinput-border);
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{#if message}
|
||||
{#key _id}
|
||||
<ThreadContent bind:selectedMessageId {message} />
|
||||
{/key}
|
||||
{:else if isLoading}
|
||||
<Loading />
|
||||
{/if}
|
||||
|
@ -28,6 +28,7 @@ import { get } from 'svelte/store'
|
||||
import { chatSpecials } from './components/chat/utils'
|
||||
import { getChannelName, isThreadMessage } from './utils'
|
||||
import chunter from './plugin'
|
||||
import { threadMessagesStore } from './stores'
|
||||
|
||||
export function openChannel (_id: string, _class: Ref<Class<Doc>>, thread?: Ref<ActivityMessage>): void {
|
||||
const loc = getCurrentLocation()
|
||||
@ -168,6 +169,8 @@ export async function replyToThread (message: ActivityMessage, e: Event): Promis
|
||||
const fromSidebar = isElementFromSidebar(e.target as HTMLElement)
|
||||
const loc = getCurrentLocation()
|
||||
|
||||
threadMessagesStore.set(message)
|
||||
|
||||
if (fromSidebar) {
|
||||
const widget = getClient().getModel().findAllSync(workbench.class.Widget, { _id: chunter.ids.ChatWidget })[0]
|
||||
const widgetState = get(sidebarStore).widgetsState.get(widget._id)
|
||||
@ -235,7 +238,8 @@ export async function openChannelInSidebar (
|
||||
_class: Ref<Class<Doc>>,
|
||||
doc?: Doc,
|
||||
thread?: Ref<ActivityMessage>,
|
||||
newTab = true
|
||||
newTab = true,
|
||||
selectedMessageId?: Ref<ActivityMessage>
|
||||
): Promise<void> {
|
||||
const client = getClient()
|
||||
|
||||
@ -267,6 +271,7 @@ export async function openChannelInSidebar (
|
||||
_id,
|
||||
_class,
|
||||
thread,
|
||||
selectedMessageId,
|
||||
channelName: name
|
||||
}
|
||||
}
|
||||
|
@ -17,11 +17,14 @@ import { writable } from 'svelte/store'
|
||||
import { type ChatMessage } from '@hcengineering/chunter'
|
||||
import { type Markup, type Ref } from '@hcengineering/core'
|
||||
import { languageStore } from '@hcengineering/ui'
|
||||
import { type ActivityMessage } from '@hcengineering/activity'
|
||||
|
||||
export const translatingMessagesStore = writable<Set<Ref<ChatMessage>>>(new Set())
|
||||
export const translatedMessagesStore = writable<Map<Ref<ChatMessage>, Markup>>(new Map())
|
||||
export const shownTranslatedMessagesStore = writable<Set<Ref<ChatMessage>>>(new Set())
|
||||
|
||||
export const threadMessagesStore = writable<ActivityMessage | undefined>(undefined)
|
||||
|
||||
languageStore.subscribe(() => {
|
||||
translatedMessagesStore.set(new Map())
|
||||
shownTranslatedMessagesStore.set(new Set())
|
||||
|
@ -100,7 +100,13 @@ export interface InlineButton extends AttachedDoc {
|
||||
}
|
||||
|
||||
export interface ChatWidgetTab extends WidgetTab {
|
||||
data: { _id?: Ref<Doc>, _class?: Ref<Class<Doc>>, thread?: Ref<ActivityMessage>, channelName: string }
|
||||
data: {
|
||||
_id?: Ref<Doc>
|
||||
_class?: Ref<Class<Doc>>
|
||||
thread?: Ref<ActivityMessage>
|
||||
channelName: string
|
||||
selectedMessageId?: Ref<ActivityMessage>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -234,7 +240,14 @@ export default plugin(chunterId, {
|
||||
CanTranslateMessage: '' as Resource<(doc?: Doc | Doc[]) => Promise<boolean>>,
|
||||
OpenThreadInSidebar: '' as Resource<(_id: Ref<ActivityMessage>, msg?: ActivityMessage, doc?: Doc) => Promise<void>>,
|
||||
OpenChannelInSidebar: '' as Resource<
|
||||
(_id: Ref<Doc>, _class: Ref<Doc>, doc?: Doc, thread?: Ref<ActivityMessage>) => Promise<void>
|
||||
(
|
||||
_id: Ref<Doc>,
|
||||
_class: Ref<Class<Doc>>,
|
||||
doc?: Doc,
|
||||
thread?: Ref<ActivityMessage>,
|
||||
newTab?: boolean,
|
||||
selectedMessageId?: Ref<ActivityMessage>
|
||||
) => Promise<void>
|
||||
>
|
||||
}
|
||||
})
|
||||
|
@ -64,6 +64,7 @@
|
||||
|
||||
$: if (object !== undefined && object?._id !== value.objectId) {
|
||||
object = undefined
|
||||
isLoading = true
|
||||
}
|
||||
|
||||
let isActionMenuOpened = false
|
||||
|
@ -1,13 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { PersonAccount } from '@hcengineering/contact'
|
||||
import { Avatar, personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||
import { BrowserNotification } from '@hcengineering/notification'
|
||||
import { Button, navigate, Notification as PlatformNotification, NotificationToast } from '@hcengineering/ui'
|
||||
import view, { decodeObjectURI } from '@hcengineering/view'
|
||||
import chunter from '@hcengineering/chunter'
|
||||
import view from '@hcengineering/view'
|
||||
import chunter, { ThreadMessage } from '@hcengineering/chunter'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { ActivityMessage } from '@hcengineering/activity'
|
||||
import activity, { ActivityMessage } from '@hcengineering/activity'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
import { pushAvailable, subscribePush } from '../utils'
|
||||
import plugin from '../plugin'
|
||||
@ -15,6 +16,9 @@
|
||||
export let notification: PlatformNotification
|
||||
export let onRemove: () => void
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
$: value = notification.params?.value as BrowserNotification
|
||||
|
||||
$: senderAccount =
|
||||
@ -24,18 +28,35 @@
|
||||
async function openChannelInSidebar (): Promise<void> {
|
||||
if (!value.onClickLocation) return
|
||||
const { onClickLocation } = value
|
||||
const [_id, _class] = decodeObjectURI(onClickLocation.path[3] ?? '')
|
||||
let _id: Ref<Doc> | undefined = value.objectId
|
||||
let _class: Ref<Class<Doc>> | undefined = value.objectClass
|
||||
let thread = onClickLocation.path[4] as Ref<ActivityMessage> | undefined
|
||||
const selectedMessageId: Ref<ActivityMessage> | undefined = value.messageId
|
||||
|
||||
if (_class && _id && hierarchy.isDerived(_class, activity.class.ActivityMessage)) {
|
||||
const message = await client.findOne<ActivityMessage>(_class, { _id: _id as Ref<ActivityMessage> })
|
||||
|
||||
if (hierarchy.isDerived(_class, chunter.class.ThreadMessage)) {
|
||||
const threadMessage = message as ThreadMessage
|
||||
_id = threadMessage?.objectId
|
||||
_class = threadMessage?.objectClass
|
||||
thread = threadMessage?.attachedTo
|
||||
} else {
|
||||
_id = message?.attachedTo
|
||||
_class = message?.attachedToClass
|
||||
thread = (message?.replies ?? 0) > 0 ? message?._id : undefined
|
||||
}
|
||||
}
|
||||
|
||||
onRemove()
|
||||
|
||||
if (!_id || !_class || _id === '' || _class === '') {
|
||||
if (!_id || !_class || _id === '' || _class === '' || selectedMessageId === undefined) {
|
||||
navigate(onClickLocation)
|
||||
return
|
||||
}
|
||||
|
||||
const thread = onClickLocation.path[4] as Ref<ActivityMessage> | undefined
|
||||
const fn = await getResource(chunter.function.OpenChannelInSidebar)
|
||||
await fn(_id, _class, undefined, thread)
|
||||
await fn(_id, _class, undefined, thread, true, selectedMessageId)
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -56,7 +77,7 @@
|
||||
<Button
|
||||
label={view.string.Open}
|
||||
on:click={() => {
|
||||
openChannelInSidebar()
|
||||
void openChannelInSidebar()
|
||||
}}
|
||||
/>
|
||||
{/if}
|
||||
|
@ -53,6 +53,10 @@ export interface BrowserNotification extends Doc {
|
||||
onClickLocation?: Location
|
||||
senderId?: Ref<Account>
|
||||
tag: Ref<Doc>
|
||||
messageId?: Ref<ActivityMessage>
|
||||
messageClass?: Ref<Class<ActivityMessage>>
|
||||
objectId: Ref<Doc>
|
||||
objectClass: Ref<Class<Doc>>
|
||||
}
|
||||
|
||||
export interface PushData {
|
||||
|
@ -160,6 +160,7 @@ export default plugin(timeId, {
|
||||
CreatedToDo: '' as IntlString,
|
||||
AddToDo: '' as IntlString,
|
||||
NewToDoDetails: '' as IntlString,
|
||||
ToDo: '' as IntlString
|
||||
ToDo: '' as IntlString,
|
||||
NewToDo: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -316,3 +316,20 @@ export function minimizeSidebar (closedByUser = false): void {
|
||||
|
||||
sidebarStore.set({ ...state, ...widgetsState, widget: undefined, variant: SidebarVariant.MINI })
|
||||
}
|
||||
|
||||
export function updateTabData (widget: Ref<Widget>, tabId: string, data: Record<string, any>): void {
|
||||
const state = get(sidebarStore)
|
||||
const { widgetsState } = state
|
||||
const widgetState = widgetsState.get(widget)
|
||||
|
||||
if (widgetState === undefined) return
|
||||
|
||||
const tabs = widgetState.tabs.map((it) => (it.id === tabId ? { ...it, data: { ...it.data, ...data } } : it))
|
||||
|
||||
widgetsState.set(widget, { ...widgetState, tabs })
|
||||
|
||||
sidebarStore.set({
|
||||
...state,
|
||||
widgetsState
|
||||
})
|
||||
}
|
||||
|
@ -175,7 +175,8 @@ export async function getCommonNotificationTxes (
|
||||
doc,
|
||||
receiver,
|
||||
sender,
|
||||
subscriptions
|
||||
subscriptions,
|
||||
_class
|
||||
)
|
||||
}
|
||||
|
||||
@ -487,6 +488,14 @@ export async function getTranslatedNotificationContent (
|
||||
return { title: '', body: '' }
|
||||
}
|
||||
|
||||
function isReactionMessage (message?: ActivityMessage): boolean {
|
||||
return (
|
||||
message !== undefined &&
|
||||
message._class === activity.class.DocUpdateMessage &&
|
||||
(message as DocUpdateMessage).objectClass === activity.class.Reaction
|
||||
)
|
||||
}
|
||||
|
||||
export async function createPushFromInbox (
|
||||
control: TriggerControl,
|
||||
receiver: ReceiverInfo,
|
||||
@ -497,10 +506,9 @@ export async function createPushFromInbox (
|
||||
sender: SenderInfo,
|
||||
_id: Ref<Doc>,
|
||||
subscriptions: PushSubscription[],
|
||||
cache: Map<Ref<Doc>, Doc> = new Map<Ref<Doc>, Doc>()
|
||||
message?: ActivityMessage
|
||||
): Promise<Tx | undefined> {
|
||||
let { title, body } = await getTranslatedNotificationContent(data, _class, control)
|
||||
|
||||
if (title === '' || body === '') {
|
||||
return
|
||||
}
|
||||
@ -515,13 +523,12 @@ export async function createPushFromInbox (
|
||||
|
||||
if (provider !== undefined) {
|
||||
const encodeFn = await getResource(provider.encode)
|
||||
const doc = cache.get(attachedTo) ?? (await control.findAll(control.ctx, attachedToClass, { _id: attachedTo }))[0]
|
||||
const doc = (await control.findAll(control.ctx, attachedToClass, { _id: attachedTo }))[0]
|
||||
|
||||
if (doc === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
cache.set(doc._id, doc)
|
||||
id = await encodeFn(doc, control)
|
||||
}
|
||||
|
||||
@ -543,6 +550,12 @@ export async function createPushFromInbox (
|
||||
body,
|
||||
senderId: sender._id,
|
||||
tag: _id,
|
||||
objectId: attachedTo,
|
||||
objectClass: attachedToClass,
|
||||
messageId: isReactionMessage(message) ? (message?.attachedTo as Ref<ActivityMessage>) : message?._id,
|
||||
messageClass: isReactionMessage(message)
|
||||
? (message?.attachedToClass as Ref<Class<ActivityMessage>>)
|
||||
: message?._class,
|
||||
onClickLocation: {
|
||||
path
|
||||
}
|
||||
@ -664,6 +677,7 @@ export async function applyNotificationProviders (
|
||||
receiver: ReceiverInfo,
|
||||
sender: SenderInfo,
|
||||
subscriptions: PushSubscription[],
|
||||
_class = notification.class.ActivityInboxNotification,
|
||||
message?: ActivityMessage
|
||||
): Promise<void> {
|
||||
const resources = control.modelDb.findAllSync(serverNotification.class.NotificationProviderResources, {})
|
||||
@ -676,10 +690,11 @@ export async function applyNotificationProviders (
|
||||
attachedTo,
|
||||
attachedToClass,
|
||||
data,
|
||||
notification.class.ActivityInboxNotification,
|
||||
_class,
|
||||
sender,
|
||||
data._id,
|
||||
subscriptions
|
||||
subscriptions,
|
||||
message
|
||||
)
|
||||
if (pushTx !== undefined) {
|
||||
res.push(pushTx)
|
||||
@ -796,6 +811,7 @@ export async function getNotificationTxes (
|
||||
receiver,
|
||||
sender,
|
||||
subscriptions,
|
||||
notificationData._class,
|
||||
message
|
||||
)
|
||||
}
|
||||
|
@ -172,6 +172,8 @@
|
||||
"@hcengineering/github": "^0.6.0",
|
||||
"@hcengineering/github-assets": "^0.6.0",
|
||||
"@hcengineering/server-ai-bot": "^0.6.0",
|
||||
"@hcengineering/server-ai-bot-resources": "^0.6.0"
|
||||
"@hcengineering/server-ai-bot-resources": "^0.6.0",
|
||||
"@hcengineering/time": "^0.6.0",
|
||||
"@hcengineering/time-assets": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import { trackerId } from '@hcengineering/tracker'
|
||||
import { trainingId } from '@hcengineering/training'
|
||||
import { viewId } from '@hcengineering/view'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
import { timeId } from '@hcengineering/time'
|
||||
import coreEng from '@hcengineering/core/lang/en.json'
|
||||
import loginEng from '@hcengineering/login-assets/lang/en.json'
|
||||
import platformEng from '@hcengineering/platform/lang/en.json'
|
||||
@ -68,6 +69,7 @@ import trackerEn from '@hcengineering/tracker-assets/lang/en.json'
|
||||
import trainingEn from '@hcengineering/training-assets/lang/en.json'
|
||||
import viewEn from '@hcengineering/view-assets/lang/en.json'
|
||||
import workbenchEn from '@hcengineering/workbench-assets/lang/en.json'
|
||||
import timeEn from '@hcengineering/time-assets/lang/en.json'
|
||||
|
||||
export function registerStringLoaders (): void {
|
||||
addStringsLoader(coreId, async (lang: string) => coreEng)
|
||||
@ -106,4 +108,5 @@ export function registerStringLoaders (): void {
|
||||
addStringsLoader(productsId, async (lang: string) => productsEn)
|
||||
addStringsLoader(trainingId, async (lang: string) => trainingEn)
|
||||
addStringsLoader(githubId, async (lang: string) => githubEn)
|
||||
addStringsLoader(timeId, async (lang: string) => timeEn)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user