From 70a1666a57e56c818169424384e76dc8dafff081 Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Fri, 4 Oct 2024 15:07:02 +0500 Subject: [PATCH] Indexer step 1 (#6798) Signed-off-by: Denis Bykhov --- dev/import-tool/src/notion.ts | 45 +++++------- models/core/src/core.ts | 19 +++++ models/core/src/index.ts | 2 + models/document/src/index.ts | 49 +++++-------- models/document/src/migration.ts | 70 ++++++++++++++++--- packages/core/src/classes.ts | 8 +++ packages/core/src/component.ts | 2 + .../src/components/CreateDocument.svelte | 20 +++--- .../src/components/DocumentEditor.svelte | 6 +- .../src/components/DocumentItem.svelte | 2 +- .../src/components/DocumentPresenter.svelte | 4 +- .../components/DocumentToDoPresenter.svelte | 2 +- .../src/components/EditDoc.svelte | 14 ++-- .../src/components/Move.svelte | 12 ++-- .../NotificationDocumentPresenter.svelte | 2 +- .../components/navigator/DocHierarchy.svelte | 2 +- .../navigator/TeamspaceSpacePresenter.svelte | 8 +-- .../src/components/sidebar/HistoryView.svelte | 2 +- plugins/document-resources/src/index.ts | 2 +- plugins/document-resources/src/utils.ts | 46 ++++++------ plugins/document/src/types.ts | 19 ++--- plugins/document/src/utils.ts | 4 +- .../components/CollaborativeTextEditor.svelte | 10 ++- .../document-resources/src/index.ts | 6 +- 24 files changed, 207 insertions(+), 149 deletions(-) diff --git a/dev/import-tool/src/notion.ts b/dev/import-tool/src/notion.ts index 56500141c0..a634222e6f 100644 --- a/dev/import-tool/src/notion.ts +++ b/dev/import-tool/src/notion.ts @@ -19,7 +19,8 @@ import { makeCollaborativeDoc, type TxOperations, type Blob, - collaborativeDocParse + collaborativeDocParse, + type Data } from '@hcengineering/core' import { yDocToBuffer } from '@hcengineering/collaboration' import document, { type Document, type Teamspace, getFirstRank } from '@hcengineering/document' @@ -325,16 +326,17 @@ async function createDBPageWithAttachments ( documentMetaMap?: Map ): Promise { const pageId = docMeta.id as Ref - const collabId = makeCollaborativeDoc(pageId, 'content') + const collabId = makeCollaborativeDoc(pageId, 'description') const parentId = parentMeta !== undefined ? (parentMeta.id as Ref) : document.ids.NoParent const lastRank = await getFirstRank(client, space, parentId) const rank = makeRank(lastRank, undefined) - const object: AttachedData = { - name: docMeta.name, - content: collabId, + const object: Data = { + title: docMeta.name, + description: collabId, + parent: parentId, attachments: 0, children: 0, embeddings: 0, @@ -344,15 +346,7 @@ async function createDBPageWithAttachments ( rank } - await client.addCollection( - document.class.Document, - space, - parentId, - document.class.Document, - 'children', - object, - pageId - ) + await client.createDoc(document.class.Document, space, object, pageId) const dbPage: DocumentMetadata = { id: pageId, @@ -466,7 +460,7 @@ async function importPageDocument ( } const id = docMeta.id as Ref - const collabId = makeCollaborativeDoc(id, 'content') + const collabId = makeCollaborativeDoc(id, 'description') const yDoc = jsonToYDocNoSchema(json, 'content') const { documentId } = collaborativeDocParse(collabId) const buffer = yDocToBuffer(yDoc) @@ -482,14 +476,15 @@ async function importPageDocument ( await uploadFile(docMeta.id, form) - const parentId = parentMeta?.id ?? document.ids.NoParent + const parent = (parentMeta?.id as Ref) ?? document.ids.NoParent - const lastRank = await getFirstRank(client, space, parentId as Ref) + const lastRank = await getFirstRank(client, space, parent) const rank = makeRank(lastRank, undefined) - const attachedData: AttachedData = { - name: docMeta.name, - content: collabId, + const attachedData: Data = { + title: docMeta.name, + description: collabId, + parent, attachments: 0, children: 0, embeddings: 0, @@ -499,15 +494,7 @@ async function importPageDocument ( rank } - await client.addCollection( - document.class.Document, - space, - parentId as Ref, - document.class.Document, - 'children', - attachedData, - id - ) + await client.createDoc(document.class.Document, space, attachedData, id) } function preProcessMarkdown (json: MarkupNode, documentMetaMap: Map): void { diff --git a/models/core/src/core.ts b/models/core/src/core.ts index 29d4d47dd0..d7bd4af27d 100644 --- a/models/core/src/core.ts +++ b/models/core/src/core.ts @@ -14,6 +14,8 @@ // import { + type Card, + type CollaborativeDoc, DOMAIN_BLOB, DOMAIN_CONFIGURATION, DOMAIN_DOC_INDEX_STATE, @@ -60,6 +62,7 @@ import { Prop, ReadOnly, TypeBoolean, + TypeCollaborativeDoc, TypeFileSize, TypeIntlString, TypeRecord, @@ -111,6 +114,22 @@ export class TDoc extends TObj implements Doc { createdOn!: Timestamp } +@Model(core.class.Card, core.class.Obj) +@UX(core.string.Object) +export class TCard extends TDoc implements Card { + @Prop(TypeString(), core.string.Name) + title!: string + + @Prop(TypeCollaborativeDoc(), core.string.Description) + description!: CollaborativeDoc | null + + @Prop(TypeString(), core.string.Id) + identifier?: string | undefined + + @Prop(TypeRef(core.class.Card), core.string.AttachedTo) + parent?: Ref | null +} + @Model(core.class.AttachedDoc, core.class.Doc) export class TAttachedDoc extends TDoc implements AttachedDoc { @Prop(TypeRef(core.class.Doc), core.string.AttachedTo) diff --git a/models/core/src/index.ts b/models/core/src/index.ts index 09e6a96fb0..b80246b6cf 100644 --- a/models/core/src/index.ts +++ b/models/core/src/index.ts @@ -44,6 +44,7 @@ import { TConfiguration, TConfigurationElement, TDoc, + TCard, TDocIndexState, TDomainIndexConfiguration, TEnum, @@ -160,6 +161,7 @@ export function createModel (builder: Builder): void { TEnum, TTypeAny, TTypeRelatedDocument, + TCard, TDocIndexState, TFullTextSearchContext, TConfiguration, diff --git a/models/document/src/index.ts b/models/document/src/index.ts index ef91dc535d..7f4f857391 100644 --- a/models/document/src/index.ts +++ b/models/document/src/index.ts @@ -15,7 +15,7 @@ import activity from '@hcengineering/activity' import type { Class, CollaborativeDoc, CollectionSize, Domain, Rank, Role, RolesAssignment } from '@hcengineering/core' -import { IndexKind, Account, Ref, AccountRole } from '@hcengineering/core' +import { Account, AccountRole, IndexKind, Ref } from '@hcengineering/core' import { type Document, type DocumentEmbedding, @@ -29,19 +29,19 @@ import { Collection, Hidden, Index, + Mixin, Model, Prop, + TypeCollaborativeDoc, + TypeCollaborativeDocVersion, TypeNumber, TypeRef, TypeString, - UX, - TypeCollaborativeDoc, - TypeCollaborativeDocVersion, - Mixin + UX } from '@hcengineering/model' import attachment, { TAttachment } from '@hcengineering/model-attachment' import chunter from '@hcengineering/model-chunter' -import core, { TAttachedDoc, TTypedSpace } from '@hcengineering/model-core' +import core, { TCard, TTypedSpace } from '@hcengineering/model-core' import { createPublicLinkAction } from '@hcengineering/model-guest' import { generateClassNotificationTypes } from '@hcengineering/model-notification' import preference, { TPreference } from '@hcengineering/model-preference' @@ -50,7 +50,7 @@ import tracker from '@hcengineering/model-tracker' import view, { actionTemplates, createAction } from '@hcengineering/model-view' import workbench from '@hcengineering/model-workbench' import notification from '@hcengineering/notification' -import { getEmbeddedLabel, type Asset } from '@hcengineering/platform' +import { type Asset, getEmbeddedLabel } from '@hcengineering/platform' import tags from '@hcengineering/tags' import time, { type ToDo, type Todoable } from '@hcengineering/time' import document from './plugin' @@ -69,31 +69,23 @@ export class TDocumentEmbedding extends TAttachment implements DocumentEmbedding declare attachedToClass: Ref> } -@Model(document.class.Document, core.class.AttachedDoc, DOMAIN_DOCUMENT) +@Model(document.class.Document, core.class.Card, DOMAIN_DOCUMENT) @UX(document.string.Document, document.icon.Document, undefined, 'name', undefined, document.string.Documents) -export class TDocument extends TAttachedDoc implements Document, Todoable { +export class TDocument extends TCard implements Document, Todoable { @Prop(TypeRef(document.class.Document), document.string.ParentDocument) - declare attachedTo: Ref - - @Prop(TypeRef(core.class.Class), core.string.AttachedToClass) - @Hidden() - declare attachedToClass: Ref> + declare parent: Ref @Prop(TypeRef(core.class.Space), core.string.Space) @Index(IndexKind.Indexed) @Hidden() declare space: Ref - @Prop(TypeString(), core.string.Collection) - @Hidden() - override collection: 'children' = 'children' - @Prop(TypeString(), document.string.Name) @Index(IndexKind.FullText) - name!: string + declare title: string @Prop(TypeCollaborativeDoc(), document.string.Document) - content!: CollaborativeDoc + declare description: CollaborativeDoc @Prop(TypeRef(core.class.Account), document.string.LockedBy) @Hidden() @@ -136,31 +128,24 @@ export class TDocument extends TAttachedDoc implements Document, Todoable { rank!: Rank } -@Model(document.class.DocumentSnapshot, core.class.AttachedDoc, DOMAIN_DOCUMENT) +@Model(document.class.DocumentSnapshot, core.class.Card, DOMAIN_DOCUMENT) @UX(document.string.Version) -export class TDocumentSnapshot extends TAttachedDoc implements DocumentSnapshot { +export class TDocumentSnapshot extends TCard implements DocumentSnapshot { @Prop(TypeRef(document.class.Document), document.string.ParentDocument) - declare attachedTo: Ref - - @Prop(TypeRef(core.class.Class), core.string.AttachedToClass) - declare attachedToClass: Ref> + declare parent: Ref @Prop(TypeRef(core.class.Space), core.string.Space) @Index(IndexKind.Indexed) @Hidden() declare space: Ref - @Prop(TypeString(), core.string.Collection) - @Hidden() - override collection: 'snapshots' = 'snapshots' - @Prop(TypeString(), document.string.Name) @Index(IndexKind.FullText) - name!: string + declare title: string @Prop(TypeCollaborativeDocVersion(), document.string.Document) @Hidden() - content!: CollaborativeDoc + declare description: CollaborativeDoc } @Model(document.class.SavedDocument, preference.class.Preference) diff --git a/models/document/src/migration.ts b/models/document/src/migration.ts index 4686a4db8d..9b96bfd73e 100644 --- a/models/document/src/migration.ts +++ b/models/document/src/migration.ts @@ -14,21 +14,21 @@ // import { DOMAIN_TX, MeasureMetricsContext, SortingOrder } from '@hcengineering/core' -import { type Document, type Teamspace } from '@hcengineering/document' +import { type DocumentSnapshot, type Document, type Teamspace } from '@hcengineering/document' import { + tryMigrate, type MigrateOperation, - type MigrationClient, - type MigrationUpgradeClient, type MigrateUpdate, + type MigrationClient, type MigrationDocumentQuery, - tryMigrate + type MigrationUpgradeClient } from '@hcengineering/model' import core, { DOMAIN_SPACE } from '@hcengineering/model-core' import { type Asset } from '@hcengineering/platform' import { makeRank } from '@hcengineering/rank' -import document, { documentId, DOMAIN_DOCUMENT } from './index' import { loadCollaborativeDoc, saveCollaborativeDoc, yDocCopyXmlField } from '@hcengineering/collaboration' +import document, { documentId, DOMAIN_DOCUMENT } from './index' async function migrateDocumentIcons (client: MigrationClient): Promise { await client.update( @@ -111,9 +111,9 @@ async function migrateContentField (client: MigrationClient): Promise { for (const document of documents) { try { - const ydoc = await loadCollaborativeDoc(storage, client.workspaceId, document.content, ctx) + const ydoc = await loadCollaborativeDoc(storage, client.workspaceId, document.description, ctx) if (ydoc === undefined) { - ctx.error('document content not found', { document: document.name }) + ctx.error('document content not found', { document: document.title }) continue } @@ -123,9 +123,9 @@ async function migrateContentField (client: MigrationClient): Promise { yDocCopyXmlField(ydoc, '', 'content') - await saveCollaborativeDoc(storage, client.workspaceId, document.content, ydoc, ctx) + await saveCollaborativeDoc(storage, client.workspaceId, document.description, ydoc, ctx) } catch (err) { - ctx.error('error document content migration', { error: err, document: document.name }) + ctx.error('error document content migration', { error: err, document: document.title }) } } } @@ -154,6 +154,54 @@ async function migrateRank (client: MigrationClient): Promise { await client.bulk(DOMAIN_DOCUMENT, operations) } +async function renameFields (client: MigrationClient): Promise { + const documents = await client.find(DOMAIN_DOCUMENT, { + _class: document.class.Document, + content: { $exists: true } + }) + + for (const document of documents) { + await client.update( + DOMAIN_DOCUMENT, + { _id: document._id }, + { + $rename: { + attachedTo: 'parent', + content: 'description', + name: 'title' + }, + $unset: { + attachedToClass: '', + collection: '' + } + } + ) + } + + const spnapshots = await client.find(DOMAIN_DOCUMENT, { + _class: document.class.DocumentSnapshot, + content: { $exists: true } + }) + + for (const snapshot of spnapshots) { + await client.update( + DOMAIN_DOCUMENT, + { _id: snapshot._id }, + { + $rename: { + attachedTo: 'parent', + content: 'description', + name: 'title' + }, + $unset: { + attachedToClass: '', + collection: '' + } + } + ) + } +} + export const documentOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { await tryMigrate(client, documentId, [ @@ -176,6 +224,10 @@ export const documentOperation: MigrateOperation = { { state: 'migrateRank', func: migrateRank + }, + { + state: 'renameFields', + func: renameFields } ]) }, diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 00ae9bf50e..a3a92fa609 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -16,6 +16,7 @@ import type { Asset, IntlString, Plugin } from '@hcengineering/platform' import type { DocumentQuery } from './storage' +import { CollaborativeDoc } from './collaboration' /** * @public @@ -73,6 +74,13 @@ export interface Doc extends Obj { createdOn?: Timestamp // Marked as optional since it will be filled by platform. } +export interface Card extends Doc { + title: string + description: CollaborativeDoc | null + identifier?: string + parent?: Ref | null +} + /** * @public */ diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 2b26d1e5a6..08343ec7f3 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -21,6 +21,7 @@ import type { ArrOf, AttachedDoc, Blob, + Card, Class, Collection, Configuration, @@ -82,6 +83,7 @@ export default plugin(coreId, { class: { Obj: '' as Ref>, Doc: '' as Ref>, + Card: '' as Ref>, Blob: '' as Ref>, AttachedDoc: '' as Ref>, Class: '' as Ref>>, diff --git a/plugins/document-resources/src/components/CreateDocument.svelte b/plugins/document-resources/src/components/CreateDocument.svelte index e0f3780ea9..552d3e71e1 100644 --- a/plugins/document-resources/src/components/CreateDocument.svelte +++ b/plugins/document-resources/src/components/CreateDocument.svelte @@ -15,9 +15,10 @@ // --> - {value.name} + {value.title} diff --git a/plugins/document-resources/src/components/DocumentPresenter.svelte b/plugins/document-resources/src/components/DocumentPresenter.svelte index ed246977fa..4b7b26684e 100644 --- a/plugins/document-resources/src/components/DocumentPresenter.svelte +++ b/plugins/document-resources/src/components/DocumentPresenter.svelte @@ -52,13 +52,13 @@ {/if} - {value.name} + {value.title} {:else if type === 'text'} - {value.name} + {value.title} {/if} {/if} diff --git a/plugins/document-resources/src/components/DocumentToDoPresenter.svelte b/plugins/document-resources/src/components/DocumentToDoPresenter.svelte index d8b3d9e215..c854e50b34 100644 --- a/plugins/document-resources/src/components/DocumentToDoPresenter.svelte +++ b/plugins/document-resources/src/components/DocumentToDoPresenter.svelte @@ -27,5 +27,5 @@
- {value.name} + {value.title} diff --git a/plugins/document-resources/src/components/EditDoc.svelte b/plugins/document-resources/src/components/EditDoc.svelte index bfdba3345b..aa646d95ec 100644 --- a/plugins/document-resources/src/components/EditDoc.svelte +++ b/plugins/document-resources/src/components/EditDoc.svelte @@ -80,7 +80,7 @@ const client = getClient() let doc: WithLookup | undefined - let name = '' + let title = '' let innerWidth: number let headings: Heading[] = [] @@ -141,10 +141,10 @@ $: _id !== undefined && query.query(document.class.Document, { _id }, async (result) => { ;[doc] = result - name = doc?.name ?? '' + title = doc?.title ?? '' }) - $: canSave = name.trim().length > 0 + $: canSave = title.trim().length > 0 async function saveTitle (ev: Event): Promise { ev.preventDefault() @@ -153,10 +153,10 @@ return } - const nameTrimmed = name.trim() + const nameTrimmed = title.trim() - if (nameTrimmed.length > 0 && nameTrimmed !== doc.name) { - await client.update(doc, { name: nameTrimmed }) + if (nameTrimmed.length > 0 && nameTrimmed !== doc.title) { + await client.update(doc, { title: nameTrimmed }) } } @@ -322,7 +322,7 @@ saveTitle(evt)} diff --git a/plugins/document-resources/src/components/Move.svelte b/plugins/document-resources/src/components/Move.svelte index e9003d2638..e0ea7a5f8c 100644 --- a/plugins/document-resources/src/components/Move.svelte +++ b/plugins/document-resources/src/components/Move.svelte @@ -29,7 +29,7 @@ const dispatch = createEventDispatcher() let space: Ref = value.space - let parent: Ref = value.attachedTo + let parent: Ref = value.parent let children: Ref[] = [] $: void updateChildren(value) @@ -58,15 +58,15 @@ async function findChildren (doc: Document): Promise>> { const documents = await client.findAll( document.class.Document, - { space: doc.space, attachedTo: { $ne: document.ids.NoParent } }, - { projection: { _id: 1, attachedTo: 1 } } + { space: doc.space, parent: { $ne: document.ids.NoParent } }, + { projection: { _id: 1, parent: 1 } } ) const byParent = new Map, Array>>() for (const document of documents) { - const group = byParent.get(document.attachedTo) ?? [] + const group = byParent.get(document.parent) ?? [] group.push(document._id) - byParent.set(document.attachedTo, group) + byParent.set(document.parent, group) } const result: Ref[] = [] @@ -83,7 +83,7 @@ return result } - $: canSave = space !== value.space || parent !== value.attachedTo + $: canSave = space !== value.space || parent !== value.parent - {value.name} + {value.title} {/if} diff --git a/plugins/document-resources/src/components/navigator/DocHierarchy.svelte b/plugins/document-resources/src/components/navigator/DocHierarchy.svelte index 5ff2c88c4b..0fec9f16f6 100644 --- a/plugins/document-resources/src/components/navigator/DocHierarchy.svelte +++ b/plugins/document-resources/src/components/navigator/DocHierarchy.svelte @@ -109,7 +109,7 @@ : { fill: doc.color !== undefined ? getPlatformColorDef(doc.color, $themeStore.dark).icon : 'currentColor' }} - title={doc.name} + title={doc.title} selected={selected === doc._id && draggedItem === undefined} isFold {level} diff --git a/plugins/document-resources/src/components/navigator/TeamspaceSpacePresenter.svelte b/plugins/document-resources/src/components/navigator/TeamspaceSpacePresenter.svelte index a887faf0e2..be3ab44026 100644 --- a/plugins/document-resources/src/components/navigator/TeamspaceSpacePresenter.svelte +++ b/plugins/document-resources/src/components/navigator/TeamspaceSpacePresenter.svelte @@ -99,9 +99,9 @@ descendants.clear() for (const doc of result) { - const current = descendants.get(doc.attachedTo) ?? [] + const current = descendants.get(doc.parent) ?? [] current.push(doc) - descendants.set(doc.attachedTo, current) + descendants.set(doc.parent, current) documentById.set(doc._id, doc) } @@ -243,7 +243,7 @@ void moveDocumentBefore(doc, target) } else if (pos === 'after') { void moveDocumentAfter(doc, target) - } else if (doc.attachedTo !== object) { + } else if (doc.parent !== object) { void moveDocument(doc, target.space, target._id) } } @@ -315,7 +315,7 @@ : { fill: item.color !== undefined ? getPlatformColorDef(item.color, $themeStore.dark).icon : 'currentColor' }} - title={item.name} + title={item.title} selected isFold empty diff --git a/plugins/document-resources/src/components/sidebar/HistoryView.svelte b/plugins/document-resources/src/components/sidebar/HistoryView.svelte index e0a7bc8163..a02a2262e4 100644 --- a/plugins/document-resources/src/components/sidebar/HistoryView.svelte +++ b/plugins/document-resources/src/components/sidebar/HistoryView.svelte @@ -30,7 +30,7 @@
- {value.name} + {value.title}
diff --git a/plugins/document-resources/src/index.ts b/plugins/document-resources/src/index.ts index bdf821935e..00e7d33ba5 100644 --- a/plugins/document-resources/src/index.ts +++ b/plugins/document-resources/src/index.ts @@ -57,7 +57,7 @@ import { const toObjectSearchResult = (e: WithLookup): ObjectSearchResult => ({ doc: e, - title: e.name, + title: e.title, icon: document.icon.Document, component: DocumentItem }) diff --git a/plugins/document-resources/src/utils.ts b/plugins/document-resources/src/utils.ts index 4cd548594b..d695ff4cea 100644 --- a/plugins/document-resources/src/utils.ts +++ b/plugins/document-resources/src/utils.ts @@ -14,8 +14,8 @@ // import { - type AttachedData, type Client, + type Data, type QuerySelector, type Ref, SortingOrder, @@ -26,7 +26,7 @@ import { type Document, type Teamspace, documentId, getFirstRank } from '@hcengi import { getMetadata, translate } from '@hcengineering/platform' import presentation, { getClient } from '@hcengineering/presentation' import { makeRank } from '@hcengineering/rank' -import { getCurrentResolvedLocation, getPanelURI, type Location, type ResolvedLocation } from '@hcengineering/ui' +import { type Location, type ResolvedLocation, getCurrentResolvedLocation, getPanelURI } from '@hcengineering/ui' import { accessDeniedStore } from '@hcengineering/view-resources' import { workbenchId } from '@hcengineering/workbench' import slugify from 'slugify' @@ -39,46 +39,47 @@ export async function moveDocument (doc: Document, space: Ref, parent const prevRank = await getFirstRank(client, space, parent) const rank = makeRank(prevRank, undefined) - await client.update(doc, { space, attachedTo: parent, rank }) + await client.update(doc, { space, parent, rank }) } export async function moveDocumentBefore (doc: Document, before: Document): Promise { const client = getClient() - const { space, attachedTo } = before + const { space, parent } = before const query = { rank: { $lt: before.rank } as unknown as QuerySelector } - const lastRank = await getFirstRank(client, space, attachedTo, SortingOrder.Descending, query) + const lastRank = await getFirstRank(client, space, parent, SortingOrder.Descending, query) const rank = makeRank(lastRank, before.rank) - await client.update(doc, { space, attachedTo, rank }) + await client.update(doc, { space, parent, rank }) } export async function moveDocumentAfter (doc: Document, after: Document): Promise { const client = getClient() - const { space, attachedTo } = after + const { space, parent } = after const query = { rank: { $gt: after.rank } as unknown as QuerySelector } - const nextRank = await getFirstRank(client, space, attachedTo, SortingOrder.Ascending, query) + const nextRank = await getFirstRank(client, space, parent, SortingOrder.Ascending, query) const rank = makeRank(after.rank, nextRank) - await client.update(doc, { space, attachedTo, rank }) + await client.update(doc, { space, parent, rank }) } export async function createEmptyDocument ( client: TxOperations, id: Ref, space: Ref, - parent: Ref, - data: Partial, 'name' | 'icon' | 'color'>> = {} + parentId?: Ref, + data: Partial, 'title' | 'icon' | 'color'>> = {} ): Promise { - const name = await translate(document.string.Untitled, {}) + const title = await translate(document.string.Untitled, {}) + const parent = parentId ?? document.ids.NoParent const lastRank = await getFirstRank(client, space, parent) const rank = makeRank(lastRank, undefined) - const object: AttachedData = { - name, - content: makeCollaborativeDoc(id, 'content'), + const object: Data = { + title, + description: makeCollaborativeDoc(id, 'description'), attachments: 0, children: 0, embeddings: 0, @@ -86,18 +87,11 @@ export async function createEmptyDocument ( comments: 0, references: 0, rank, + parent: parent ?? document.ids.NoParent, ...data } - await client.addCollection( - document.class.Document, - space, - parent ?? document.ids.NoParent, - document.class.Document, - 'children', - object, - id - ) + await client.createDoc(document.class.Document, space, object, id) } export async function resolveLocation (loc: Location): Promise { @@ -171,7 +165,7 @@ export function getDocumentLink (doc: Document): Location { } export function getDocumentLinkId (doc: Document): string { - const slug = slugify(doc.name, { lower: true }) + const slug = slugify(doc.title, { lower: true }) return `${slug}-${doc._id}` } @@ -188,5 +182,5 @@ export function parseDocumentId (shortLink?: string): Ref | undefined export async function documentTitleProvider (client: Client, ref: Ref, doc?: Document): Promise { const object = doc ?? (await client.findOne(document.class.Document, { _id: ref })) - return object?.name ?? '' + return object?.title ?? '' } diff --git a/plugins/document/src/types.ts b/plugins/document/src/types.ts index 16a1d5bbe0..7c3c05590c 100644 --- a/plugins/document/src/types.ts +++ b/plugins/document/src/types.ts @@ -14,7 +14,7 @@ // import { Attachment } from '@hcengineering/attachment' -import { Account, AttachedDoc, Class, CollaborativeDoc, Rank, Ref, TypedSpace } from '@hcengineering/core' +import { Account, Card, Class, CollaborativeDoc, Rank, Ref, TypedSpace } from '@hcengineering/core' import { Preference } from '@hcengineering/preference' import { IconProps } from '@hcengineering/view' @@ -22,11 +22,12 @@ import { IconProps } from '@hcengineering/view' export interface Teamspace extends TypedSpace, IconProps {} /** @public */ -export interface Document extends AttachedDoc, IconProps { - attachedTo: Ref +export interface Document extends Card, IconProps { + parent: Ref - name: string - content: CollaborativeDoc + description: CollaborativeDoc + + space: Ref lockedBy?: Ref | null @@ -42,10 +43,10 @@ export interface Document extends AttachedDoc, } /** @public */ -export interface DocumentSnapshot extends AttachedDoc { - attachedTo: Ref - name: string - content: CollaborativeDoc +export interface DocumentSnapshot extends Card { + parent: Ref + title: string + description: CollaborativeDoc } /** @public */ diff --git a/plugins/document/src/utils.ts b/plugins/document/src/utils.ts index 6a6cb701aa..64162395b9 100644 --- a/plugins/document/src/utils.ts +++ b/plugins/document/src/utils.ts @@ -21,13 +21,13 @@ import { type Document, type Teamspace } from './types' export async function getFirstRank ( client: TxOperations, space: Ref, - attachedTo: Ref, + parent: Ref, sort: SortingOrder = SortingOrder.Descending, extra: DocumentQuery = {} ): Promise { const doc = await client.findOne( document.class.Document, - { space, attachedTo, ...extra }, + { space, parent, ...extra }, { sort: { rank: sort }, projection: { rank: 1 } } ) diff --git a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte index 0b1982db3a..7f551e54e2 100644 --- a/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte +++ b/plugins/text-editor-resources/src/components/CollaborativeTextEditor.svelte @@ -365,7 +365,15 @@ remoteProvider.awareness?.setLocalStateField('lastUpdate', Date.now()) } + function parseField (collaborativeDoc: CollaborativeDoc): string | undefined { + if (collaborativeDoc === undefined) return undefined + const _id = collaborativeDoc.split(':') + if (_id === undefined) return undefined + return _id[0]?.split('%')?.[1] + } + onMount(async () => { + const _field = parseField(collaborativeDoc) ?? field await ph editor = new Editor({ @@ -398,7 +406,7 @@ Placeholder.configure({ placeholder: placeHolderStr }), Collaboration.configure({ document: ydoc, - field + field: _field }), CollaborationCursor.configure({ provider: remoteProvider, diff --git a/server-plugins/document-resources/src/index.ts b/server-plugins/document-resources/src/index.ts index 80fb1d7807..14a1941020 100644 --- a/server-plugins/document-resources/src/index.ts +++ b/server-plugins/document-resources/src/index.ts @@ -11,7 +11,7 @@ import serverCore, { TriggerControl } from '@hcengineering/server-core' import slugify from 'slugify' function getDocumentId (doc: Document): string { - const slug = slugify(doc.name, { lower: true }) + const slug = slugify(doc.title, { lower: true }) return `${slug}-${doc._id}` } @@ -23,7 +23,7 @@ export async function documentHTMLPresenter (doc: Doc, control: TriggerControl): const front = control.branding?.front ?? getMetadata(serverCore.metadata.FrontUrl) ?? '' const path = `${workbenchId}/${control.workspace.workspaceUrl}/${documentId}/${getDocumentId(document)}` const link = concatLink(front, path) - return `${document.name}` + return `${document.title}` } export async function documentLinkIdProvider (doc: Document): Promise { @@ -35,7 +35,7 @@ export async function documentLinkIdProvider (doc: Document): Promise { */ export async function documentTextPresenter (doc: Doc): Promise { const document = doc as Document - return document.name + return document.title } // eslint-disable-next-line @typescript-eslint/explicit-function-return-type