diff --git a/models/controlled-documents/src/index.ts b/models/controlled-documents/src/index.ts
index 0885da5aee..1b15efadc0 100644
--- a/models/controlled-documents/src/index.ts
+++ b/models/controlled-documents/src/index.ts
@@ -13,60 +13,60 @@
// limitations under the License.
//
-import documentsPlugin, {
- documentsId,
- type Document,
- type DocumentSpace,
- DocumentState
-} from '@hcengineering/controlled-documents'
import activity from '@hcengineering/activity'
import contact from '@hcengineering/contact'
+import documentsPlugin, {
+ documentsId,
+ DocumentState,
+ type Document,
+ type DocumentSpace
+} from '@hcengineering/controlled-documents'
import { type Builder } from '@hcengineering/model'
import chunter from '@hcengineering/model-chunter'
import core from '@hcengineering/model-core'
+import { generateClassNotificationTypes } from '@hcengineering/model-notification'
+import presentation from '@hcengineering/model-presentation'
+import print from '@hcengineering/model-print'
import request from '@hcengineering/model-request'
import tracker from '@hcengineering/model-tracker'
-import { generateClassNotificationTypes } from '@hcengineering/model-notification'
import view, { classPresenter, createAction } from '@hcengineering/model-view'
-import presentation from '@hcengineering/model-presentation'
import workbench from '@hcengineering/model-workbench'
import notification from '@hcengineering/notification'
import setting from '@hcengineering/setting'
import tags from '@hcengineering/tags'
-import print from '@hcengineering/model-print'
import textEditor from '@hcengineering/text-editor'
-import documents from './plugin'
+import { type Class, type Doc, type Ref } from '@hcengineering/core'
+import { type Action } from '@hcengineering/view'
import { definePermissions } from './permissions'
+import documents from './plugin'
+import { defineSpaceType } from './spaceType'
import {
+ TChangeControl,
+ TControlledDocument,
+ TControlledDocumentSnapshot,
+ TDocument,
+ TDocumentApprovalRequest,
+ TDocumentCategory,
+ TDocumentComment,
+ TDocumentMeta,
+ TDocumentRequest,
+ TDocumentReviewRequest,
+ TDocumentSnapshot,
TDocumentSpace,
TDocumentSpaceType,
TDocumentSpaceTypeDescriptor,
- TExternalSpace,
- TOrgSpace,
- TDocumentMeta,
- TProjectDocument,
- TProjectMeta,
- TProject,
- TDocument,
- TDocumentSnapshot,
- TControlledDocumentSnapshot,
- THierarchyDocument,
TDocumentTemplate,
TDocumentTraining,
- TDocumentCategory,
- TControlledDocument,
- TChangeControl,
- TDocumentRequest,
- TDocumentReviewRequest,
- TDocumentApprovalRequest,
- TTypeDocumentState,
+ TExternalSpace,
+ THierarchyDocument,
+ TOrgSpace,
+ TProject,
+ TProjectDocument,
+ TProjectMeta,
TTypeControlledDocumentState,
- TDocumentComment
+ TTypeDocumentState
} from './types'
-import { defineSpaceType } from './spaceType'
-import { type Class, type Doc, type Ref } from '@hcengineering/core'
-import { type Action } from '@hcengineering/view'
export { documentsId } from '@hcengineering/controlled-documents/src/index'
export * from './types'
@@ -105,6 +105,10 @@ export function createModel (builder: Builder): void {
titleProvider: documents.function.ControlledDocumentTitleProvider
})
+ builder.mixin(documents.class.DocumentMeta, core.class.Class, view.mixin.ObjectTitle, {
+ titleProvider: documents.function.ControlledDocumentTitleProvider
+ })
+
builder.mixin(documents.class.DocumentApprovalRequest, core.class.Class, view.mixin.ObjectPresenter, {
presenter: documents.component.DocumentApprovalRequestPresenter
})
diff --git a/packages/text/src/markup/__tests__/dsl.test.ts b/packages/text/src/markup/__tests__/dsl.test.ts
index 2458a48b36..69762fa291 100644
--- a/packages/text/src/markup/__tests__/dsl.test.ts
+++ b/packages/text/src/markup/__tests__/dsl.test.ts
@@ -21,7 +21,7 @@ describe('dsl', () => {
)
)
expect(jsonToHTML(doc)).toEqual(
- '
Hello, @World
Check out this link.
'
+ 'Hello, @World
Check out this link.
'
)
})
})
diff --git a/packages/text/src/nodes/reference.ts b/packages/text/src/nodes/reference.ts
index 6e75cfcffc..c333371095 100644
--- a/packages/text/src/nodes/reference.ts
+++ b/packages/text/src/nodes/reference.ts
@@ -15,10 +15,18 @@
import { Node, mergeAttributes } from '@tiptap/core'
import { getDataAttribute } from './utils'
+import { Class, Doc, Ref } from '@hcengineering/core'
+
+export interface ReferenceNodeProps {
+ id: Ref
+ objectclass: Ref>
+ label: string
+}
export interface ReferenceOptions {
- renderLabel: (props: { options: ReferenceOptions, node: any }) => string
- suggestion: { char: string }
+ renderLabel: (props: { options: ReferenceOptions, props: ReferenceNodeProps }) => string
+ suggestion: { char?: string }
+ HTMLAttributes: Record
}
/**
@@ -28,23 +36,26 @@ export const ReferenceNode = Node.create({
name: 'reference',
group: 'inline',
inline: true,
+ selectable: true,
+ atom: true,
+ draggable: true,
addAttributes () {
return {
id: getDataAttribute('id'),
objectclass: getDataAttribute('objectclass'),
- label: getDataAttribute('label'),
- class: { default: null }
+ label: getDataAttribute('label')
}
},
addOptions () {
return {
- renderLabel ({ options, node }) {
+ renderLabel ({ options, props }) {
// eslint-disable-next-line
- return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`
+ return `${options.suggestion.char}${props.label ?? props.id}`
},
- suggestion: { char: '@' }
+ suggestion: { char: '@' },
+ HTMLAttributes: {}
}
},
@@ -72,21 +83,25 @@ export const ReferenceNode = Node.create({
},
renderHTML ({ node, HTMLAttributes }) {
- const options = this.options
return [
'span',
mergeAttributes(
{
- 'data-type': this.name
+ 'data-type': this.name,
+ class: 'antiMention'
},
+ this.options.HTMLAttributes,
HTMLAttributes
),
- this.options.renderLabel({ options, node })
+ this.options.renderLabel({
+ options: this.options,
+ props: node.attrs as ReferenceNodeProps
+ })
]
},
renderText ({ node }) {
const options = this.options
- return options.renderLabel({ options, node })
+ return options.renderLabel({ options, props: node.attrs as ReferenceNodeProps })
}
})
diff --git a/plugins/controlled-documents-resources/src/index.ts b/plugins/controlled-documents-resources/src/index.ts
index e0b32883c5..40d379be40 100644
--- a/plugins/controlled-documents-resources/src/index.ts
+++ b/plugins/controlled-documents-resources/src/index.ts
@@ -109,6 +109,7 @@ import {
getAllDocumentStates,
getControlledDocumentTitle,
getDocumentMetaLinkFragment,
+ getDocumentMetaTitle,
getVisibleFilters,
isFolder,
renameFolder,
@@ -457,6 +458,7 @@ export default async (): Promise => ({
CanPrintDocument: canPrintDocument,
DocumentIdentifierProvider: documentIdentifierProvider,
ControlledDocumentTitleProvider: getControlledDocumentTitle,
+ DocumentMetaTitleProvider: getDocumentMetaTitle,
Comment: comment,
IsCommentVisible: isCommentVisible
},
diff --git a/plugins/controlled-documents-resources/src/plugin.ts b/plugins/controlled-documents-resources/src/plugin.ts
index 2c139b36c7..9e14aaa0cb 100644
--- a/plugins/controlled-documents-resources/src/plugin.ts
+++ b/plugins/controlled-documents-resources/src/plugin.ts
@@ -246,6 +246,7 @@ export default mergeIds(documentsId, documents, {
CanOpenDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise>,
CanPrintDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise>,
CanTransferDocument: '' as Resource<(doc?: Doc | Doc[]) => Promise>,
- ControlledDocumentTitleProvider: '' as Resource<(client: Client, ref: Ref, doc?: Doc) => Promise>
+ ControlledDocumentTitleProvider: '' as Resource<(client: Client, ref: Ref, doc?: Doc) => Promise>,
+ DocumentMetaTitleProvider: '' as Resource<(client: Client, ref: Ref, doc?: Doc) => Promise>
}
})
diff --git a/plugins/controlled-documents-resources/src/utils.ts b/plugins/controlled-documents-resources/src/utils.ts
index bc3122a6d7..d238e18a3b 100644
--- a/plugins/controlled-documents-resources/src/utils.ts
+++ b/plugins/controlled-documents-resources/src/utils.ts
@@ -727,6 +727,18 @@ export async function getControlledDocumentTitle (
return object.title
}
+export async function getDocumentMetaTitle (
+ client: Client,
+ ref: Ref,
+ doc?: DocumentMeta
+): Promise {
+ const object = doc ?? (await client.findOne(documents.class.DocumentMeta, { _id: ref }))
+
+ if (object === undefined) return ''
+
+ return object.title
+}
+
export const getCurrentEmployee = (): Ref | undefined => {
const currentAccount = getCurrentAccount()
const person = (currentAccount as PersonAccount)?.person
diff --git a/plugins/text-editor-resources/src/Completion.ts b/plugins/text-editor-resources/src/Completion.ts
deleted file mode 100644
index 061c752f46..0000000000
--- a/plugins/text-editor-resources/src/Completion.ts
+++ /dev/null
@@ -1,179 +0,0 @@
-import { Node, mergeAttributes } from '@tiptap/core'
-import { Plugin, PluginKey } from '@tiptap/pm/state'
-import { getDataAttribute } from './utils'
-
-import Suggestion, { type SuggestionOptions } from './components/extension/suggestion'
-
-export interface CompletionOptions {
- HTMLAttributes: Record
- renderLabel: (props: { options: CompletionOptions, node: any }) => string
- suggestion: Omit
- showDoc?: (event: MouseEvent, _id: string, _class: string) => void
-}
-
-export function clickHandler (opt: CompletionOptions): Plugin {
- return new Plugin({
- key: new PluginKey('completion-handleClickLink'),
- props: {
- handleClick: (view, pos, event) => {
- if (event.button !== 0) {
- return false
- }
-
- const link = (event.target as HTMLElement)?.closest('span')
- if (link != null) {
- const _class = link.getAttribute('data-objectclass')
- const _id = link.getAttribute('data-id')
- if (_id != null && _class != null) {
- opt.showDoc?.(event, _id, _class)
- }
- }
-
- return false
- }
- }
- })
-}
-
-export const Completion = Node.create({
- name: 'reference',
-
- addOptions () {
- return {
- HTMLAttributes: {},
- renderLabel ({ options, node }) {
- // eslint-disable-next-line
- return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`
- },
- suggestion: {
- char: '@',
- allowSpaces: true,
- // pluginKey: CompletionPluginKey,
- command: ({ editor, range, props }) => {
- // increase range.to by one when the next node is of type "text"
- // and starts with a space character
- const nodeAfter = editor.view.state.selection.$to.nodeAfter
- const overrideSpace = nodeAfter?.text?.startsWith(' ')
-
- if (overrideSpace !== undefined && overrideSpace) {
- // eslint-disable-next-line
- range.to += 1
- }
-
- if (props !== null) {
- editor
- .chain()
- .focus()
- .insertContentAt(range, [
- {
- type: this.name,
- attrs: props
- },
- {
- type: 'text',
- text: ' '
- }
- ])
- .run()
- }
- },
- allow: ({ editor, range }) => {
- if (range.from > editor.state.doc.content.size) return false
- const $from = editor.state.doc.resolve(range.from)
- const type = editor.schema.nodes[this.name]
- // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
- return !!$from.parent.type.contentMatch.matchType(type)
- }
- }
- }
- },
-
- group: 'inline',
-
- inline: true,
-
- selectable: true,
-
- atom: true,
-
- draggable: true,
-
- addAttributes () {
- return {
- id: getDataAttribute('id'),
- label: getDataAttribute('label'),
- objectclass: getDataAttribute('objectclass')
- }
- },
-
- parseHTML () {
- return [
- {
- tag: `span[data-type="${this.name}"]`
- }
- ]
- },
-
- renderHTML ({ node, HTMLAttributes }) {
- return [
- 'span',
- mergeAttributes(
- {
- 'data-type': this.name,
- class: 'antiMention'
- },
- this.options.HTMLAttributes,
- HTMLAttributes
- ),
- this.options.renderLabel({
- options: this.options,
- node
- })
- ]
- },
-
- renderText ({ node }) {
- return this.options.renderLabel({
- options: this.options,
- node
- })
- },
-
- addKeyboardShortcuts () {
- return {
- Backspace: () =>
- this.editor.commands.command(({ tr, state }) => {
- let isMention = false
- const { selection } = state
- const { empty, anchor } = selection
-
- if (!empty) {
- return false
- }
-
- state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {
- if (node.type.name === this.name) {
- isMention = true
-
- // eslint-disable-next-line
- tr.insertText(this.options.suggestion.char || '', pos, pos + node.nodeSize)
-
- return false
- }
- })
-
- return isMention
- })
- }
- },
-
- addProseMirrorPlugins () {
- return [
- Suggestion({
- editor: this.editor,
- ...this.options.suggestion
- }),
- clickHandler(this.options)
- ]
- }
-})
diff --git a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte
index f58f3936b5..b247fe201d 100644
--- a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte
+++ b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte
@@ -66,7 +66,6 @@
TextEditorHandler
} from '@hcengineering/text-editor'
import { EditorKitOptions, getEditorKit } from '../../src/kits/editor-kit'
- import { Completion } from '../Completion'
import { deleteAttachment } from '../command/deleteAttachment'
import { textEditorCommandHandler } from '../commands'
import { Provider } from '../provider/types'
@@ -84,8 +83,9 @@
import { InlineCommentCollaborationExtension } from './extension/inlineComment'
import { LeftMenuExtension } from './extension/leftMenu'
import { mermaidOptions } from './extension/mermaid'
+ import { ReferenceExtension, referenceConfig } from './extension/reference'
import { type FileAttachFunction } from './extension/types'
- import { completionConfig, inlineCommandsConfig } from './extensions'
+ import { inlineCommandsConfig } from './extensions'
export let object: Doc
export let attribute: KeyedAttribute
@@ -495,8 +495,8 @@
render: renderCursor,
selectionRender: noSelectionRender
}),
- Completion.configure({
- ...completionConfig,
+ ReferenceExtension.configure({
+ ...referenceConfig,
showDoc (event: MouseEvent, _id: string, _class: string) {
dispatch('open-document', { event, _id, _class })
}
diff --git a/plugins/text-editor-resources/src/components/MentionPopup.svelte b/plugins/text-editor-resources/src/components/MentionPopup.svelte
index 6b9632b418..c43b03241d 100644
--- a/plugins/text-editor-resources/src/components/MentionPopup.svelte
+++ b/plugins/text-editor-resources/src/components/MentionPopup.svelte
@@ -15,23 +15,13 @@
-->