TSK-810 Rename Team -> Project, Project -> Component (#2756)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2023-03-17 12:17:53 +06:00
committed by GitHub
parent 26adf14966
commit 0f24fe80d6
110 changed files with 1646 additions and 1324 deletions
+327 -51
View File
@@ -14,16 +14,20 @@
//
import core, {
Class,
Doc,
DocumentUpdate,
DOMAIN_TX,
generateId,
Ref,
SortingOrder,
TxCreateDoc,
TxOperations,
TxResult
TxResult,
TxUpdateDoc
} 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,
@@ -31,7 +35,9 @@ import {
Issue,
IssueStatus,
IssueStatusCategory,
Team,
IssueTemplate,
IssueTemplateChild,
Project,
TimeReportDayType,
WorkDayLength
} from '@hcengineering/tracker'
@@ -46,9 +52,9 @@ enum DeprecatedIssueStatus {
Canceled
}
interface CreateTeamIssueStatusesArgs {
interface CreateProjectIssueStatusesArgs {
tx: TxOperations
teamId: Ref<Team>
projectId: Ref<Project>
categories: IssueStatusCategory[]
defaultStatusId?: Ref<IssueStatus>
defaultCategoryId?: Ref<IssueStatusCategory>
@@ -62,13 +68,13 @@ const categoryByDeprecatedIssueStatus = {
[DeprecatedIssueStatus.Canceled]: tracker.issueStatusCategory.Canceled
} as const
async function createTeamIssueStatuses ({
async function createProjectIssueStatuses ({
tx,
teamId: attachedTo,
projectId: attachedTo,
categories,
defaultStatusId,
defaultCategoryId = tracker.issueStatusCategory.Backlog
}: CreateTeamIssueStatusesArgs): Promise<void> {
}: CreateProjectIssueStatusesArgs): Promise<void> {
const issueStatusRanks = [...genRanks(categories.length)]
for (const [i, statusCategory] of categories.entries()) {
@@ -79,7 +85,7 @@ async function createTeamIssueStatuses ({
tracker.class.IssueStatus,
attachedTo,
attachedTo,
tracker.class.Team,
tracker.class.Project,
'issueStatuses',
{ name: defaultStatusName, category, rank },
category === defaultCategoryId ? defaultStatusId : undefined
@@ -87,13 +93,13 @@ async function createTeamIssueStatuses ({
}
}
async function createDefaultTeam (tx: TxOperations): Promise<void> {
const current = await tx.findOne(tracker.class.Team, {
_id: tracker.team.DefaultTeam
async function createDefaultProject (tx: TxOperations): Promise<void> {
const current = await tx.findOne(tracker.class.Project, {
_id: tracker.project.DefaultProject
})
const currentDeleted = await tx.findOne(core.class.TxRemoveDoc, {
objectId: tracker.team.DefaultTeam
objectId: tracker.project.DefaultProject
})
// Create new if not deleted by customers.
@@ -105,12 +111,12 @@ async function createDefaultTeam (tx: TxOperations): Promise<void> {
{ sort: { order: SortingOrder.Ascending } }
)
await tx.createDoc<Team>(
tracker.class.Team,
await tx.createDoc<Project>(
tracker.class.Project,
core.space.Space,
{
name: 'Default',
description: 'Default team',
description: 'Default project',
private: false,
members: [],
archived: false,
@@ -122,16 +128,16 @@ async function createDefaultTeam (tx: TxOperations): Promise<void> {
defaultAssignee: undefined,
workDayLength: WorkDayLength.EIGHT_HOURS
},
tracker.team.DefaultTeam
tracker.project.DefaultProject
)
await createTeamIssueStatuses({ tx, teamId: tracker.team.DefaultTeam, categories, defaultStatusId })
await createProjectIssueStatuses({ tx, projectId: tracker.project.DefaultProject, categories, defaultStatusId })
}
}
async function fixTeamIssueStatusesOrder (tx: TxOperations, team: Team): Promise<TxResult> {
async function fixProjectIssueStatusesOrder (tx: TxOperations, project: Project): Promise<TxResult> {
const statuses = await tx.findAll(
tracker.class.IssueStatus,
{ attachedTo: team._id },
{ attachedTo: project._id },
{ lookup: { category: tracker.class.IssueStatusCategory } }
)
statuses.sort((a, b) => (a.$lookup?.category?.order ?? 0) - (b.$lookup?.category?.order ?? 0))
@@ -143,19 +149,19 @@ async function fixTeamIssueStatusesOrder (tx: TxOperations, team: Team): Promise
})
}
async function fixTeamsIssueStatusesOrder (tx: TxOperations): Promise<void> {
const teams = await tx.findAll(tracker.class.Team, {})
await Promise.all(teams.map((team) => fixTeamIssueStatusesOrder(tx, team)))
async function fixProjectsIssueStatusesOrder (tx: TxOperations): Promise<void> {
const projects = await tx.findAll(tracker.class.Project, {})
await Promise.all(projects.map((project) => fixProjectIssueStatusesOrder(tx, project)))
}
async function upgradeTeamSettings (tx: TxOperations): Promise<void> {
const teams = await tx.findAll(tracker.class.Team, {
async function upgradeProjectSettings (tx: TxOperations): Promise<void> {
const projects = await tx.findAll(tracker.class.Project, {
defaultTimeReportDay: { $exists: false },
workDayLength: { $exists: false }
})
await Promise.all(
teams.map((team) =>
tx.update(team, {
projects.map((project) =>
tx.update(project, {
defaultTimeReportDay: TimeReportDayType.PreviousWorkDay,
workDayLength: WorkDayLength.EIGHT_HOURS
})
@@ -163,21 +169,21 @@ async function upgradeTeamSettings (tx: TxOperations): Promise<void> {
)
}
async function upgradeTeamIssueStatuses (tx: TxOperations): Promise<void> {
const teams = await tx.findAll(tracker.class.Team, { issueStatuses: undefined })
async function upgradeProjectIssueStatuses (tx: TxOperations): Promise<void> {
const projects = await tx.findAll(tracker.class.Project, { issueStatuses: undefined })
if (teams.length > 0) {
if (projects.length > 0) {
const categories = await tx.findAll(
tracker.class.IssueStatusCategory,
{},
{ sort: { order: SortingOrder.Ascending } }
)
for (const team of teams) {
for (const project of projects) {
const defaultStatusId: Ref<IssueStatus> = generateId()
await tx.update(team, { issueStatuses: 0, defaultIssueStatus: defaultStatusId })
await createTeamIssueStatuses({ tx, teamId: team._id, categories, defaultStatusId })
await tx.update(project, { issueStatuses: 0, defaultIssueStatus: defaultStatusId })
await createProjectIssueStatuses({ tx, projectId: project._id, categories, defaultStatusId })
}
}
}
@@ -291,38 +297,38 @@ async function migrateIssueParentInfo (client: MigrationClient): Promise<void> {
await updateIssueParentInfo(client, null)
}
async function migrateIssueProjects (client: MigrationClient): Promise<void> {
const issues = await client.find(DOMAIN_TRACKER, { _class: tracker.class.Issue, project: { $exists: false } })
async function migrateIssueComponents (client: MigrationClient): Promise<void> {
const issues = await client.find(DOMAIN_TRACKER, { _class: tracker.class.Issue, component: { $exists: false } })
if (issues.length === 0) {
return
}
for (const issue of issues) {
await client.update(DOMAIN_TRACKER, { _id: issue._id }, { project: null })
await client.update(DOMAIN_TRACKER, { _id: issue._id }, { component: null })
}
}
async function upgradeProjectIcons (tx: TxOperations): Promise<void> {
const projects = await tx.findAll(tracker.class.Project, {})
async function upgradeComponentIcons (tx: TxOperations): Promise<void> {
const components = await tx.findAll(tracker.class.Component, {})
if (projects.length === 0) {
if (components.length === 0) {
return
}
for (const project of projects) {
const icon = project.icon as unknown
for (const component of components) {
const icon = component.icon as unknown
if (icon !== undefined) {
continue
}
await tx.update(project, { icon: tracker.icon.Projects })
await tx.update(component, { icon: tracker.icon.Components })
}
}
async function createDefaults (tx: TxOperations): Promise<void> {
await createDefaultTeam(tx)
await createDefaultProject(tx)
await createOrUpdate(
tx,
tags.class.TagCategory,
@@ -377,10 +383,10 @@ async function fillRank (client: MigrationClient): Promise<void> {
}
}
async function upgradeTeams (tx: TxOperations): Promise<void> {
await upgradeTeamIssueStatuses(tx)
await fixTeamsIssueStatusesOrder(tx)
await upgradeTeamSettings(tx)
async function upgradeProjects (tx: TxOperations): Promise<void> {
await upgradeProjectIssueStatuses(tx)
await fixProjectsIssueStatusesOrder(tx)
await upgradeProjectSettings(tx)
}
async function upgradeIssues (tx: TxOperations): Promise<void> {
@@ -408,8 +414,277 @@ async function upgradeIssues (tx: TxOperations): Promise<void> {
}
}
async function upgradeProjects (tx: TxOperations): Promise<void> {
await upgradeProjectIcons(tx)
async function upgradeComponents (tx: TxOperations): Promise<void> {
await upgradeComponentIcons(tx)
}
async function renameProject (client: MigrationClient): Promise<void> {
await client.update(
DOMAIN_TRACKER,
{
_class: { $in: [tracker.class.Issue, tracker.class.Sprint] },
project: { $exists: true }
},
{
$rename: { project: 'component' }
}
)
await client.update(
DOMAIN_TX,
{
_class: core.class.TxCollectionCUD,
'tx._class': core.class.TxCreateDoc,
'tx.objectClass': tracker.class.Issue,
'tx.attributes.project': { $exists: true }
},
{
$rename: { 'tx.attributes.project': 'tx.attributes.component' }
}
)
await client.update(
DOMAIN_TX,
{
_class: core.class.TxCollectionCUD,
'tx._class': core.class.TxUpdateDoc,
'tx.objectClass': tracker.class.Issue,
'tx.operations.project': { $exists: true }
},
{
$rename: { 'tx.operations.project': 'tx.operations.component' }
}
)
await client.update(
DOMAIN_TX,
{
objectClass: tracker.class.Sprint,
_class: core.class.TxCreateDoc,
'attributes.project': { $exists: true }
},
{
$rename: { 'attributes.project': 'attributes.component' }
}
)
await client.update(
DOMAIN_TX,
{
objectClass: { $in: [tracker.class.Issue, tracker.class.Sprint] },
_class: core.class.TxUpdateDoc,
'operations.project': { $exists: true }
},
{
$rename: { 'operations.project': 'operations.component' }
}
)
const templates = await client.find<IssueTemplate>(DOMAIN_TRACKER, {
_class: tracker.class.IssueTemplate,
project: { $exists: true }
})
for (const template of templates) {
const children: IssueTemplateChild[] = template.children.map((p) => {
const res = {
...p,
component: p.component
}
delete (res as any).project
return res
})
await client.update<IssueTemplate>(
DOMAIN_TRACKER,
{
_id: template._id
},
{
children
}
)
await client.update(
DOMAIN_TRACKER,
{
_id: template._id
},
{
$rename: { project: 'component' }
}
)
const createTxes = await client.find<TxCreateDoc<IssueTemplate>>(DOMAIN_TX, {
objectId: template._id,
_class: core.class.TxCreateDoc
})
for (const createTx of createTxes) {
const children: IssueTemplateChild[] = createTx.attributes.children.map((p) => {
const res = {
...p,
component: p.component
}
delete (res as any).project
return res
})
await client.update<TxCreateDoc<IssueTemplate>>(
DOMAIN_TX,
{
_id: createTx._id
},
{
children
}
)
await client.update(
DOMAIN_TX,
{
_id: createTx._id
},
{
$rename: { 'attributes.project': 'attributes.component' }
}
)
}
const updateTxes = await client.find<TxUpdateDoc<IssueTemplate>>(DOMAIN_TX, {
objectId: template._id,
_class: core.class.TxUpdateDoc
})
for (const updateTx of updateTxes) {
if ((updateTx.operations as any).project !== undefined) {
await client.update(
DOMAIN_TX,
{
_id: updateTx._id
},
{
$rename: { 'operations.project': 'operations.component' }
}
)
}
if (updateTx.operations.children !== undefined) {
const children: IssueTemplateChild[] = updateTx.operations.children.map((p) => {
const res = {
...p,
component: p.component
}
delete (res as any).project
return res
})
await client.update(
DOMAIN_TX,
{
_id: updateTx._id
},
{
children
}
)
}
}
}
const defaultSpace = (
await client.find<Project>(DOMAIN_SPACE, {
_id: 'tracker:team:DefaultTeam' as Ref<Project>
})
)[0]
if (defaultSpace !== undefined) {
await client.delete(DOMAIN_SPACE, tracker.project.DefaultProject)
await client.create(DOMAIN_SPACE, {
...defaultSpace,
_id: tracker.project.DefaultProject,
_class: tracker.class.Project,
description: defaultSpace.description === 'Default team' ? 'Default project' : defaultSpace.description
})
await client.delete(DOMAIN_SPACE, defaultSpace._id)
}
await client.update(
DOMAIN_SPACE,
{
_id: 'tracker:team:DefaultTeam' as Ref<Project>,
_class: 'tracker:class:Team' as Ref<Class<Doc>>
},
{
_id: tracker.project.DefaultProject,
_class: tracker.class.Project,
description: 'Default project'
}
)
await client.update(
DOMAIN_TRACKER,
{
attachedTo: 'tracker:team:DefaultTeam' as Ref<Doc>
},
{
attachedTo: tracker.project.DefaultProject
}
)
await client.update(
DOMAIN_TRACKER,
{
space: 'tracker:team:DefaultTeam' as Ref<Project>
},
{
space: tracker.project.DefaultProject
}
)
await client.update(
DOMAIN_TRACKER,
{
attachedToClass: 'tracker:class:Team' as Ref<Class<Doc>>
},
{
attachedToClass: tracker.class.Project
}
)
await client.update(
DOMAIN_TX,
{
objectId: 'tracker:team:DefaultTeam' as Ref<Project>
},
{
objectId: tracker.project.DefaultProject
}
)
await client.update(
DOMAIN_TX,
{
objectClass: 'tracker:class:Team' as Ref<Class<Doc>>
},
{
objectClass: tracker.class.Project
}
)
await client.update(
DOMAIN_TX,
{
'tx.objectClass': 'tracker:class:Team' as Ref<Class<Doc>>
},
{
'tx.objectClass': tracker.class.Project
}
)
await client.update(
DOMAIN_TX,
{
objectSpace: 'tracker:team:DefaultTeam' as Ref<Project>
},
{
objectSpace: tracker.project.DefaultProject
}
)
await client.update(
DOMAIN_TX,
{
'tx.objectSpace': 'tracker:team:DefaultTeam' as Ref<Project>
},
{
'tx.objectSpace': tracker.project.DefaultProject
}
)
}
export const trackerOperation: MigrateOperation = {
@@ -423,15 +698,16 @@ export const trackerOperation: MigrateOperation = {
reportedTime: 0
}
)
await Promise.all([migrateIssueProjects(client), migrateParentIssues(client)])
await Promise.all([migrateIssueComponents(client), migrateParentIssues(client)])
await migrateIssueParentInfo(client)
await fillRank(client)
await renameProject(client)
},
async upgrade (client: MigrationUpgradeClient): Promise<void> {
const tx = new TxOperations(client, core.account.System)
await createDefaults(tx)
await upgradeTeams(tx)
await upgradeIssues(tx)
await upgradeProjects(tx)
await upgradeIssues(tx)
await upgradeComponents(tx)
}
}