EQMS-1633 Fix qms inline comments (#9873)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov
2025-09-18 16:37:18 +07:00
committed by GitHub
parent 32027c80ea
commit c633be0084
8 changed files with 178 additions and 186 deletions
@@ -25,7 +25,8 @@
TableOfContents,
TableOfContentsContent,
getNodeElement,
highlightUpdateCommand
highlightUpdateCommand,
selectNode
} from '@hcengineering/text-editor-resources'
import { EditBox, Label, Scroller } from '@hcengineering/ui'
import { getCollaborationUser } from '@hcengineering/view-resources'
@@ -41,8 +42,8 @@
$documentCommentHighlightedLocation as documentCommentHighlightedLocation,
$documentComments as documentComments,
documentCommentsDisplayRequested,
documentCommentsHighlightUpdated,
documentCommentsLocationNavigateRequested,
documentCommentsAddCanceled,
$isEditable as isEditable
} from '../../stores/editors/document'
import DocumentPrintTitlePage from '../print/DocumentPrintTitlePage.svelte'
@@ -58,19 +59,16 @@
let headings: Heading[] = []
let textEditor: CollaboratorEditor
let selectedNodeId: string | null | undefined = undefined
let isFocused = false
let editor: Editor
let title = $controlledDocument?.title ?? ''
$: isTemplate =
$controlledDocument != null && hierarchy.hasMixin($controlledDocument, documents.mixin.DocumentTemplate)
function handleRefreshHighlight () {
if (!textEditor) {
return
}
$: commentUuids = $documentComments.map((p) => p.nodeId).filter((id) => id != null)
textEditor.commands()?.command(highlightUpdateCommand())
function handleRefreshHighlight (): void {
textEditor?.commands()?.command(highlightUpdateCommand())
}
const unsubscribeHighlightRefresh = merge([documentCommentHighlightedLocation, documentComments.updates]).subscribe({
@@ -82,21 +80,28 @@
const unsubscribeNavigateToLocation = documentCommentsLocationNavigateRequested.subscribe({
// eslint-disable-next-line @typescript-eslint/no-misused-promises
next: async ({ nodeId }) => {
if (!nodeId) {
if (nodeId == null) {
handleRefreshHighlight()
return
}
if (!textEditor) {
return
selectedNodeId = nodeId
if (editor !== undefined) {
await tick()
const element = getNodeElement(editor, nodeId)
element?.scrollIntoView({ behavior: 'smooth' })
}
}
})
await tick()
const element = getNodeElement(editor, nodeId)
if (element) {
element.scrollIntoView({ behavior: 'smooth' })
const unsubscribeCommentsAddCanceled = documentCommentsAddCanceled.subscribe({
next: ({ nodeId }) => {
if (editor !== undefined && nodeId != null) {
if (selectNode(editor, nodeId)) {
editor.commands.unsetQMSInlineCommentMark()
}
}
}
})
@@ -104,6 +109,7 @@
onDestroy(() => {
unsubscribeHighlightRefresh()
unsubscribeNavigateToLocation()
unsubscribeCommentsAddCanceled()
})
const handleUpdateTitle = async () => {
@@ -137,15 +143,9 @@
return null
}
function handleShowDocumentComments (uuid: string) {
if (!uuid) {
return
}
documentCommentsDisplayRequested({
element: getNodeElement(editor, uuid),
nodeId: uuid
})
function handleShowDocumentComments (nodeId: string): void {
const element = getNodeElement(editor, nodeId)
documentCommentsDisplayRequested({ element, nodeId })
}
async function createEmbedding (file: File): Promise<{ file: Ref<Blob>, type: string } | undefined> {
@@ -241,32 +241,22 @@
qmsInlineComment: {
isHighlightModeOn: () => $canViewDocumentComments || $canAddDocumentComments,
getNodeHighlight: handleNodeHighlight,
onNodeSelected: (uuid) => {
if (selectedNodeId !== uuid) {
selectedNodeId = uuid
}
if (isFocused) {
documentCommentsHighlightUpdated(selectedNodeId !== null ? { nodeId: selectedNodeId } : null)
}
},
onNodeClicked: (uuid) => {
if (selectedNodeId !== uuid) {
selectedNodeId = uuid
}
onNodeClicked: (uuids) => {
// filter out those uuids that are not in comments
uuids = Array.isArray(uuids) ? uuids : [uuids]
uuids = uuids.filter((id) => commentUuids.includes(id)).sort()
if (!$arePopupsOpened && $canViewDocumentComments && selectedNodeId) {
// scroll through the comments as user clicks on the same node
const currIndex = selectedNodeId != null ? uuids.indexOf(selectedNodeId) : -1
const nextIndex = currIndex === -1 ? 0 : (currIndex + 1) % uuids.length
selectedNodeId = uuids[nextIndex]
if (!$arePopupsOpened && $canViewDocumentComments && selectedNodeId != null) {
handleShowDocumentComments(selectedNodeId)
}
}
}
},
hooks: {
focus: {
onFocus: (focused) => {
isFocused = focused
}
}
},
toc: {
onChange: (h) => {
headings = h
@@ -11,17 +11,29 @@
const dispatch = createEventDispatcher()
let messageId: Ref<ChatMessage> = generateId()
async function handleMessage (event: CustomEvent<string>): Promise<void> {
const messageId: Ref<ChatMessage> = generateId()
const comment = await addDocumentCommentFx({ content: event.detail, messageId, nodeId })
messageId = generateId()
dispatch('close', comment)
}
let popup: HTMLDivElement | undefined
function handleClick (event: MouseEvent): void {
if (event.target instanceof Node) {
if (popup !== undefined && !popup.contains(event.target)) {
event.preventDefault()
event.stopPropagation()
dispatch('close', undefined)
}
}
}
</script>
<div class="text-editor-popup w-85">
<svelte:window on:click|capture={handleClick} />
<div class="text-editor-popup w-85" bind:this={popup}>
<ReferenceInput
autofocus
focusable