mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-22 08:20:39 +00:00
UBERF-8499: Use our generateId for ydocs (#6958)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
e6d9b8f606
commit
51679bf82c
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { Markup } from '@hcengineering/core'
|
import { generateId, Markup } from '@hcengineering/core'
|
||||||
import { Extensions, getSchema } from '@tiptap/core'
|
import { Extensions, getSchema } from '@tiptap/core'
|
||||||
import { Node, Schema } from '@tiptap/pm/model'
|
import { Node, Schema } from '@tiptap/pm/model'
|
||||||
import { prosemirrorJSONToYDoc, prosemirrorToYDoc, yDocToProsemirrorJSON } from 'y-prosemirror'
|
import { prosemirrorJSONToYDoc, prosemirrorToYDoc, yDocToProsemirrorJSON } from 'y-prosemirror'
|
||||||
@ -50,7 +50,7 @@ export function jsonToYDocNoSchema (json: MarkupNode, field: string): YDoc {
|
|||||||
const nodes = json.type === 'doc' ? json.content ?? [] : [json]
|
const nodes = json.type === 'doc' ? json.content ?? [] : [json]
|
||||||
const content = nodes.map(nodeToYXmlElement)
|
const content = nodes.map(nodeToYXmlElement)
|
||||||
|
|
||||||
const ydoc = new YDoc()
|
const ydoc = new YDoc({ guid: generateId() })
|
||||||
|
|
||||||
const fragment = ydoc.getXmlFragment(field)
|
const fragment = ydoc.getXmlFragment(field)
|
||||||
fragment.push(content)
|
fragment.push(content)
|
||||||
@ -113,7 +113,10 @@ export function yDocContentToNodes (content: ArrayBuffer, schema?: Schema, exten
|
|||||||
const nodes: Node[] = []
|
const nodes: Node[] = []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ydoc = new YDoc()
|
const ydoc = new YDoc({
|
||||||
|
gc: false,
|
||||||
|
guid: generateId()
|
||||||
|
})
|
||||||
const uint8arr = new Uint8Array(content)
|
const uint8arr = new Uint8Array(content)
|
||||||
applyUpdate(ydoc, uint8arr)
|
applyUpdate(ydoc, uint8arr)
|
||||||
|
|
||||||
@ -144,8 +147,8 @@ export function updateYDocContent (
|
|||||||
schema ??= extensions === undefined ? defaultSchema : getSchema(extensions ?? defaultExtensions)
|
schema ??= extensions === undefined ? defaultSchema : getSchema(extensions ?? defaultExtensions)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ydoc = new YDoc({ gc: false })
|
const ydoc = new YDoc({ guid: generateId(), gc: false })
|
||||||
const res = new YDoc({ gc: false })
|
const res = new YDoc({ guid: generateId(), gc: false })
|
||||||
const uint8arr = new Uint8Array(content)
|
const uint8arr = new Uint8Array(content)
|
||||||
applyUpdate(ydoc, uint8arr)
|
applyUpdate(ydoc, uint8arr)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Analytics } from '@hcengineering/analytics'
|
import { Analytics } from '@hcengineering/analytics'
|
||||||
import { type Space, type Class, type CollaborativeDoc, type Doc, type Ref } from '@hcengineering/core'
|
import { type Space, type Class, type CollaborativeDoc, type Doc, type Ref, generateId } from '@hcengineering/core'
|
||||||
import { IntlString, translate } from '@hcengineering/platform'
|
import { IntlString, translate } from '@hcengineering/platform'
|
||||||
import { getFileUrl, getImageSize, imageSizeToRatio } from '@hcengineering/presentation'
|
import { getFileUrl, getImageSize, imageSizeToRatio } from '@hcengineering/presentation'
|
||||||
import { markupToJSON } from '@hcengineering/text'
|
import { markupToJSON } from '@hcengineering/text'
|
||||||
@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
const ydoc = getContext<YDoc>(CollaborationIds.Doc) ?? new YDoc()
|
const ydoc = getContext<YDoc>(CollaborationIds.Doc) ?? new YDoc({ guid: generateId() })
|
||||||
const contextProvider = getContext<Provider>(CollaborationIds.Provider)
|
const contextProvider = getContext<Provider>(CollaborationIds.Provider)
|
||||||
|
|
||||||
const localProvider = createLocalProvider(ydoc, collaborativeDoc)
|
const localProvider = createLocalProvider(ydoc, collaborativeDoc)
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { type Ref, type CollaborativeDoc, type Doc, type Class } from '@hcengineering/core'
|
import { type Ref, type CollaborativeDoc, type Doc, type Class, generateId } from '@hcengineering/core'
|
||||||
import {
|
import {
|
||||||
type DocumentId,
|
type DocumentId,
|
||||||
type PlatformDocumentId,
|
type PlatformDocumentId,
|
||||||
@ -99,7 +99,7 @@ export const createTiptapCollaborationData = (params: {
|
|||||||
objectId?: Ref<Doc>
|
objectId?: Ref<Doc>
|
||||||
objectAttr?: string
|
objectAttr?: string
|
||||||
}): { provider: Provider, ydoc: Ydoc } => {
|
}): { provider: Provider, ydoc: Ydoc } => {
|
||||||
const ydoc: Ydoc = new Ydoc()
|
const ydoc: Ydoc = new Ydoc({ guid: generateId() })
|
||||||
return {
|
return {
|
||||||
ydoc,
|
ydoc,
|
||||||
provider: createRemoteProvider(ydoc, params)
|
provider: createRemoteProvider(ydoc, params)
|
||||||
|
@ -16,11 +16,12 @@
|
|||||||
import { Doc as YDoc, encodeStateAsUpdate, encodeStateVector } from 'yjs'
|
import { Doc as YDoc, encodeStateAsUpdate, encodeStateVector } from 'yjs'
|
||||||
|
|
||||||
import { yDocBranch, yDocBranchWithGC } from '../branch'
|
import { yDocBranch, yDocBranchWithGC } from '../branch'
|
||||||
|
import { generateId } from '@hcengineering/core'
|
||||||
|
|
||||||
describe('branch', () => {
|
describe('branch', () => {
|
||||||
describe('yDocBranch', () => {
|
describe('yDocBranch', () => {
|
||||||
it('branches document without gc', async () => {
|
it('branches document without gc', async () => {
|
||||||
const source = new YDoc({ gc: false })
|
const source = new YDoc({ guid: generateId(), gc: false })
|
||||||
|
|
||||||
applyGarbageCollectableChanges(source)
|
applyGarbageCollectableChanges(source)
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ describe('branch', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('branches document state with gc', async () => {
|
it('branches document state with gc', async () => {
|
||||||
const source = new YDoc({ gc: true })
|
const source = new YDoc({ guid: generateId(), gc: true })
|
||||||
|
|
||||||
applyGarbageCollectableChanges(source)
|
applyGarbageCollectableChanges(source)
|
||||||
|
|
||||||
@ -72,7 +73,7 @@ describe('branch', () => {
|
|||||||
|
|
||||||
describe('yDocBranchWithGC', () => {
|
describe('yDocBranchWithGC', () => {
|
||||||
it('branches document state without gc', async () => {
|
it('branches document state without gc', async () => {
|
||||||
const source = new YDoc({ gc: false })
|
const source = new YDoc({ guid: generateId(), gc: false })
|
||||||
|
|
||||||
applyGarbageCollectableChanges(source)
|
applyGarbageCollectableChanges(source)
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ describe('branch', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('branches document state with gc', async () => {
|
it('branches document state with gc', async () => {
|
||||||
const source = new YDoc({ gc: true })
|
const source = new YDoc({ guid: generateId(), gc: true })
|
||||||
|
|
||||||
applyGarbageCollectableChanges(source)
|
applyGarbageCollectableChanges(source)
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ describe('history', () => {
|
|||||||
let ydoc: YDoc
|
let ydoc: YDoc
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ydoc = new YDoc()
|
ydoc = new YDoc({ guid: generateId() })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('addVersion should append new version', async () => {
|
it('addVersion should append new version', async () => {
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
import { Account, Ref, generateId } from '@hcengineering/core'
|
import { Account, Ref, generateId } from '@hcengineering/core'
|
||||||
import { Doc as YDoc } from 'yjs'
|
import { Doc as YDoc } from 'yjs'
|
||||||
|
|
||||||
import { createYdocSnapshot, restoreYdocSnapshot } from '../snapshot'
|
|
||||||
import { YDocVersion } from '../history'
|
import { YDocVersion } from '../history'
|
||||||
|
import { createYdocSnapshot, restoreYdocSnapshot } from '../snapshot'
|
||||||
|
|
||||||
const HISTORY = 'history'
|
const HISTORY = 'history'
|
||||||
const UPDATES = 'updates'
|
const UPDATES = 'updates'
|
||||||
@ -27,8 +27,8 @@ describe('snapshot', () => {
|
|||||||
let yHistory: YDoc
|
let yHistory: YDoc
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
yContent = new YDoc({ gc: false })
|
yContent = new YDoc({ guid: generateId(), gc: false })
|
||||||
yHistory = new YDoc()
|
yHistory = new YDoc({ guid: generateId() })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('createYdocSnapshot appends new version', async () => {
|
it('createYdocSnapshot appends new version', async () => {
|
||||||
@ -74,7 +74,7 @@ describe('snapshot', () => {
|
|||||||
const versionId = generateId()
|
const versionId = generateId()
|
||||||
const version = yDocVersion(versionId)
|
const version = yDocVersion(versionId)
|
||||||
|
|
||||||
yContent = new YDoc({ gc: true })
|
yContent = new YDoc({ guid: generateId(), gc: true })
|
||||||
createYdocSnapshot(yContent, yHistory, version)
|
createYdocSnapshot(yContent, yHistory, version)
|
||||||
expect(() => restoreYdocSnapshot(yContent, yHistory, versionId)).toThrow()
|
expect(() => restoreYdocSnapshot(yContent, yHistory, versionId)).toThrow()
|
||||||
})
|
})
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import { generateId } from '@hcengineering/core'
|
||||||
import { Doc as YDoc, applyUpdate, encodeStateAsUpdate } from 'yjs'
|
import { Doc as YDoc, applyUpdate, encodeStateAsUpdate } from 'yjs'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,7 +26,7 @@ import { Doc as YDoc, applyUpdate, encodeStateAsUpdate } from 'yjs'
|
|||||||
* @public
|
* @public
|
||||||
* */
|
* */
|
||||||
export function yDocBranch (source: YDoc): YDoc {
|
export function yDocBranch (source: YDoc): YDoc {
|
||||||
const target = new YDoc({ gc: source.gc })
|
const target = new YDoc({ guid: generateId(), gc: source.gc })
|
||||||
|
|
||||||
const update = encodeStateAsUpdate(source)
|
const update = encodeStateAsUpdate(source)
|
||||||
applyUpdate(target, update)
|
applyUpdate(target, update)
|
||||||
@ -43,9 +44,9 @@ export function yDocBranch (source: YDoc): YDoc {
|
|||||||
* @public
|
* @public
|
||||||
* */
|
* */
|
||||||
export function yDocBranchWithGC (source: YDoc): YDoc {
|
export function yDocBranchWithGC (source: YDoc): YDoc {
|
||||||
const target = new YDoc({ gc: source.gc })
|
const target = new YDoc({ guid: generateId(), gc: source.gc })
|
||||||
|
|
||||||
const gc = new YDoc({ gc: true })
|
const gc = new YDoc({ guid: generateId(), gc: true })
|
||||||
applyUpdate(gc, encodeStateAsUpdate(source))
|
applyUpdate(gc, encodeStateAsUpdate(source))
|
||||||
applyUpdate(target, encodeStateAsUpdate(gc))
|
applyUpdate(target, encodeStateAsUpdate(gc))
|
||||||
|
|
||||||
|
@ -16,22 +16,23 @@
|
|||||||
import { Doc as YDoc, XmlElement as YXmlElement, XmlText as YXmlText, encodeStateVector } from 'yjs'
|
import { Doc as YDoc, XmlElement as YXmlElement, XmlText as YXmlText, encodeStateVector } from 'yjs'
|
||||||
|
|
||||||
import { clone, yDocCopyXmlField, yDocFromBuffer, yDocToBuffer } from '../ydoc'
|
import { clone, yDocCopyXmlField, yDocFromBuffer, yDocToBuffer } from '../ydoc'
|
||||||
|
import { generateId } from '@hcengineering/core'
|
||||||
|
|
||||||
describe('ydoc', () => {
|
describe('ydoc', () => {
|
||||||
it('yDocFromBuffer converts ydoc to a buffer', async () => {
|
it('yDocFromBuffer converts ydoc to a buffer', async () => {
|
||||||
const ydoc = new YDoc()
|
const ydoc = new YDoc({ guid: generateId() })
|
||||||
const buffer = yDocToBuffer(ydoc)
|
const buffer = yDocToBuffer(ydoc)
|
||||||
|
|
||||||
expect(buffer).toBeDefined()
|
expect(buffer).toBeDefined()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('yDocFromBuffer converts buffer to a ydoc', async () => {
|
it('yDocFromBuffer converts buffer to a ydoc', async () => {
|
||||||
const source = new YDoc()
|
const source = new YDoc({ guid: generateId() })
|
||||||
source.getArray('data').insert(0, [1, 2])
|
source.getArray('data').insert(0, [1, 2])
|
||||||
|
|
||||||
const buffer = yDocToBuffer(source)
|
const buffer = yDocToBuffer(source)
|
||||||
|
|
||||||
const target = yDocFromBuffer(buffer, new YDoc())
|
const target = yDocFromBuffer(buffer, new YDoc({ guid: generateId() }))
|
||||||
expect(target).toBeDefined()
|
expect(target).toBeDefined()
|
||||||
expect(encodeStateVector(target)).toEqual(encodeStateVector(source))
|
expect(encodeStateVector(target)).toEqual(encodeStateVector(source))
|
||||||
})
|
})
|
||||||
|
@ -20,7 +20,8 @@ import {
|
|||||||
MeasureContext,
|
MeasureContext,
|
||||||
WorkspaceId,
|
WorkspaceId,
|
||||||
collaborativeDocParse,
|
collaborativeDocParse,
|
||||||
collaborativeDocUnchain
|
collaborativeDocUnchain,
|
||||||
|
generateId
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { Doc as YDoc } from 'yjs'
|
import { Doc as YDoc } from 'yjs'
|
||||||
|
|
||||||
@ -42,7 +43,13 @@ async function loadCollaborativeDocVersion (
|
|||||||
versionId: string
|
versionId: string
|
||||||
): Promise<YDoc | undefined> {
|
): Promise<YDoc | undefined> {
|
||||||
const yContent = await ctx.with('yDocFromStorage', { type: 'content' }, async (ctx) => {
|
const yContent = await ctx.with('yDocFromStorage', { type: 'content' }, async (ctx) => {
|
||||||
return await yDocFromStorage(ctx, storageAdapter, workspace, documentId, new YDoc({ gc: false }))
|
return await yDocFromStorage(
|
||||||
|
ctx,
|
||||||
|
storageAdapter,
|
||||||
|
workspace,
|
||||||
|
documentId,
|
||||||
|
new YDoc({ guid: generateId(), gc: false })
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// the document does not exist
|
// the document does not exist
|
||||||
@ -56,7 +63,7 @@ async function loadCollaborativeDocVersion (
|
|||||||
|
|
||||||
const historyDocumentId = collaborativeHistoryDocId(documentId)
|
const historyDocumentId = collaborativeHistoryDocId(documentId)
|
||||||
const yHistory = await ctx.with('yDocFromStorage', { type: 'history' }, async (ctx) => {
|
const yHistory = await ctx.with('yDocFromStorage', { type: 'history' }, async (ctx) => {
|
||||||
return await yDocFromStorage(ctx, storageAdapter, workspace, historyDocumentId, new YDoc())
|
return await yDocFromStorage(ctx, storageAdapter, workspace, historyDocumentId, new YDoc({ guid: generateId() }))
|
||||||
})
|
})
|
||||||
|
|
||||||
// the history document does not exist
|
// the history document does not exist
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { MeasureContext, WorkspaceId } from '@hcengineering/core'
|
import { generateId, MeasureContext, WorkspaceId } from '@hcengineering/core'
|
||||||
import { StorageAdapter } from '@hcengineering/server-core'
|
import { StorageAdapter } from '@hcengineering/server-core'
|
||||||
import { Doc as YDoc } from 'yjs'
|
import { Doc as YDoc } from 'yjs'
|
||||||
|
|
||||||
@ -35,10 +35,10 @@ export async function yDocFromStorage (
|
|||||||
|
|
||||||
// no need to apply gc because we load existing document
|
// no need to apply gc because we load existing document
|
||||||
// it is either already gc-ed, or gc not needed and it is disabled
|
// it is either already gc-ed, or gc not needed and it is disabled
|
||||||
ydoc ??= new YDoc({ gc: false })
|
ydoc ??= new YDoc({ guid: generateId(), gc: false })
|
||||||
|
|
||||||
const buffer = await storageAdapter.read(ctx, workspace, documentId)
|
const buffer = await storageAdapter.read(ctx, workspace, documentId)
|
||||||
return yDocFromBuffer(Buffer.concat(buffer), ydoc)
|
return yDocFromBuffer(Buffer.concat(buffer as any), ydoc)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
|
@ -50,7 +50,7 @@ export async function createRekoniAdapter (
|
|||||||
}
|
}
|
||||||
return r.content
|
return r.content
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.info('Content Processing error', name, type, doc, err.response.body)
|
console.info('Content Processing error', name, type, doc, err)
|
||||||
if (err.message === 'Response code 400 (Bad Request)' || err.code === 400) {
|
if (err.message === 'Response code 400 (Bad Request)' || err.code === 400) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user