From 8a8f56fda486d8dd3d206134efcc8beb34bf5969 Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Wed, 2 Oct 2024 18:00:38 +0700 Subject: [PATCH] UBERF-8316 Documents drag and drop (#6769) Signed-off-by: Alexander Onnikov --- dev/import-tool/package.json | 1 + dev/import-tool/src/notion.ts | 15 +- models/document/package.json | 3 +- models/document/src/index.ts | 6 +- models/document/src/migration.ts | 37 ++- packages/ui/src/components/NavGroup.svelte | 5 + packages/ui/src/components/NavItem.svelte | 8 +- .../src/components/CreateDocument.svelte | 8 +- .../src/components/Move.svelte | 6 +- .../components/navigator/DocHierarchy.svelte | 92 +++++-- .../navigator/DocTreeElement.svelte | 6 + .../src/components/navigator/DropArea.svelte | 29 ++ .../components/navigator/DropMarker.svelte | 33 +++ .../navigator/TeamspaceSpacePresenter.svelte | 252 ++++++++++++++---- plugins/document-resources/src/utils.ts | 50 +++- plugins/document/src/index.ts | 3 +- plugins/document/src/types.ts | 4 +- plugins/document/src/utils.ts | 35 +++ .../components/navigator/TreeElement.svelte | 9 + .../src/components/navigator/TreeNode.svelte | 5 + 20 files changed, 510 insertions(+), 97 deletions(-) create mode 100644 plugins/document-resources/src/components/navigator/DropArea.svelte create mode 100644 plugins/document-resources/src/components/navigator/DropMarker.svelte create mode 100644 plugins/document/src/utils.ts diff --git a/dev/import-tool/package.json b/dev/import-tool/package.json index 2f1a81148e..79602a42d9 100644 --- a/dev/import-tool/package.json +++ b/dev/import-tool/package.json @@ -61,6 +61,7 @@ "@hcengineering/platform": "^0.6.11", "@hcengineering/server-tool": "^0.6.0", "@hcengineering/server-client": "^0.6.0", + "@hcengineering/rank": "^0.6.4", "commander": "^8.1.0", "mime-types": "~2.1.34" } diff --git a/dev/import-tool/src/notion.ts b/dev/import-tool/src/notion.ts index 7eb5d3da2d..56500141c0 100644 --- a/dev/import-tool/src/notion.ts +++ b/dev/import-tool/src/notion.ts @@ -22,7 +22,8 @@ import { collaborativeDocParse } from '@hcengineering/core' import { yDocToBuffer } from '@hcengineering/collaboration' -import document, { type Document, type Teamspace } from '@hcengineering/document' +import document, { type Document, type Teamspace, getFirstRank } from '@hcengineering/document' +import { makeRank } from '@hcengineering/rank' import { MarkupMarkType, type MarkupNode, @@ -328,6 +329,9 @@ async function createDBPageWithAttachments ( 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, @@ -336,7 +340,8 @@ async function createDBPageWithAttachments ( embeddings: 0, labels: 0, comments: 0, - references: 0 + references: 0, + rank } await client.addCollection( @@ -479,6 +484,9 @@ async function importPageDocument ( const parentId = parentMeta?.id ?? document.ids.NoParent + const lastRank = await getFirstRank(client, space, parentId as Ref) + const rank = makeRank(lastRank, undefined) + const attachedData: AttachedData = { name: docMeta.name, content: collabId, @@ -487,7 +495,8 @@ async function importPageDocument ( embeddings: 0, labels: 0, comments: 0, - references: 0 + references: 0, + rank } await client.addCollection( diff --git a/models/document/package.json b/models/document/package.json index bdcb979429..55c1b687ad 100644 --- a/models/document/package.json +++ b/models/document/package.json @@ -50,6 +50,7 @@ "@hcengineering/time": "^0.6.0", "@hcengineering/document": "^0.6.0", "@hcengineering/document-resources": "^0.6.0", - "@hcengineering/collaboration": "^0.6.0" + "@hcengineering/collaboration": "^0.6.0", + "@hcengineering/rank": "^0.6.4" } } diff --git a/models/document/src/index.ts b/models/document/src/index.ts index a3f167cc0e..ef91dc535d 100644 --- a/models/document/src/index.ts +++ b/models/document/src/index.ts @@ -14,7 +14,7 @@ // import activity from '@hcengineering/activity' -import type { Class, CollaborativeDoc, CollectionSize, Domain, Role, RolesAssignment } from '@hcengineering/core' +import type { Class, CollaborativeDoc, CollectionSize, Domain, Rank, Role, RolesAssignment } from '@hcengineering/core' import { IndexKind, Account, Ref, AccountRole } from '@hcengineering/core' import { type Document, @@ -130,6 +130,10 @@ export class TDocument extends TAttachedDoc implements Document, Todoable { @Prop(Collection(time.class.ToDo), getEmbeddedLabel('Action Items')) todos?: CollectionSize + + @Index(IndexKind.Indexed) + @Hidden() + rank!: Rank } @Model(document.class.DocumentSnapshot, core.class.AttachedDoc, DOMAIN_DOCUMENT) diff --git a/models/document/src/migration.ts b/models/document/src/migration.ts index 89eeb311b8..4686a4db8d 100644 --- a/models/document/src/migration.ts +++ b/models/document/src/migration.ts @@ -13,16 +13,19 @@ // limitations under the License. // -import { DOMAIN_TX, MeasureMetricsContext } from '@hcengineering/core' +import { DOMAIN_TX, MeasureMetricsContext, SortingOrder } from '@hcengineering/core' import { type Document, type Teamspace } from '@hcengineering/document' import { - tryMigrate, type MigrateOperation, type MigrationClient, - type MigrationUpgradeClient + type MigrationUpgradeClient, + type MigrateUpdate, + type MigrationDocumentQuery, + tryMigrate } 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' @@ -127,6 +130,30 @@ async function migrateContentField (client: MigrationClient): Promise { } } +async function migrateRank (client: MigrationClient): Promise { + const documents = await client.find( + DOMAIN_DOCUMENT, + { + _class: document.class.Document, + rank: { $exists: false } + }, + { sort: { name: SortingOrder.Ascending } } + ) + + let rank = makeRank(undefined, undefined) + const operations: { filter: MigrationDocumentQuery, update: MigrateUpdate }[] = [] + + for (const doc of documents) { + operations.push({ + filter: { _id: doc._id }, + update: { $set: { rank } } + }) + rank = makeRank(rank, undefined) + } + + await client.bulk(DOMAIN_DOCUMENT, operations) +} + export const documentOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { await tryMigrate(client, documentId, [ @@ -145,6 +172,10 @@ export const documentOperation: MigrateOperation = { { state: 'migrateContentField', func: migrateContentField + }, + { + state: 'migrateRank', + func: migrateRank } ]) }, diff --git a/packages/ui/src/components/NavGroup.svelte b/packages/ui/src/components/NavGroup.svelte index 8ead2b7d2d..171846feca 100644 --- a/packages/ui/src/components/NavGroup.svelte +++ b/packages/ui/src/components/NavGroup.svelte @@ -55,6 +55,7 @@ export let showMenu: boolean = false export let shouldTooltip: boolean = false export let forciblyСollapsed: boolean = false + export let draggable: boolean = false export let actions: Action[] = [] export let _id: Ref | string | undefined = undefined @@ -97,6 +98,10 @@ class:selected class:showMenu={showMenu || pressed} on:click={toggle} + {draggable} + on:dragstart + on:dragover + on:drop > {#if isFold && !empty}