From 0c1b13f5e778536cf962006251b939e5bbe99242 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Thu, 16 Mar 2023 10:15:35 +0700 Subject: [PATCH] TSK-838: Created by (#2742) Signed-off-by: Andrey Sobolev --- models/board/src/migration.ts | 36 +-------- models/chunter/src/migration.ts | 36 +-------- models/core/src/component.ts | 1 - models/core/src/core.ts | 3 + models/core/src/migration.ts | 74 ++++++++++++++++++- models/core/src/security.ts | 3 - models/lead/src/migration.ts | 41 +--------- models/recruit/src/migration.ts | 33 --------- models/tracker/src/migration.ts | 35 --------- packages/core/src/classes.ts | 2 +- packages/core/src/component.ts | 3 +- packages/core/src/tx.ts | 4 +- packages/model/src/migration.ts | 10 +++ .../board-resources/src/utils/BoardUtils.ts | 3 +- .../src/components/CreateChannel.svelte | 3 +- .../src/components/CreateDirectMessage.svelte | 3 +- .../src/components/CreateFunnel.svelte | 3 +- .../src/components/CreateVacancy.svelte | 1 - .../components/CreateTemplateCategory.svelte | 5 +- .../issues/edit/ControlPanel.svelte | 50 ++++++++++++- .../src/components/teams/CreateTeam.svelte | 1 - server/backup/src/index.ts | 6 +- server/tool/src/index.ts | 17 ++++- server/tool/src/upgrade.ts | 32 +++++++- 24 files changed, 199 insertions(+), 206 deletions(-) diff --git a/models/board/src/migration.ts b/models/board/src/migration.ts index a58812d0f7..bef0d38024 100644 --- a/models/board/src/migration.ts +++ b/models/board/src/migration.ts @@ -29,7 +29,7 @@ import { TxUpdateDoc } from '@hcengineering/core' import { createOrUpdate, MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model' -import core, { DOMAIN_SPACE } from '@hcengineering/model-core' +import core from '@hcengineering/model-core' import { DOMAIN_TAGS } from '@hcengineering/model-tags' import { createKanbanTemplate, createSequence, DOMAIN_TASK } from '@hcengineering/model-task' import tags, { TagElement, TagReference } from '@hcengineering/tags' @@ -191,43 +191,9 @@ async function migrateLabels (client: MigrationClient): Promise { } } } - -async function fillCreatedBy (client: MigrationClient): Promise { - const objects = await client.find(DOMAIN_SPACE, { - _class: board.class.Board, - createdBy: { $exists: false } - }) - const txes = await client.find>(DOMAIN_TX, { - objectClass: board.class.Board, - _class: core.class.TxCreateDoc - }) - const txMap = new Map(txes.map((p) => [p.objectId, p])) - - for (const object of objects) { - const createTx = txMap.get(object._id) - if (createTx !== undefined && createTx.attributes.createdBy === undefined) { - await client.update( - DOMAIN_TX, - { _id: createTx._id }, - { - 'attributes.createdBy': createTx.modifiedBy - } - ) - } - await client.update( - DOMAIN_SPACE, - { _id: object._id }, - { - createdBy: createTx?.modifiedBy ?? object.modifiedBy - } - ) - } -} - export const boardOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { await Promise.all([migrateLabels(client)]) - await fillCreatedBy(client) }, async upgrade (client: MigrationUpgradeClient): Promise { const ops = new TxOperations(client, core.account.System) diff --git a/models/chunter/src/migration.ts b/models/chunter/src/migration.ts index 83ef2ada6d..7220a9643b 100644 --- a/models/chunter/src/migration.ts +++ b/models/chunter/src/migration.ts @@ -13,10 +13,9 @@ // limitations under the License. // -import { ChunterSpace, Comment, Message, ThreadMessage } from '@hcengineering/chunter' +import { Comment, Message, ThreadMessage } from '@hcengineering/chunter' import core, { Doc, DOMAIN_TX, Ref, TxCreateDoc, TxOperations } from '@hcengineering/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model' -import { DOMAIN_SPACE } from '@hcengineering/model-core' import { DOMAIN_CHUNTER, DOMAIN_COMMENT } from './index' import chunter from './plugin' @@ -179,43 +178,10 @@ export async function migrateThreadMessages (client: MigrationClient): Promise { - const objects = await client.find(DOMAIN_SPACE, { - _class: { $in: [chunter.class.DirectMessage, chunter.class.Channel] }, - createdBy: { $exists: false } - }) - const txes = await client.find>(DOMAIN_TX, { - objectClass: { $in: [chunter.class.DirectMessage, chunter.class.Channel] }, - _class: core.class.TxCreateDoc - }) - const txMap = new Map(txes.map((p) => [p.objectId, p])) - - for (const object of objects) { - const createTx = txMap.get(object._id) - if (createTx !== undefined && createTx.attributes.createdBy === undefined) { - await client.update( - DOMAIN_TX, - { _id: createTx._id }, - { - 'attributes.createdBy': createTx.modifiedBy - } - ) - } - await client.update( - DOMAIN_SPACE, - { _id: object._id }, - { - createdBy: createTx?.modifiedBy ?? object.modifiedBy - } - ) - } -} - export const chunterOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { await migrateMessages(client) await migrateThreadMessages(client) - await fillCreatedBy(client) }, async upgrade (client: MigrationUpgradeClient): Promise { const tx = new TxOperations(client, core.account.System) diff --git a/models/core/src/component.ts b/models/core/src/component.ts index 6e0ab85454..8135f32ebd 100644 --- a/models/core/src/component.ts +++ b/models/core/src/component.ts @@ -19,7 +19,6 @@ import { IntlString, mergeIds } from '@hcengineering/platform' export default mergeIds(coreId, core, { string: { Archived: '' as IntlString, - CreatedBy: '' as IntlString, ClassLabel: '' as IntlString, ClassPropertyLabel: '' as IntlString, Members: '' as IntlString diff --git a/models/core/src/core.ts b/models/core/src/core.ts index d17903413e..135bb41eb9 100644 --- a/models/core/src/core.ts +++ b/models/core/src/core.ts @@ -94,6 +94,9 @@ export class TDoc extends TObj implements Doc { @Prop(TypeRef(core.class.Account), core.string.ModifiedBy) modifiedBy!: Ref + + @Prop(TypeRef(core.class.Account), core.string.CreatedBy) + createdBy!: Ref } @Model(core.class.AttachedDoc, core.class.Doc) diff --git a/models/core/src/migration.ts b/models/core/src/migration.ts index 01d2fe246d..c5be987982 100644 --- a/models/core/src/migration.ts +++ b/models/core/src/migration.ts @@ -14,8 +14,80 @@ // import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model' +import core, { + Doc, + DOMAIN_BLOB, + DOMAIN_DOC_INDEX_STATE, + DOMAIN_MODEL, + DOMAIN_TX, + TxCreateDoc, + TxCollectionCUD, + AttachedDoc +} from '@hcengineering/core' +async function fillCreatedBy (client: MigrationClient): Promise { + const h = client.hierarchy + const domains = h.domains() + for (const domain of domains) { + if ( + domain === DOMAIN_TX || + domain === DOMAIN_MODEL || + domain === DOMAIN_BLOB || + domain === DOMAIN_DOC_INDEX_STATE + ) { + continue + } + try { + const objects = await client.find( + domain, + { createdBy: { $exists: false } }, + { projection: { _id: 1, modifiedBy: 1 } } + ) + if (objects.length === 0) { + continue + } + const txes = await client.find>( + DOMAIN_TX, + { + _class: core.class.TxCreateDoc, + objectId: { $in: Array.from(objects.map((it) => it._id)) } + }, + { projection: { _id: 1, modifiedBy: 1, createdBy: 1, objectId: 1 } } + ) + + const txes2 = ( + await client.find>( + DOMAIN_TX, + { + _class: core.class.TxCollectionCUD, + 'tx._class': core.class.TxCreateDoc, + 'tx.objectId': { $in: Array.from(objects.map((it) => it._id)) } + }, + { projection: { _id: 1, modifiedBy: 1, createdBy: 1, tx: 1 } } + ) + ).map((it) => it.tx as unknown as TxCreateDoc) + + const txMap = new Map(txes.concat(txes2).map((p) => [p.objectId, p])) + + console.log('migrateCreateBy', domain, objects.length) + await client.bulk( + domain, + objects.map((it) => { + const createTx = txMap.get(it._id) + return { + filter: { _id: it._id }, + update: { + createdBy: createTx?.modifiedBy ?? it.modifiedBy + } + } + }) + ) + } catch (err) {} + } +} export const coreOperation: MigrateOperation = { - async migrate (client: MigrationClient): Promise {}, + async migrate (client: MigrationClient): Promise { + await fillCreatedBy(client) + }, async upgrade (client: MigrationUpgradeClient): Promise {} } diff --git a/models/core/src/security.ts b/models/core/src/security.ts index bba97bdf44..9efa528acc 100644 --- a/models/core/src/security.ts +++ b/models/core/src/security.ts @@ -41,9 +41,6 @@ export class TSpace extends TDoc implements Space { @Prop(ArrOf(TypeRef(core.class.Account)), core.string.Members) members!: Arr> - - @Prop(TypeRef(core.class.Account), core.string.CreatedBy) - createdBy?: Ref } @Model(core.class.Account, core.class.Doc, DOMAIN_MODEL) diff --git a/models/lead/src/migration.ts b/models/lead/src/migration.ts index f990fdeaf3..8c4ddebdc3 100644 --- a/models/lead/src/migration.ts +++ b/models/lead/src/migration.ts @@ -13,10 +13,9 @@ // limitations under the License. // -import { DOMAIN_TX, Ref, TxCreateDoc, TxOperations } from '@hcengineering/core' -import { Funnel } from '@hcengineering/lead' +import { Ref, TxOperations } from '@hcengineering/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model' -import core, { DOMAIN_SPACE } from '@hcengineering/model-core' +import core from '@hcengineering/model-core' import { createKanbanTemplate, createSequence } from '@hcengineering/model-task' import task, { createKanban, KanbanTemplate } from '@hcengineering/task' import lead from './plugin' @@ -100,42 +99,8 @@ async function createDefaults (tx: TxOperations): Promise { await createDefaultKanban(tx) } -async function fillCreatedBy (client: MigrationClient): Promise { - const objects = await client.find(DOMAIN_SPACE, { - _class: lead.class.Funnel, - createdBy: { $exists: false } - }) - const txes = await client.find>(DOMAIN_TX, { - objectClass: lead.class.Funnel, - _class: core.class.TxCreateDoc - }) - const txMap = new Map(txes.map((p) => [p.objectId, p])) - - for (const object of objects) { - const createTx = txMap.get(object._id) - if (createTx !== undefined && createTx.attributes.createdBy === undefined) { - await client.update( - DOMAIN_TX, - { _id: createTx._id }, - { - 'attributes.createdBy': createTx.modifiedBy - } - ) - } - await client.update( - DOMAIN_SPACE, - { _id: object._id }, - { - createdBy: createTx?.modifiedBy ?? object.modifiedBy - } - ) - } -} - export const leadOperation: MigrateOperation = { - async migrate (client: MigrationClient): Promise { - await fillCreatedBy(client) - }, + async migrate (client: MigrationClient): Promise {}, async upgrade (client: MigrationUpgradeClient): Promise { const ops = new TxOperations(client, core.account.System) await createDefaults(ops) diff --git a/models/recruit/src/migration.ts b/models/recruit/src/migration.ts index 02d11069ef..99e4507801 100644 --- a/models/recruit/src/migration.ts +++ b/models/recruit/src/migration.ts @@ -140,38 +140,6 @@ async function fillVacancyNumbers (client: MigrationClient): Promise { } } -async function fillCreatedBy (client: MigrationClient): Promise { - const objects = await client.find(DOMAIN_SPACE, { - _class: recruit.class.Vacancy, - createdBy: { $exists: false } - }) - const txes = await client.find>(DOMAIN_TX, { - objectClass: recruit.class.Vacancy, - _class: core.class.TxCreateDoc - }) - const txMap = new Map(txes.map((p) => [p.objectId, p])) - - for (const object of objects) { - const createTx = txMap.get(object._id) - if (createTx !== undefined && createTx.attributes.createdBy === undefined) { - await client.update( - DOMAIN_TX, - { _id: createTx._id }, - { - 'attributes.createdBy': createTx.modifiedBy - } - ) - } - await client.update( - DOMAIN_SPACE, - { _id: object._id }, - { - createdBy: createTx?.modifiedBy ?? object.modifiedBy - } - ) - } -} - export const recruitOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { await setCreate(client) @@ -214,7 +182,6 @@ export const recruitOperation: MigrateOperation = { ) } } - await fillCreatedBy(client) }, async upgrade (client: MigrationUpgradeClient): Promise { const tx = new TxOperations(client, core.account.System) diff --git a/models/tracker/src/migration.ts b/models/tracker/src/migration.ts index c867684764..d7561f295e 100644 --- a/models/tracker/src/migration.ts +++ b/models/tracker/src/migration.ts @@ -20,12 +20,10 @@ import core, { generateId, Ref, SortingOrder, - TxCreateDoc, TxOperations, TxResult } from '@hcengineering/core' import { createOrUpdate, MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@hcengineering/model' -import { DOMAIN_SPACE } from '@hcengineering/model-core' import tags from '@hcengineering/tags' import { calcRank, @@ -410,38 +408,6 @@ async function upgradeIssues (tx: TxOperations): Promise { } } -async function fillCreatedBy (client: MigrationClient): Promise { - const objects = await client.find(DOMAIN_SPACE, { - _class: tracker.class.Team, - createdBy: { $exists: false } - }) - const txes = await client.find>(DOMAIN_TX, { - objectClass: tracker.class.Team, - _class: core.class.TxCreateDoc - }) - const txMap = new Map(txes.map((p) => [p.objectId, p])) - - for (const object of objects) { - const createTx = txMap.get(object._id) - if (createTx !== undefined && createTx.attributes.createdBy === undefined) { - await client.update( - DOMAIN_TX, - { _id: createTx._id }, - { - 'attributes.createdBy': createTx.modifiedBy - } - ) - } - await client.update( - DOMAIN_SPACE, - { _id: object._id }, - { - createdBy: createTx?.modifiedBy ?? object.modifiedBy - } - ) - } -} - async function upgradeProjects (tx: TxOperations): Promise { await upgradeProjectIcons(tx) } @@ -460,7 +426,6 @@ export const trackerOperation: MigrateOperation = { await Promise.all([migrateIssueProjects(client), migrateParentIssues(client)]) await migrateIssueParentInfo(client) await fillRank(client) - await fillCreatedBy(client) }, async upgrade (client: MigrationUpgradeClient): Promise { const tx = new TxOperations(client, core.account.System) diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index b7c557de2a..4fa6644eac 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -56,6 +56,7 @@ export interface Doc extends Obj { space: Ref modifiedOn: Timestamp modifiedBy: Ref + createdBy?: Ref } /** @@ -295,7 +296,6 @@ export interface Space extends Doc { private: boolean members: Arr> archived: boolean - createdBy?: Ref } /** diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 3b9d319ab6..78d01a43e5 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -154,6 +154,7 @@ export default plugin(coreId, { Description: '' as IntlString, Hyperlink: '' as IntlString, Private: '' as IntlString, - Object: '' as IntlString + Object: '' as IntlString, + CreatedBy: '' as IntlString } }) diff --git a/packages/core/src/tx.ts b/packages/core/src/tx.ts index 73e81c4120..a5d06d29ba 100644 --- a/packages/core/src/tx.ts +++ b/packages/core/src/tx.ts @@ -312,7 +312,8 @@ export abstract class TxProcessor implements WithTx { _class: tx.objectClass, space: tx.objectSpace, modifiedBy: tx.modifiedBy, - modifiedOn: tx.modifiedOn + modifiedOn: tx.modifiedOn, + createdBy: tx.createdBy ?? tx.modifiedBy } as T } @@ -444,6 +445,7 @@ export class TxFactory { objectSpace: space, modifiedOn: modifiedOn ?? Date.now(), modifiedBy: modifiedBy ?? this.account, + createdBy: modifiedBy ?? this.account, attributes } } diff --git a/packages/model/src/migration.ts b/packages/model/src/migration.ts index 774aaea415..16a60aff6e 100644 --- a/packages/model/src/migration.ts +++ b/packages/model/src/migration.ts @@ -5,7 +5,9 @@ import { DocumentQuery, Domain, FindOptions, + Hierarchy, IncOptions, + ModelDb, ObjQueryType, OmitNever, PushOptions, @@ -71,11 +73,19 @@ export interface MigrationClient { operations: MigrateUpdate ) => Promise + bulk: ( + domain: Domain, + operations: { filter: MigrationDocumentQuery, update: MigrateUpdate }[] + ) => Promise + // Move documents per domain move: (sourceDomain: Domain, query: DocumentQuery, targetDomain: Domain) => Promise create: (domain: Domain, doc: T) => Promise delete: (domain: Domain, _id: Ref) => Promise + + hierarchy: Hierarchy + model: ModelDb } /** diff --git a/plugins/board-resources/src/utils/BoardUtils.ts b/plugins/board-resources/src/utils/BoardUtils.ts index 5e6c94db11..571c517a7e 100644 --- a/plugins/board-resources/src/utils/BoardUtils.ts +++ b/plugins/board-resources/src/utils/BoardUtils.ts @@ -30,8 +30,7 @@ export async function createBoard ( description, private: false, archived: false, - members: [getCurrentAccount()._id], - createdBy: getCurrentAccount()._id + members: [getCurrentAccount()._id] }) await Promise.all([createKanban(client, boardRef, templateId)]) diff --git a/plugins/chunter-resources/src/components/CreateChannel.svelte b/plugins/chunter-resources/src/components/CreateChannel.svelte index e9aad81be1..4cd6ee8731 100644 --- a/plugins/chunter-resources/src/components/CreateChannel.svelte +++ b/plugins/chunter-resources/src/components/CreateChannel.svelte @@ -37,8 +37,7 @@ description: '', private: isPrivate, archived: false, - members: [getCurrentAccount()._id], - createdBy: getCurrentAccount()._id + members: [getCurrentAccount()._id] }) const navigate = await getResource(workbench.actionImpl.Navigate) diff --git a/plugins/chunter-resources/src/components/CreateDirectMessage.svelte b/plugins/chunter-resources/src/components/CreateDirectMessage.svelte index 3032ab8cfc..4c5f8a6bce 100644 --- a/plugins/chunter-resources/src/components/CreateDirectMessage.svelte +++ b/plugins/chunter-resources/src/components/CreateDirectMessage.svelte @@ -52,8 +52,7 @@ description: '', private: true, archived: false, - members: accIds, - createdBy: getCurrentAccount()._id + members: accIds }) await navigate([], undefined as any, { diff --git a/plugins/lead-resources/src/components/CreateFunnel.svelte b/plugins/lead-resources/src/components/CreateFunnel.svelte index 9b810c839c..f4a76ede17 100644 --- a/plugins/lead-resources/src/components/CreateFunnel.svelte +++ b/plugins/lead-resources/src/components/CreateFunnel.svelte @@ -47,8 +47,7 @@ description, private: isPrivate, archived: false, - members: [getCurrentAccount()._id], - createdBy: getCurrentAccount()._id + members: [getCurrentAccount()._id] }) await createKanban(client, id, templateId) diff --git a/plugins/recruit-resources/src/components/CreateVacancy.svelte b/plugins/recruit-resources/src/components/CreateVacancy.svelte index 342da76346..60e1b537a7 100644 --- a/plugins/recruit-resources/src/components/CreateVacancy.svelte +++ b/plugins/recruit-resources/src/components/CreateVacancy.svelte @@ -143,7 +143,6 @@ archived: false, number: (incResult as any).object.sequence, company, - createdBy: getCurrentAccount()._id, members: [getCurrentAccount()._id] }, objectId diff --git a/plugins/templates-resources/src/components/CreateTemplateCategory.svelte b/plugins/templates-resources/src/components/CreateTemplateCategory.svelte index 43df1c7ecd..92d415c2fa 100644 --- a/plugins/templates-resources/src/components/CreateTemplateCategory.svelte +++ b/plugins/templates-resources/src/components/CreateTemplateCategory.svelte @@ -13,7 +13,7 @@ // limitations under the License. --> diff --git a/plugins/tracker-resources/src/components/issues/edit/ControlPanel.svelte b/plugins/tracker-resources/src/components/issues/edit/ControlPanel.svelte index 02b65fd58f..e29d4af919 100644 --- a/plugins/tracker-resources/src/components/issues/edit/ControlPanel.svelte +++ b/plugins/tracker-resources/src/components/issues/edit/ControlPanel.svelte @@ -13,8 +13,11 @@ // limitations under the License. -->
@@ -126,6 +154,13 @@ + + +
+ +
+ @@ -196,4 +231,17 @@ align-self: start; margin-top: 0.385rem; } + + .employee-button { + padding: 0 0.875rem; + border: 1px solid transparent; + display: flex; + min-height: 2rem; + &:hover { + border: 1px solid var(--button-border-hover); + color: var(--accent-color); + transition-duration: 0; + border-radius: 0.25rem; + } + } diff --git a/plugins/tracker-resources/src/components/teams/CreateTeam.svelte b/plugins/tracker-resources/src/components/teams/CreateTeam.svelte index 6ab4def20d..1401bc378e 100644 --- a/plugins/tracker-resources/src/components/teams/CreateTeam.svelte +++ b/plugins/tracker-resources/src/components/teams/CreateTeam.svelte @@ -77,7 +77,6 @@ private: isPrivate, members, archived: false, - createdBy: getCurrentAccount()._id, identifier, sequence: 0, issueStatuses: 0, diff --git a/server/backup/src/index.ts b/server/backup/src/index.ts index b5ea68c633..ecaae4ff04 100644 --- a/server/backup/src/index.ts +++ b/server/backup/src/index.ts @@ -214,11 +214,9 @@ export async function backup (transactorUrl: string, workspaceId: WorkspaceId, s const infoFile = 'backup.json.gz' if (await storage.exists(infoFile)) { - const backupInfoE = JSON.parse(gunzipSync(await storage.loadFile(infoFile)).toString()) - if (backupInfoE.version === backupInfo.version) { - backupInfo = backupInfoE - } + backupInfo = JSON.parse(gunzipSync(await storage.loadFile(infoFile)).toString()) } + backupInfo.version = '0.6.1' backupInfo.workspace = workspaceId.name backupInfo.productId = workspaceId.productId diff --git a/server/tool/src/index.ts b/server/tool/src/index.ts index ed1b957a12..fbdf0b113a 100644 --- a/server/tool/src/index.ts +++ b/server/tool/src/index.ts @@ -22,7 +22,9 @@ import core, { DOMAIN_MODEL, DOMAIN_TX, FieldIndex, + Hierarchy, IndexKind, + ModelDb, Tx, WorkspaceId } from '@hcengineering/core' @@ -172,7 +174,20 @@ export async function upgradeModel ( const insert = await db.collection(DOMAIN_TX).insertMany(model as Document[]) console.log(`${insert.insertedCount} model transactions inserted.`) - const migrateClient = new MigrateClientImpl(db) + const hierarchy = new Hierarchy() + const modelDb = new ModelDb(hierarchy) + for (const tx of txes) { + try { + hierarchy.tx(tx) + } catch (err: any) {} + } + for (const tx of txes) { + try { + await modelDb.tx(tx) + } catch (err: any) {} + } + + const migrateClient = new MigrateClientImpl(db, hierarchy, modelDb) for (const op of migrateOperations) { console.log('migrate:', op[0]) await op[1].migrate(migrateClient) diff --git a/server/tool/src/upgrade.ts b/server/tool/src/upgrade.ts index d4bacfd472..7e3cef9c3c 100644 --- a/server/tool/src/upgrade.ts +++ b/server/tool/src/upgrade.ts @@ -1,12 +1,22 @@ -import { Doc, DocumentQuery, Domain, FindOptions, isOperator, Ref, SortingOrder } from '@hcengineering/core' -import { MigrationClient, MigrateUpdate, MigrationResult } from '@hcengineering/model' +import { + Doc, + DocumentQuery, + Domain, + FindOptions, + Hierarchy, + isOperator, + ModelDb, + Ref, + SortingOrder +} from '@hcengineering/core' +import { MigrateUpdate, MigrationClient, MigrationResult } from '@hcengineering/model' import { Db, Document, Filter, Sort, UpdateFilter } from 'mongodb' /** * Upgrade client implementation. */ export class MigrateClientImpl implements MigrationClient { - constructor (readonly db: Db) {} + constructor (readonly db: Db, readonly hierarchy: Hierarchy, readonly model: ModelDb) {} private translateQuery(query: DocumentQuery): Filter { const translated: any = {} @@ -67,6 +77,22 @@ export class MigrateClientImpl implements MigrationClient { } } + async bulk( + domain: Domain, + operations: { filter: DocumentQuery, update: MigrateUpdate }[] + ): Promise { + const result = await this.db.collection(domain).bulkWrite( + operations.map((it) => ({ + updateOne: { + filter: this.translateQuery(it.filter), + update: { $set: it.update } + } + })) + ) + + return { matched: result.matchedCount, updated: result.modifiedCount } + } + async move( sourceDomain: Domain, query: DocumentQuery,