mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-08 17:00:47 +00:00
Fix thread messages pin (#6129)
Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
parent
27c626857a
commit
3b9318e34a
@ -92,7 +92,7 @@
|
|||||||
skipLabels={!isDocChannel}
|
skipLabels={!isDocChannel}
|
||||||
selectedFilters={filters}
|
selectedFilters={filters}
|
||||||
startFromBottom
|
startFromBottom
|
||||||
{selectedMessageId}
|
bind:selectedMessageId
|
||||||
{collection}
|
{collection}
|
||||||
provider={dataProvider}
|
provider={dataProvider}
|
||||||
{isAsideOpened}
|
{isAsideOpened}
|
||||||
|
@ -78,7 +78,7 @@
|
|||||||
on:aside-toggled
|
on:aside-toggled
|
||||||
on:close
|
on:close
|
||||||
>
|
>
|
||||||
<PinnedMessages {_id} {_class} />
|
<PinnedMessages {_id} {_class} on:select />
|
||||||
</Header>
|
</Header>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
export let scrollElement: HTMLDivElement | undefined = undefined
|
export let scrollElement: HTMLDivElement | undefined = undefined
|
||||||
export let startFromBottom = false
|
export let startFromBottom = false
|
||||||
export let selectedFilters: Ref<ActivityMessagesFilter>[] = []
|
export let selectedFilters: Ref<ActivityMessagesFilter>[] = []
|
||||||
export let withDates: boolean = true
|
export let embedded = false
|
||||||
export let collection: string | undefined = undefined
|
export let collection: string | undefined = undefined
|
||||||
export let showEmbedded = false
|
export let showEmbedded = false
|
||||||
export let skipLabels = false
|
export let skipLabels = false
|
||||||
@ -355,7 +355,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateSelectedDate (): void {
|
function updateSelectedDate (): void {
|
||||||
if (!withDates) {
|
if (embedded) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,13 +468,13 @@
|
|||||||
if (isLoading || !isScrollInitialized || isInitialScrolling) {
|
if (isLoading || !isScrollInitialized || isInitialScrolling) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const msg = messages.find(({ _id }) => _id === selectedMessageId)
|
const msg = $metadataStore.find(({ _id }) => _id === selectedMessageId)
|
||||||
if (msg !== undefined) {
|
if (msg !== undefined) {
|
||||||
const isReload = provider.jumpToMessage(msg)
|
const isReload = provider.jumpToMessage(msg)
|
||||||
if (isReload) {
|
if (isReload) {
|
||||||
reinitializeScroll()
|
reinitializeScroll()
|
||||||
}
|
}
|
||||||
} else {
|
} else if (selectedMessageId === undefined) {
|
||||||
provider.jumpToEnd()
|
provider.jumpToEnd()
|
||||||
reinitializeScroll()
|
reinitializeScroll()
|
||||||
}
|
}
|
||||||
@ -677,7 +677,7 @@
|
|||||||
{#if startFromBottom}
|
{#if startFromBottom}
|
||||||
<div class="grower" />
|
<div class="grower" />
|
||||||
{/if}
|
{/if}
|
||||||
{#if withDates && displayMessages.length > 0 && selectedDate}
|
{#if !embedded && displayMessages.length > 0 && selectedDate}
|
||||||
<div class="selectedDate">
|
<div class="selectedDate">
|
||||||
<JumpToDateSelector {selectedDate} fixed on:jumpToDate={jumpToDate} />
|
<JumpToDateSelector {selectedDate} fixed on:jumpToDate={jumpToDate} />
|
||||||
</div>
|
</div>
|
||||||
@ -702,7 +702,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<slot name="header" />
|
<slot name="header" />
|
||||||
|
|
||||||
{#if displayMessages.length === 0 && !hierarchy.isDerived(objectClass, activity.class.ActivityMessage)}
|
{#if displayMessages.length === 0 && !embedded}
|
||||||
<BlankView
|
<BlankView
|
||||||
icon={chunter.icon.Thread}
|
icon={chunter.icon.Thread}
|
||||||
header={chunter.string.NoMessagesInChannel}
|
header={chunter.string.NoMessagesInChannel}
|
||||||
@ -717,7 +717,7 @@
|
|||||||
<ActivityMessagesSeparator bind:element={separatorElement} label={activity.string.New} />
|
<ActivityMessagesSeparator bind:element={separatorElement} label={activity.string.New} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if withDates && message.createdOn && $datesStore.includes(message.createdOn)}
|
{#if !embedded && message.createdOn && $datesStore.includes(message.createdOn)}
|
||||||
<JumpToDateSelector selectedDate={message.createdOn} on:jumpToDate={jumpToDate} />
|
<JumpToDateSelector selectedDate={message.createdOn} on:jumpToDate={jumpToDate} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@ -741,7 +741,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</Scroller>
|
</Scroller>
|
||||||
|
|
||||||
{#if showScrollDownButton}
|
{#if !embedded && showScrollDownButton}
|
||||||
<div class="down-button absolute">
|
<div class="down-button absolute">
|
||||||
<ModernButton
|
<ModernButton
|
||||||
label={chunter.string.LatestMessages}
|
label={chunter.string.LatestMessages}
|
||||||
|
@ -16,23 +16,27 @@
|
|||||||
import core, { Doc, getCurrentAccount, Ref, Space } from '@hcengineering/core'
|
import core, { Doc, getCurrentAccount, Ref, Space } from '@hcengineering/core'
|
||||||
import {
|
import {
|
||||||
defineSeparators,
|
defineSeparators,
|
||||||
|
getCurrentLocation,
|
||||||
Label,
|
Label,
|
||||||
location as locationStore,
|
location as locationStore,
|
||||||
ModernButton,
|
ModernButton,
|
||||||
|
navigate,
|
||||||
panelSeparators,
|
panelSeparators,
|
||||||
Separator
|
Separator
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { DocNotifyContext } from '@hcengineering/notification'
|
import { DocNotifyContext } from '@hcengineering/notification'
|
||||||
import { ActivityMessagesFilter } from '@hcengineering/activity'
|
import { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { Channel } from '@hcengineering/chunter'
|
import { Channel } from '@hcengineering/chunter'
|
||||||
import view from '@hcengineering/view'
|
import view from '@hcengineering/view'
|
||||||
|
import { messageInFocus } from '@hcengineering/activity-resources'
|
||||||
|
|
||||||
import ChannelComponent from './Channel.svelte'
|
import ChannelComponent from './Channel.svelte'
|
||||||
import ChannelHeader from './ChannelHeader.svelte'
|
import ChannelHeader from './ChannelHeader.svelte'
|
||||||
import DocAside from './chat/DocAside.svelte'
|
import DocAside from './chat/DocAside.svelte'
|
||||||
import chunter from '../plugin'
|
import chunter from '../plugin'
|
||||||
import ChannelAside from './chat/ChannelAside.svelte'
|
import ChannelAside from './chat/ChannelAside.svelte'
|
||||||
|
import { isThreadMessage } from '../utils'
|
||||||
|
|
||||||
export let object: Doc
|
export let object: Doc
|
||||||
export let context: DocNotifyContext | undefined
|
export let context: DocNotifyContext | undefined
|
||||||
@ -76,6 +80,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
defineSeparators('aside', panelSeparators)
|
defineSeparators('aside', panelSeparators)
|
||||||
|
|
||||||
|
async function handleMessageSelect (event: CustomEvent<ActivityMessage>): Promise<void> {
|
||||||
|
const message = event.detail
|
||||||
|
|
||||||
|
if (isThreadMessage(message)) {
|
||||||
|
const location = getCurrentLocation()
|
||||||
|
location.path[4] = message.attachedTo
|
||||||
|
navigate(location)
|
||||||
|
}
|
||||||
|
|
||||||
|
messageInFocus.set(message._id)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="popupPanel panel" class:embedded>
|
<div class="popupPanel panel" class:embedded>
|
||||||
@ -89,6 +105,7 @@
|
|||||||
canOpen={isDocChat}
|
canOpen={isDocChat}
|
||||||
{isAsideShown}
|
{isAsideShown}
|
||||||
on:close
|
on:close
|
||||||
|
on:select={handleMessageSelect}
|
||||||
on:aside-toggled={() => {
|
on:aside-toggled={() => {
|
||||||
isAsideShown = !isAsideShown
|
isAsideShown = !isAsideShown
|
||||||
}}
|
}}
|
||||||
|
@ -19,32 +19,53 @@
|
|||||||
import activity, { ActivityMessage } from '@hcengineering/activity'
|
import activity, { ActivityMessage } from '@hcengineering/activity'
|
||||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||||
import view from '@hcengineering/view'
|
import view from '@hcengineering/view'
|
||||||
|
import { ThreadMessage } from '@hcengineering/chunter'
|
||||||
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
|
||||||
import chunter from '../plugin'
|
import chunter from '../plugin'
|
||||||
|
|
||||||
export let _class: Ref<Class<Doc>>
|
export let _class: Ref<Class<Doc>>
|
||||||
export let _id: Ref<Doc>
|
export let _id: Ref<Doc>
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
const pinnedQuery = createQuery()
|
const pinnedQuery = createQuery()
|
||||||
|
const pinnedThreadsQuery = createQuery()
|
||||||
|
|
||||||
let pinnedMessagesCount = 0
|
let pinnedMessagesCount = 0
|
||||||
|
let pinnedThreadsCount = 0
|
||||||
|
|
||||||
$: pinnedQuery.query(
|
$: pinnedQuery.query(
|
||||||
activity.class.ActivityMessage,
|
activity.class.ActivityMessage,
|
||||||
{ attachedTo: _id, isPinned: true },
|
{ attachedTo: _id, isPinned: true },
|
||||||
(res: ActivityMessage[]) => {
|
(res: ActivityMessage[]) => {
|
||||||
pinnedMessagesCount = res.length
|
pinnedMessagesCount = res.length
|
||||||
}
|
},
|
||||||
|
{ projection: { _id: 1, attachedTo: 1, isPinned: 1 } }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
$: pinnedThreadsQuery.query(
|
||||||
|
chunter.class.ThreadMessage,
|
||||||
|
{ objectId: _id, isPinned: true },
|
||||||
|
(res: ThreadMessage[]) => {
|
||||||
|
pinnedThreadsCount = res.length
|
||||||
|
},
|
||||||
|
{ projection: { _id: 1, objectId: 1, isPinned: 1 } }
|
||||||
|
)
|
||||||
|
|
||||||
function openMessagesPopup (ev: MouseEvent) {
|
function openMessagesPopup (ev: MouseEvent) {
|
||||||
showPopup(PinnedMessagesPopup, { attachedTo: _id, attachedToClass: _class }, eventToHTMLElement(ev))
|
showPopup(PinnedMessagesPopup, { attachedTo: _id, attachedToClass: _class }, eventToHTMLElement(ev), (result) => {
|
||||||
|
if (result == null) return
|
||||||
|
dispatch('select', result)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: count = pinnedMessagesCount + pinnedThreadsCount
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if pinnedMessagesCount > 0}
|
{#if count > 0}
|
||||||
<div class="antiHSpacer x2" />
|
<div class="antiHSpacer x2" />
|
||||||
<ModernButton size={'extra-small'} on:click={openMessagesPopup}>
|
<ModernButton size={'extra-small'} on:click={openMessagesPopup}>
|
||||||
<Icon icon={view.icon.Pin} size={'x-small'} />
|
<Icon icon={view.icon.Pin} size={'x-small'} />
|
||||||
<span class="text-sm"><Label label={chunter.string.PinnedCount} params={{ count: pinnedMessagesCount }} /></span>
|
<span class="text-sm"><Label label={chunter.string.PinnedCount} params={{ count }} /></span>
|
||||||
</ModernButton>
|
</ModernButton>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -13,12 +13,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import activity, { ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
|
import activity, { ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
|
||||||
import { ActivityMessagePresenter } from '@hcengineering/activity-resources'
|
import { ActivityMessagePresenter, sortActivityMessages } from '@hcengineering/activity-resources'
|
||||||
import { ActionIcon, IconClose } from '@hcengineering/ui'
|
import { ActionIcon, IconClose } from '@hcengineering/ui'
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import { ThreadMessage } from '@hcengineering/chunter'
|
||||||
|
import { Class, Doc, Ref, SortingOrder } from '@hcengineering/core'
|
||||||
|
|
||||||
import chunter from '../plugin'
|
import chunter from '../plugin'
|
||||||
|
|
||||||
@ -26,40 +27,54 @@
|
|||||||
export let attachedToClass: Ref<Class<Doc>>
|
export let attachedToClass: Ref<Class<Doc>>
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
|
||||||
const messagesQuery = createQuery()
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
const pinnedQuery = createQuery()
|
||||||
|
const pinnedThreadsQuery = createQuery()
|
||||||
|
|
||||||
let pinnedMessages: DisplayActivityMessage[] = []
|
let pinnedMessages: ActivityMessage[] = []
|
||||||
|
let pinnedThreads: ThreadMessage[] = []
|
||||||
|
|
||||||
$: messagesQuery.query(activity.class.ActivityMessage, { attachedTo, isPinned: true }, (res: ActivityMessage[]) => {
|
$: pinnedQuery.query(activity.class.ActivityMessage, { attachedTo, isPinned: true }, (res: ActivityMessage[]) => {
|
||||||
pinnedMessages = res as DisplayActivityMessage[]
|
pinnedMessages = res
|
||||||
|
|
||||||
if (pinnedMessages.length === 0) {
|
|
||||||
dispatch('close')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
async function unPinMessaage (message: ActivityMessage): Promise<void> {
|
$: pinnedThreadsQuery.query(
|
||||||
|
chunter.class.ThreadMessage,
|
||||||
|
{ objectId: attachedTo, isPinned: true },
|
||||||
|
(res: ThreadMessage[]) => {
|
||||||
|
pinnedThreads = res
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
$: if (pinnedMessages.length === 0 && pinnedThreads.length === 0) {
|
||||||
|
dispatch('close', undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function unpinMessage (message: ActivityMessage): Promise<void> {
|
||||||
await client.update(message, { isPinned: false })
|
await client.update(message, { isPinned: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: displayMessages = sortActivityMessages(pinnedMessages.concat(pinnedThreads), SortingOrder.Descending)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiPopup vScroll popup">
|
<div class="antiPopup vScroll popup">
|
||||||
{#each pinnedMessages as message}
|
{#each displayMessages as message}
|
||||||
<div class="message relative">
|
<div class="message relative">
|
||||||
<ActivityMessagePresenter
|
<ActivityMessagePresenter
|
||||||
value={message}
|
value={message}
|
||||||
withActions={false}
|
withActions={false}
|
||||||
hoverable={false}
|
hoverable={false}
|
||||||
skipLabel={!hierarchy.isDerived(attachedToClass, chunter.class.ChunterSpace)}
|
skipLabel={true}
|
||||||
|
onClick={() => {
|
||||||
|
dispatch('close', message)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
size="small"
|
size="small"
|
||||||
icon={IconClose}
|
icon={IconClose}
|
||||||
action={() => {
|
action={() => {
|
||||||
unPinMessaage(message)
|
unpinMessage(message)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
import { Doc, Ref } from '@hcengineering/core'
|
import { Doc, Ref } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { Breadcrumbs, IconClose, Label, location as locationStore } from '@hcengineering/ui'
|
import { Breadcrumbs, IconClose, Label, location as locationStore } from '@hcengineering/ui'
|
||||||
import { createEventDispatcher, onMount } from 'svelte'
|
import { createEventDispatcher, onDestroy } from 'svelte'
|
||||||
import activity, { ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
|
import activity, { ActivityMessage, DisplayActivityMessage } from '@hcengineering/activity'
|
||||||
import { getMessageFromLoc } from '@hcengineering/activity-resources'
|
import { getMessageFromLoc, messageInFocus } from '@hcengineering/activity-resources'
|
||||||
import contact from '@hcengineering/contact'
|
import contact from '@hcengineering/contact'
|
||||||
|
|
||||||
import chunter from '../../plugin'
|
import chunter from '../../plugin'
|
||||||
@ -45,8 +45,23 @@
|
|||||||
let channelName: string | undefined = undefined
|
let channelName: string | undefined = undefined
|
||||||
let dataProvider: ChannelDataProvider | undefined = undefined
|
let dataProvider: ChannelDataProvider | undefined = undefined
|
||||||
|
|
||||||
locationStore.subscribe((newLocation) => {
|
const unsubscribe = messageInFocus.subscribe((id) => {
|
||||||
selectedMessageId = getMessageFromLoc(newLocation)
|
if (id !== undefined && id !== selectedMessageId) {
|
||||||
|
selectedMessageId = id
|
||||||
|
}
|
||||||
|
|
||||||
|
messageInFocus.set(undefined)
|
||||||
|
})
|
||||||
|
|
||||||
|
const unsubscribeLocation = locationStore.subscribe((newLocation) => {
|
||||||
|
const id = getMessageFromLoc(newLocation)
|
||||||
|
selectedMessageId = id
|
||||||
|
messageInFocus.set(id)
|
||||||
|
})
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
unsubscribe()
|
||||||
|
unsubscribeLocation()
|
||||||
})
|
})
|
||||||
|
|
||||||
$: messageQuery.query(activity.class.ActivityMessage, { _id }, (result: ActivityMessage[]) => {
|
$: messageQuery.query(activity.class.ActivityMessage, { _id }, (result: ActivityMessage[]) => {
|
||||||
@ -111,14 +126,13 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
{#if message && dataProvider !== undefined}
|
{#if message && dataProvider !== undefined}
|
||||||
<ChannelScrollView
|
<ChannelScrollView
|
||||||
{selectedMessageId}
|
bind:selectedMessageId
|
||||||
withDates={false}
|
embedded
|
||||||
skipLabels
|
skipLabels
|
||||||
object={message}
|
object={message}
|
||||||
objectId={message._id}
|
objectId={message._id}
|
||||||
objectClass={message._class}
|
objectClass={message._class}
|
||||||
provider={dataProvider}
|
provider={dataProvider}
|
||||||
loadMoreAllowed={false}
|
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
|
Loading…
Reference in New Issue
Block a user