fix: revert document content field rename (#6955)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov 2024-10-16 22:52:46 +07:00 committed by GitHub
parent d1bf10b1d9
commit dea31012b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 136 additions and 53 deletions

View File

@ -326,7 +326,7 @@ async function createDBPageWithAttachments (
documentMetaMap?: Map<string, DocumentMetadata> documentMetaMap?: Map<string, DocumentMetadata>
): Promise<void> { ): Promise<void> {
const pageId = docMeta.id as Ref<Document> const pageId = docMeta.id as Ref<Document>
const collabId = makeCollaborativeDoc(pageId, 'description') const collabId = makeCollaborativeDoc(pageId, 'content')
const parentId = parentMeta !== undefined ? (parentMeta.id as Ref<Document>) : document.ids.NoParent const parentId = parentMeta !== undefined ? (parentMeta.id as Ref<Document>) : document.ids.NoParent
@ -335,7 +335,7 @@ async function createDBPageWithAttachments (
const object: Data<Document> = { const object: Data<Document> = {
title: docMeta.name, title: docMeta.name,
description: collabId, content: collabId,
parent: parentId, parent: parentId,
attachments: 0, attachments: 0,
embeddings: 0, embeddings: 0,
@ -482,7 +482,7 @@ async function importPageDocument (
const attachedData: Data<Document> = { const attachedData: Data<Document> = {
title: docMeta.name, title: docMeta.name,
description: collabId, content: collabId,
parent, parent,
attachments: 0, attachments: 0,
embeddings: 0, embeddings: 0,

View File

@ -41,7 +41,7 @@ import {
} from '@hcengineering/model' } from '@hcengineering/model'
import attachment, { TAttachment } from '@hcengineering/model-attachment' import attachment, { TAttachment } from '@hcengineering/model-attachment'
import chunter from '@hcengineering/model-chunter' import chunter from '@hcengineering/model-chunter'
import core, { TCard, TTypedSpace } from '@hcengineering/model-core' import core, { TDoc, TTypedSpace } from '@hcengineering/model-core'
import { createPublicLinkAction } from '@hcengineering/model-guest' import { createPublicLinkAction } from '@hcengineering/model-guest'
import { generateClassNotificationTypes } from '@hcengineering/model-notification' import { generateClassNotificationTypes } from '@hcengineering/model-notification'
import preference, { TPreference } from '@hcengineering/model-preference' import preference, { TPreference } from '@hcengineering/model-preference'
@ -69,24 +69,24 @@ export class TDocumentEmbedding extends TAttachment implements DocumentEmbedding
declare attachedToClass: Ref<Class<Document>> declare attachedToClass: Ref<Class<Document>>
} }
@Model(document.class.Document, core.class.Card, DOMAIN_DOCUMENT) @Model(document.class.Document, core.class.Doc, DOMAIN_DOCUMENT)
@UX(document.string.Document, document.icon.Document, undefined, 'name', undefined, document.string.Documents) @UX(document.string.Document, document.icon.Document, undefined, 'name', undefined, document.string.Documents)
export class TDocument extends TCard implements Document, Todoable { export class TDocument extends TDoc implements Document, Todoable {
@Prop(TypeString(), document.string.Name)
@Index(IndexKind.FullText)
title!: string
@Prop(TypeCollaborativeDoc(), document.string.Document)
content!: CollaborativeDoc
@Prop(TypeRef(document.class.Document), document.string.ParentDocument) @Prop(TypeRef(document.class.Document), document.string.ParentDocument)
declare parent: Ref<Document> parent!: Ref<Document>
@Prop(TypeRef(core.class.Space), core.string.Space) @Prop(TypeRef(core.class.Space), core.string.Space)
@Index(IndexKind.Indexed) @Index(IndexKind.Indexed)
@Hidden() @Hidden()
declare space: Ref<Teamspace> declare space: Ref<Teamspace>
@Prop(TypeString(), document.string.Name)
@Index(IndexKind.FullText)
declare title: string
@Prop(TypeCollaborativeDoc(), document.string.Document)
declare description: CollaborativeDoc
@Prop(TypeRef(core.class.Account), document.string.LockedBy) @Prop(TypeRef(core.class.Account), document.string.LockedBy)
@Hidden() @Hidden()
lockedBy?: Ref<Account> lockedBy?: Ref<Account>
@ -125,12 +125,9 @@ export class TDocument extends TCard implements Document, Todoable {
rank!: Rank rank!: Rank
} }
@Model(document.class.DocumentSnapshot, core.class.Card, DOMAIN_DOCUMENT) @Model(document.class.DocumentSnapshot, core.class.Doc, DOMAIN_DOCUMENT)
@UX(document.string.Version) @UX(document.string.Version)
export class TDocumentSnapshot extends TCard implements DocumentSnapshot { export class TDocumentSnapshot extends TDoc implements DocumentSnapshot {
@Prop(TypeRef(document.class.Document), document.string.ParentDocument)
declare parent: Ref<Document>
@Prop(TypeRef(core.class.Space), core.string.Space) @Prop(TypeRef(core.class.Space), core.string.Space)
@Index(IndexKind.Indexed) @Index(IndexKind.Indexed)
@Hidden() @Hidden()
@ -138,11 +135,13 @@ export class TDocumentSnapshot extends TCard implements DocumentSnapshot {
@Prop(TypeString(), document.string.Name) @Prop(TypeString(), document.string.Name)
@Index(IndexKind.FullText) @Index(IndexKind.FullText)
declare title: string title!: string
@Prop(TypeCollaborativeDocVersion(), document.string.Document) @Prop(TypeCollaborativeDocVersion(), document.string.Document)
@Hidden() content!: CollaborativeDoc
declare description: CollaborativeDoc
@Prop(TypeRef(document.class.Document), document.string.ParentDocument)
parent!: Ref<Document>
} }
@Model(document.class.SavedDocument, preference.class.Preference) @Model(document.class.SavedDocument, preference.class.Preference)
@ -444,7 +443,7 @@ function defineDocument (builder: Builder): void {
allowedForAuthor: false, allowedForAuthor: false,
label: document.string.Document, label: document.string.Document,
group: document.ids.DocumentNotificationGroup, group: document.ids.DocumentNotificationGroup,
field: 'description', field: 'content',
txClasses: [core.class.TxUpdateDoc], txClasses: [core.class.TxUpdateDoc],
objectClass: document.class.Document, objectClass: document.class.Document,
defaultEnabled: false, defaultEnabled: false,

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
// //
import { DOMAIN_TX, MeasureMetricsContext, SortingOrder } from '@hcengineering/core' import { type CollaborativeDoc, DOMAIN_TX, MeasureMetricsContext, SortingOrder } from '@hcengineering/core'
import { type DocumentSnapshot, type Document, type Teamspace } from '@hcengineering/document' import { type DocumentSnapshot, type Document, type Teamspace } from '@hcengineering/document'
import { import {
tryMigrate, tryMigrate,
@ -111,7 +111,7 @@ async function migrateContentField (client: MigrationClient): Promise<void> {
for (const document of documents) { for (const document of documents) {
try { try {
const ydoc = await loadCollaborativeDoc(storage, client.workspaceId, document.description, ctx) const ydoc = await loadCollaborativeDoc(storage, client.workspaceId, document.content, ctx)
if (ydoc === undefined) { if (ydoc === undefined) {
ctx.error('document content not found', { document: document.title }) ctx.error('document content not found', { document: document.title })
continue continue
@ -123,7 +123,7 @@ async function migrateContentField (client: MigrationClient): Promise<void> {
yDocCopyXmlField(ydoc, '', 'content') yDocCopyXmlField(ydoc, '', 'content')
await saveCollaborativeDoc(storage, client.workspaceId, document.description, ydoc, ctx) await saveCollaborativeDoc(storage, client.workspaceId, document.content, ydoc, ctx)
} catch (err) { } catch (err) {
ctx.error('error document content migration', { error: err, document: document.title }) ctx.error('error document content migration', { error: err, document: document.title })
} }
@ -202,6 +202,68 @@ async function renameFields (client: MigrationClient): Promise<void> {
} }
} }
async function renameFieldsRevert (client: MigrationClient): Promise<void> {
const ctx = new MeasureMetricsContext('renameFieldsRevert', {})
const storage = client.storageAdapter
type ExDocument = Document & {
description: CollaborativeDoc
}
const documents = await client.find<ExDocument>(DOMAIN_DOCUMENT, {
_class: document.class.Document,
description: { $exists: true }
})
for (const document of documents) {
await client.update(
DOMAIN_DOCUMENT,
{ _id: document._id },
{
$rename: {
description: 'content'
}
}
)
if (document.description.includes('%description:')) {
try {
const ydoc = await loadCollaborativeDoc(storage, client.workspaceId, document.description, ctx)
if (ydoc === undefined) {
continue
}
if (!ydoc.share.has('description') || ydoc.share.has('content')) {
continue
}
yDocCopyXmlField(ydoc, 'description', 'content')
await saveCollaborativeDoc(storage, client.workspaceId, document.description, ydoc, ctx)
} catch (err) {
ctx.error('error document content migration', { error: err, document: document.title })
}
}
}
const snapshots = await client.find<DocumentSnapshot>(DOMAIN_DOCUMENT, {
_class: document.class.DocumentSnapshot,
description: { $exists: true }
})
for (const snapshot of snapshots) {
await client.update(
DOMAIN_DOCUMENT,
{ _id: snapshot._id },
{
$rename: {
description: 'content'
}
}
)
}
}
export const documentOperation: MigrateOperation = { export const documentOperation: MigrateOperation = {
async migrate (client: MigrationClient): Promise<void> { async migrate (client: MigrationClient): Promise<void> {
await tryMigrate(client, documentId, [ await tryMigrate(client, documentId, [
@ -234,6 +296,10 @@ export const documentOperation: MigrateOperation = {
func: async (client: MigrationClient): Promise<void> => { func: async (client: MigrationClient): Promise<void> => {
await client.update(DOMAIN_DOCUMENT, { '%hash%': { $exists: true } }, { $set: { '%hash%': null } }) await client.update(DOMAIN_DOCUMENT, { '%hash%': { $exists: true } }, { $set: { '%hash%': null } })
} }
},
{
state: 'renameFieldsRevert',
func: renameFieldsRevert
} }
]) ])
}, },

View File

@ -5,9 +5,9 @@
import { type Builder } from '@hcengineering/model' import { type Builder } from '@hcengineering/model'
import core from '@hcengineering/core' import core, { type Class, type Doc } from '@hcengineering/core'
import document from '@hcengineering/document' import document from '@hcengineering/document'
import serverCore from '@hcengineering/server-core' import serverCore, { type ObjectDDParticipant } from '@hcengineering/server-core'
import serverDocument from '@hcengineering/server-document' import serverDocument from '@hcengineering/server-document'
import serverNotification from '@hcengineering/server-notification' import serverNotification from '@hcengineering/server-notification'
import serverView from '@hcengineering/server-view' import serverView from '@hcengineering/server-view'
@ -36,4 +36,13 @@ export function createModel (builder: Builder): void {
title: 'title' title: 'title'
} }
}) })
builder.mixin<Class<Doc>, ObjectDDParticipant>(
document.class.Document,
core.class.Class,
serverCore.mixin.ObjectDDParticipant,
{
collectDocs: serverDocument.function.FindChildDocuments
}
)
} }

View File

@ -56,12 +56,12 @@
</script> </script>
<CollaboratorEditor <CollaboratorEditor
collaborativeDoc={object.description} collaborativeDoc={object.content}
objectClass={object._class} objectClass={object._class}
objectId={object._id} objectId={object._id}
objectSpace={object.space} objectSpace={object.space}
objectAttr="description" objectAttr="content"
field="description" field="content"
{user} {user}
{userComponent} {userComponent}
{focusIndex} {focusIndex}

View File

@ -79,7 +79,7 @@ export async function createEmptyDocument (
const object: Data<Document> = { const object: Data<Document> = {
title, title,
description: makeCollaborativeDoc(id, 'description'), content: makeCollaborativeDoc(id, 'content'),
attachments: 0, attachments: 0,
embeddings: 0, embeddings: 0,
labels: 0, labels: 0,

View File

@ -14,7 +14,7 @@
// //
import { Attachment } from '@hcengineering/attachment' import { Attachment } from '@hcengineering/attachment'
import { Account, Card, Class, CollaborativeDoc, Rank, Ref, TypedSpace } from '@hcengineering/core' import { Account, Class, CollaborativeDoc, Doc, Rank, Ref, TypedSpace } from '@hcengineering/core'
import { Preference } from '@hcengineering/preference' import { Preference } from '@hcengineering/preference'
import { IconProps } from '@hcengineering/view' import { IconProps } from '@hcengineering/view'
@ -22,11 +22,10 @@ import { IconProps } from '@hcengineering/view'
export interface Teamspace extends TypedSpace, IconProps {} export interface Teamspace extends TypedSpace, IconProps {}
/** @public */ /** @public */
export interface Document extends Card, IconProps { export interface Document extends Doc, IconProps {
title: string
content: CollaborativeDoc
parent: Ref<Document> parent: Ref<Document>
description: CollaborativeDoc
space: Ref<Teamspace> space: Ref<Teamspace>
lockedBy?: Ref<Account> | null lockedBy?: Ref<Account> | null
@ -42,10 +41,10 @@ export interface Document extends Card, IconProps {
} }
/** @public */ /** @public */
export interface DocumentSnapshot extends Card { export interface DocumentSnapshot extends Doc {
parent: Ref<Document>
title: string title: string
description: CollaborativeDoc content: CollaborativeDoc
parent: Ref<Document>
} }
/** @public */ /** @public */

View File

@ -365,15 +365,7 @@
remoteProvider.awareness?.setLocalStateField('lastUpdate', Date.now()) 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 () => { onMount(async () => {
const _field = parseField(collaborativeDoc) ?? field
await ph await ph
editor = new Editor({ editor = new Editor({
@ -406,7 +398,7 @@
Placeholder.configure({ placeholder: placeHolderStr }), Placeholder.configure({ placeholder: placeHolderStr }),
Collaboration.configure({ Collaboration.configure({
document: ydoc, document: ydoc,
field: _field field
}), }),
CollaborationCursor.configure({ CollaborationCursor.configure({
provider: remoteProvider, provider: remoteProvider,

View File

@ -3,8 +3,8 @@
// //
// //
import { Doc, concatLink } from '@hcengineering/core' import { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref, concatLink } from '@hcengineering/core'
import { Document, documentId } from '@hcengineering/document' import document, { Document, documentId } from '@hcengineering/document'
import { getMetadata } from '@hcengineering/platform' import { getMetadata } from '@hcengineering/platform'
import { workbenchId } from '@hcengineering/workbench' import { workbenchId } from '@hcengineering/workbench'
import serverCore, { TriggerControl } from '@hcengineering/server-core' import serverCore, { TriggerControl } from '@hcengineering/server-core'
@ -38,11 +38,27 @@ export async function documentTextPresenter (doc: Doc): Promise<string> {
return document.title return document.title
} }
/**
* @public
*/
export async function findChildDocuments (
doc: Doc,
hiearachy: Hierarchy,
findAll: <T extends Doc>(
clazz: Ref<Class<T>>,
query: DocumentQuery<T>,
options?: FindOptions<T>
) => Promise<FindResult<T>>
): Promise<Doc[]> {
return await findAll(document.class.Document, { parent: doc._id as Ref<Document> })
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async () => ({ export default async () => ({
function: { function: {
DocumentHTMLPresenter: documentHTMLPresenter, DocumentHTMLPresenter: documentHTMLPresenter,
DocumentTextPresenter: documentTextPresenter, DocumentTextPresenter: documentTextPresenter,
DocumentLinkIdProvider: documentLinkIdProvider DocumentLinkIdProvider: documentLinkIdProvider,
FindChildDocuments: findChildDocuments
} }
}) })

View File

@ -6,6 +6,7 @@
import { Doc } from '@hcengineering/core' import { Doc } from '@hcengineering/core'
import type { Plugin, Resource } from '@hcengineering/platform' import type { Plugin, Resource } from '@hcengineering/platform'
import { plugin } from '@hcengineering/platform' import { plugin } from '@hcengineering/platform'
import { ObjectDDParticipantFunc } from '@hcengineering/server-core'
import { Presenter } from '@hcengineering/server-notification' import { Presenter } from '@hcengineering/server-notification'
/** /**
@ -20,6 +21,7 @@ export default plugin(serverDocumentId, {
function: { function: {
DocumentHTMLPresenter: '' as Resource<Presenter>, DocumentHTMLPresenter: '' as Resource<Presenter>,
DocumentTextPresenter: '' as Resource<Presenter>, DocumentTextPresenter: '' as Resource<Presenter>,
DocumentLinkIdProvider: '' as Resource<(doc: Doc) => Promise<string>> DocumentLinkIdProvider: '' as Resource<(doc: Doc) => Promise<string>>,
FindChildDocuments: '' as Resource<ObjectDDParticipantFunc>
} }
}) })