diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 1da7b771ed..bcd0e30ae4 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -51,7 +51,7 @@ specifiers: '@rush-temp/model-server-chunter': file:./projects/model-server-chunter.tgz '@rush-temp/model-server-core': file:./projects/model-server-core.tgz '@rush-temp/model-server-recruit': file:./projects/model-server-recruit.tgz - '@rush-temp/model-server-view': file:./projects/model-server-view.tgz + '@rush-temp/model-server-task': file:./projects/model-server-task.tgz '@rush-temp/model-setting': file:./projects/model-setting.tgz '@rush-temp/model-task': file:./projects/model-task.tgz '@rush-temp/model-telegram': file:./projects/model-telegram.tgz @@ -74,8 +74,8 @@ specifiers: '@rush-temp/server-core': file:./projects/server-core.tgz '@rush-temp/server-recruit': file:./projects/server-recruit.tgz '@rush-temp/server-recruit-resources': file:./projects/server-recruit-resources.tgz - '@rush-temp/server-view': file:./projects/server-view.tgz - '@rush-temp/server-view-resources': file:./projects/server-view-resources.tgz + '@rush-temp/server-task': file:./projects/server-task.tgz + '@rush-temp/server-task-resources': file:./projects/server-task-resources.tgz '@rush-temp/server-ws': file:./projects/server-ws.tgz '@rush-temp/setting': file:./projects/setting.tgz '@rush-temp/setting-assets': file:./projects/setting-assets.tgz @@ -220,7 +220,7 @@ dependencies: '@rush-temp/model-server-chunter': file:projects/model-server-chunter.tgz_typescript@4.4.3 '@rush-temp/model-server-core': file:projects/model-server-core.tgz_typescript@4.4.3 '@rush-temp/model-server-recruit': file:projects/model-server-recruit.tgz_typescript@4.4.3 - '@rush-temp/model-server-view': file:projects/model-server-view.tgz_typescript@4.4.3 + '@rush-temp/model-server-task': file:projects/model-server-task.tgz_typescript@4.4.3 '@rush-temp/model-setting': file:projects/model-setting.tgz_typescript@4.4.3 '@rush-temp/model-task': file:projects/model-task.tgz_typescript@4.4.3 '@rush-temp/model-telegram': file:projects/model-telegram.tgz_typescript@4.4.3 @@ -243,8 +243,8 @@ dependencies: '@rush-temp/server-core': file:projects/server-core.tgz '@rush-temp/server-recruit': file:projects/server-recruit.tgz '@rush-temp/server-recruit-resources': file:projects/server-recruit-resources.tgz - '@rush-temp/server-view': file:projects/server-view.tgz - '@rush-temp/server-view-resources': file:projects/server-view-resources.tgz + '@rush-temp/server-task': file:projects/server-task.tgz + '@rush-temp/server-task-resources': file:projects/server-task-resources.tgz '@rush-temp/server-ws': file:projects/server-ws.tgz '@rush-temp/setting': file:projects/setting.tgz '@rush-temp/setting-assets': file:projects/setting-assets.tgz @@ -10588,7 +10588,7 @@ packages: dev: false file:projects/generator.tgz: - resolution: {integrity: sha512-vufLNo3Nd5EZMfZnpDyCgzmtiOxuuOCfdcez1VUXR8EJV+07YGGLKpYcUsJ+hp7vrOMe5/iW0gGun4p42SEL9Q==, tarball: file:projects/generator.tgz} + resolution: {integrity: sha512-Difehi/KDbulPB9s3UOP1fSeLfvWQwpSUr77OnMF31EoCLAXT+9ugFduvlveFdnYCttYKpgGO2bvaxBaH7krdA==, tarball: file:projects/generator.tgz} name: '@rush-temp/generator' version: 0.0.0 dependencies: @@ -10633,7 +10633,7 @@ packages: dev: false file:projects/lead-resources.tgz_476f694f64637160ae71e12ff57815b9: - resolution: {integrity: sha512-o80Jqqi39oV9wTk/nhjlU53bHy92gsqqCQo1nWTsPLlMB+R1nYY5/Yw/GFxsuVHSzbzjmahUnkHIOxltJMSTig==, tarball: file:projects/lead-resources.tgz} + resolution: {integrity: sha512-Bko+x/XDsWFrhZ4EfXCZ8GwS56DMgWA5t2tYGyPF7nlzIPY97oJWPZGc2z1T7olyx0bye+Od9Vk7qmZI3KuBkQ==, tarball: file:projects/lead-resources.tgz} id: file:projects/lead-resources.tgz name: '@rush-temp/lead-resources' version: 0.0.0 @@ -10668,7 +10668,7 @@ packages: dev: false file:projects/lead.tgz: - resolution: {integrity: sha512-fdeirdweHpZ+WcGz5xlKcvue+gtDXhK5WNFINY6XnhVgfUvNsEtEgiWX1RaQ8uSReXbaEok6GGmhsV29SOr1lQ==, tarball: file:projects/lead.tgz} + resolution: {integrity: sha512-M28QADdDu2RRVXMqicIrIf8ithwSkKwdxaOe2HZJrvO+K8wXarOtFKkFf8Hg0Kqjtf6oYkS7RZMQhnwf3Fe94Q==, tarball: file:projects/lead.tgz} name: '@rush-temp/lead' version: 0.0.0 dependencies: @@ -10770,7 +10770,7 @@ packages: dev: false file:projects/model-all.tgz_typescript@4.4.3: - resolution: {integrity: sha512-nbSO6SqE93R4cFPMUkIU19Nn5ZAMItWdQ5+7++7lBjqpJUtUxxgWsIPHjk1wmDmdu4LjPq5F5UruZwQQgu7wJw==, tarball: file:projects/model-all.tgz} + resolution: {integrity: sha512-XyhGIWfnSxUKXSXQ/yfvCx+S5xqBMJ4eko1pDFv0v048sQJy6fefxg3LOLyCDodNzsa5KxGdqvk7Y8H7Izop0g==, tarball: file:projects/model-all.tgz} id: file:projects/model-all.tgz name: '@rush-temp/model-all' version: 0.0.0 @@ -10900,7 +10900,7 @@ packages: dev: false file:projects/model-lead.tgz_typescript@4.4.3: - resolution: {integrity: sha512-qEMZ6aUEiEZgFvIMcqR8lTVkKKiUNM4eAa5OeLjnDmY1TkFF60EJpnE0e2D1SzO8zPdS+cDH+jT9FqRvXtkO9A==, tarball: file:projects/model-lead.tgz} + resolution: {integrity: sha512-3+Wf+/TdMpbuSoiTaI/ga+1KHSsPd1q9MDtpG6i4oAhxt/48aTZnfOV4nt9hrpWy2MmQWVhK9YJFTaKGIgKwOA==, tarball: file:projects/model-lead.tgz} id: file:projects/model-lead.tgz name: '@rush-temp/model-lead' version: 0.0.0 @@ -10921,7 +10921,7 @@ packages: dev: false file:projects/model-recruit.tgz_typescript@4.4.3: - resolution: {integrity: sha512-LgqXtVecQ6ZdlAb4ufvWI+kDIeeMFtm/5mXvUXBbGsmg07rCa4tsqfm9uwecj6TvpaPYC3mlyYv/N316VeKeGA==, tarball: file:projects/model-recruit.tgz} + resolution: {integrity: sha512-wIeXWWUD1Lwg8R43hEvmJzZ/ooN4DWdqv1+2vPFDZU/1xKwlW7Gqu1hZM5qUUVHbLLgMOmHsHDscPfn7tB11UQ==, tarball: file:projects/model-recruit.tgz} id: file:projects/model-recruit.tgz name: '@rush-temp/model-recruit' version: 0.0.0 @@ -11023,10 +11023,10 @@ packages: - typescript dev: false - file:projects/model-server-view.tgz_typescript@4.4.3: - resolution: {integrity: sha512-1LEHcc6xr1A+plRNPtWBHEp8RooarT/XXKfovuqvHugwdjz9ddTHYThxrQcZFuUMya+F1mBgOHdohjYikWZnXQ==, tarball: file:projects/model-server-view.tgz} - id: file:projects/model-server-view.tgz - name: '@rush-temp/model-server-view' + file:projects/model-server-task.tgz_typescript@4.4.3: + resolution: {integrity: sha512-FZRz0sa1wBabVBBZietKGBDDF6vrJzSH6bcWlm8K3OkLl9jHoZlXRjBHIx4f0Vo1DSIPSH++/gULbgNAsd2p1A==, tarball: file:projects/model-server-task.tgz} + id: file:projects/model-server-task.tgz + name: '@rush-temp/model-server-task' version: 0.0.0 dependencies: '@rushstack/heft': 0.41.1 @@ -11339,7 +11339,7 @@ packages: dev: false file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3: - resolution: {integrity: sha512-LFYJVCBzP4R4RpgdxrsiolRiVKAZn2F5mKKb0prXnYIKrRVKLlMkPexB7bnNbg5KG0NBey6WZoxek6/cQ1xk6w==, tarball: file:projects/prod.tgz} + resolution: {integrity: sha512-jgSulZmT4Kq28boQo8BJQrdkcN660EtY7XUH0QWcgGYHDBXFiGfP4eoIxAJL4wtb/JKwKLEkwG+SwTUIuIb7Xw==, tarball: file:projects/prod.tgz} id: file:projects/prod.tgz name: '@rush-temp/prod' version: 0.0.0 @@ -11413,7 +11413,7 @@ packages: dev: false file:projects/recruit-resources.tgz_476f694f64637160ae71e12ff57815b9: - resolution: {integrity: sha512-+AEmp4tNJEHvQatbY5fN1niGYpaIyWMPXbo0QRhUDELdEkm0nhevUfw2Cf44Yj0DroXL+S0YgnXcEI7AtV2QOQ==, tarball: file:projects/recruit-resources.tgz} + resolution: {integrity: sha512-DtOMgqpR+/A09g0gIsXhEy9/GmgTcIEypvvZ53m//Q4YVYXG8/u82bpE6Na74+g4FyQ+S9FaNwMXH2Da1WDnwQ==, tarball: file:projects/recruit-resources.tgz} id: file:projects/recruit-resources.tgz name: '@rush-temp/recruit-resources' version: 0.0.0 @@ -11450,7 +11450,7 @@ packages: dev: false file:projects/recruit.tgz: - resolution: {integrity: sha512-nqrkga8ccMV8sqQ6O4ta9qEdvHkgEChdViELXUXViGldrhz6qi9UAE1aDuVYHgEFRX+eC+OACSME0YpHbibylw==, tarball: file:projects/recruit.tgz} + resolution: {integrity: sha512-vvQ892DoJCDRaRuVWx+DBpuKPtCic0O0PdgPDtbKxl+pWk31MVdEhO6m+ySpqkPsu297ot/D7lpYXcK/775fow==, tarball: file:projects/recruit.tgz} name: '@rush-temp/recruit' version: 0.0.0 dependencies: @@ -11573,9 +11573,9 @@ packages: - supports-color dev: false - file:projects/server-view-resources.tgz: - resolution: {integrity: sha512-8Gg8dO9C0bLtdRQ08F7Yegi8o4Y/VwljPEHRevt7Z6+SpLrpBcbouBgdIaiELK+oXQiPfZWdl3Fwyhd54YJGQQ==, tarball: file:projects/server-view-resources.tgz} - name: '@rush-temp/server-view-resources' + file:projects/server-task-resources.tgz: + resolution: {integrity: sha512-Y2B9G8w4IpTnfIoDV+LtiARLb568CfTKG28VyMc2faS4QUz62f3PLU+ODB8NxwG5f1LsJf8DLrZM8fPRzYdc6w==, tarball: file:projects/server-task-resources.tgz} + name: '@rush-temp/server-task-resources' version: 0.0.0 dependencies: '@rushstack/heft': 0.41.1 @@ -11593,9 +11593,9 @@ packages: - supports-color dev: false - file:projects/server-view.tgz: - resolution: {integrity: sha512-7VfwkR2Yqg0aeuFS+1MWOhCqtuiQBXFqoyxmflQ5+cigwTpJko06NkKnFlGFUW3V+XCxZH4i36PQJod2MXXrng==, tarball: file:projects/server-view.tgz} - name: '@rush-temp/server-view' + file:projects/server-task.tgz: + resolution: {integrity: sha512-qaB/cZSAPKuvTUfBv5wsqD0r/YoQO/hy7rD7WBC0lx2TOWIp0/aacYKVkEltinbYjJzP4gg9cQQNful4Mvpp5Q==, tarball: file:projects/server-task.tgz} + name: '@rush-temp/server-task' version: 0.0.0 dependencies: '@rushstack/heft': 0.41.1 @@ -11641,7 +11641,7 @@ packages: dev: false file:projects/server.tgz: - resolution: {integrity: sha512-V8XWLBzilsZ/5Nuh52ZM8D02XsIGYuOHKhu6q+q7ERPCRm/q3GTMzcZ3WpE3A3ngtFDxHIZJMS314gK50XKM6g==, tarball: file:projects/server.tgz} + resolution: {integrity: sha512-fFYknnDfAOz+iq8INHKSgCjYUkbxqLiHIBM55W8QtmZq0R8hMLEwCcLiyNqL1iCgXKs8sGHf+aMbZcciBNi1Ow==, tarball: file:projects/server.tgz} name: '@rush-temp/server' version: 0.0.0 dependencies: @@ -11673,7 +11673,7 @@ packages: dev: false file:projects/setting-resources.tgz_476f694f64637160ae71e12ff57815b9: - resolution: {integrity: sha512-Ybi5GrbbI/5SMBIe5W9Ub8cwA3wIKPCj98lSJ+Z9YCokpjYn2dGhRJ5LeBKBPu8LDWPfxlrU2Yi17YcHu0xufw==, tarball: file:projects/setting-resources.tgz} + resolution: {integrity: sha512-r/wZZM67R0JwXnUUHxlo5gS1wshjqgf6qJx/fBKfe5d59ZqIXvLD41NhkNBwA7iQsRd+QNmCS4u1fNtCjl20dQ==, tarball: file:projects/setting-resources.tgz} id: file:projects/setting-resources.tgz name: '@rush-temp/setting-resources' version: 0.0.0 @@ -11734,7 +11734,7 @@ packages: dev: false file:projects/task-resources.tgz_e1367da94684b005adf08f025c517b1a: - resolution: {integrity: sha512-8q7drsS3cuBhtj4PIl+/QIH8QDt0fZWk89fH3FxY/3Oog8Xd5dGkBH4YdPHUSyk9k5u9iS/P8OwvR9CKMBmxRg==, tarball: file:projects/task-resources.tgz} + resolution: {integrity: sha512-s/MtNSr/ERDwItbtGtcaE+nnTepUKUsuD2SrtGcpgYUXT3XarZyVaGHC4Q9ol6Ok7RajfDSdAj1ZD8V2LLn3Pw==, tarball: file:projects/task-resources.tgz} id: file:projects/task-resources.tgz name: '@rush-temp/task-resources' version: 0.0.0 @@ -11769,7 +11769,7 @@ packages: dev: false file:projects/task.tgz: - resolution: {integrity: sha512-Yi88o15ExlXV9xqFXzpmi4I5OjnnY7l6SiQasIC7HqKc5/lG4KFvw/dlZHsFnEbRw3Zxa+laq9MejSMqLEzEVw==, tarball: file:projects/task.tgz} + resolution: {integrity: sha512-H61a9iYDCDExaqx08I8pBpSZj2gDyDvF+K+R/QjML1YouYeUa1M1UPpjfz4DHwT7a67TJCasvqJ9nh0/ZNvcDw==, tarball: file:projects/task.tgz} name: '@rush-temp/task' version: 0.0.0 dependencies: diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index ace5b19e73..8eb41ea377 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -18,7 +18,7 @@ services: volumes: - files:/data elastic: - image: 'elasticsearch:7.14.0' + image: 'elasticsearch:7.14.2' command: | /bin/sh -c "./bin/elasticsearch-plugin list | grep -q ingest-attachment || yes | ./bin/elasticsearch-plugin install --silent ingest-attachment; /usr/local/bin/docker-entrypoint.sh eswrapper" diff --git a/dev/generator/package.json b/dev/generator/package.json index 3b1a2fb057..096c7c6c69 100644 --- a/dev/generator/package.json +++ b/dev/generator/package.json @@ -58,7 +58,7 @@ "@anticrm/attachment": "~0.6.1", "minio": "^7.0.19", "@types/pdfkit": "~0.12.3", - "@anticrm/view": "~0.6.0", + "@anticrm/task": "~0.6.0", "jpeg-js": "~0.4.3" } } diff --git a/dev/generator/src/kanban.ts b/dev/generator/src/kanban.ts index e44a86359f..f75e237296 100644 --- a/dev/generator/src/kanban.ts +++ b/dev/generator/src/kanban.ts @@ -1,6 +1,7 @@ -import core, { DoneState, Ref, SpaceWithStates, State, TxOperations } from '@anticrm/core' + +import { Ref, TxOperations } from '@anticrm/core' +import task, { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task' import { findOrUpdate } from './utils' -import view, { Kanban } from '@anticrm/view' export async function createUpdateSpaceKanban (spaceId: Ref, client: TxOperations): Promise[]> { const rawStates = [ @@ -13,7 +14,7 @@ export async function createUpdateSpaceKanban (spaceId: Ref, cl const states: Array> = [] for (const st of rawStates) { const sid = ('generated-' + spaceId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref - await findOrUpdate(client, spaceId, core.class.State, + await findOrUpdate(client, spaceId, task.class.State, sid, { title: st.name, @@ -24,8 +25,8 @@ export async function createUpdateSpaceKanban (spaceId: Ref, cl } const rawDoneStates = [ - { class: core.class.WonState, title: 'Won' }, - { class: core.class.LostState, title: 'Lost' } + { class: task.class.WonState, title: 'Won' }, + { class: task.class.LostState, title: 'Lost' } ] const doneStates: Array> = [] for (const st of rawDoneStates) { @@ -40,7 +41,7 @@ export async function createUpdateSpaceKanban (spaceId: Ref, cl } await findOrUpdate(client, spaceId, - view.class.Kanban, + task.class.Kanban, ('generated-' + spaceId + '.kanban') as Ref, { attachedTo: spaceId, diff --git a/dev/generator/src/recruit.ts b/dev/generator/src/recruit.ts index 8471baffdf..1c978b9a59 100644 --- a/dev/generator/src/recruit.ts +++ b/dev/generator/src/recruit.ts @@ -98,7 +98,7 @@ export async function generateContacts (transactorUrl: string, dbName: string, o const applicant: AttachedData = { number: faker.datatype.number(), - employee: faker.random.arrayElement(emoloyeeIds), + assignee: faker.random.arrayElement(emoloyeeIds), state: faker.random.arrayElement(states), doneState: null } diff --git a/dev/prod/package.json b/dev/prod/package.json index c0431710bb..fb0b94066d 100644 --- a/dev/prod/package.json +++ b/dev/prod/package.json @@ -71,8 +71,8 @@ "@anticrm/contact-assets": "~0.6.0", "@anticrm/server-recruit": "~0.6.1", "@anticrm/server-recruit-resources": "~0.6.0", - "@anticrm/server-view": "~0.6.0", - "@anticrm/server-view-resources": "~0.6.0", + "@anticrm/server-task": "~0.6.0", + "@anticrm/server-task-resources": "~0.6.0", "@anticrm/activity": "~0.6.0", "@anticrm/activity-assets": "~0.6.0", "@anticrm/activity-resources": "~0.6.0", diff --git a/dev/prod/src/platform-dev.ts b/dev/prod/src/platform-dev.ts index 6b3e704b0d..97db2db1d5 100644 --- a/dev/prod/src/platform-dev.ts +++ b/dev/prod/src/platform-dev.ts @@ -19,7 +19,7 @@ import login from '@anticrm/login' import { clientId } from '@anticrm/client' import { serverChunterId } from '@anticrm/server-chunter' import { serverRecruitId } from '@anticrm/server-recruit' -import { serverViewId } from '@anticrm/server-view' +import { serverViewId } from '@anticrm/server-task' import { setMetadata } from '@anticrm/platform' @@ -33,7 +33,7 @@ export function configurePlatformDev() { addLocation(clientId, () => import(/* webpackChunkName: "client-dev" */ '@anticrm/dev-client-resources')) addLocation(serverChunterId, () => import(/* webpackChunkName: "server-chunter" */ '@anticrm/dev-server-chunter-resources')) addLocation(serverRecruitId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-recruit-resources')) - addLocation(serverViewId, () => import(/* webpackChunkName: "server-view" */ '@anticrm/server-view-resources')) + addLocation(serverViewId, () => import(/* webpackChunkName: "server-task" */ '@anticrm/server-task-resources')) // Set devmodel to hook client to be able to present all activity enableDevModel() diff --git a/dev/tool/src/upgrade.ts b/dev/tool/src/upgrade.ts index 3e526d991e..17641b0e21 100644 --- a/dev/tool/src/upgrade.ts +++ b/dev/tool/src/upgrade.ts @@ -69,4 +69,22 @@ export class MigrateClientImpl implements MigrationClient { return { matched: result.matchedCount, updated: result.modifiedCount } } } + + async move (sourceDomain: Domain, query: DocumentQuery, targetDomain: Domain): Promise { + const q = this.translateQuery(query) + const cursor = this.db.collection(sourceDomain).find(q) + const target = this.db.collection(targetDomain) + const result: MigrationResult = { + matched: 0, + updated: 0 + } + let doc: Document | null + while ((doc = await cursor.next()) != null) { + await target.insertOne(doc) + result.matched++ + result.updated++ + } + await this.db.collection(sourceDomain).deleteMany(q) + return result + } } diff --git a/models/all/package.json b/models/all/package.json index f54a4f7eaa..ecbcc3d01a 100644 --- a/models/all/package.json +++ b/models/all/package.json @@ -43,7 +43,7 @@ "@anticrm/model-server-core": "~0.6.0", "@anticrm/model-server-chunter": "~0.6.0", "@anticrm/model-server-recruit": "~0.6.0", - "@anticrm/model-server-view": "~0.6.0", + "@anticrm/model-server-task": "~0.6.0", "@anticrm/model-activity": "~0.6.0", "@anticrm/model-attachment": "~0.6.0", "@anticrm/core": "~0.6.13" diff --git a/models/all/src/index.ts b/models/all/src/index.ts index d8355f56ad..77c3cebf1e 100644 --- a/models/all/src/index.ts +++ b/models/all/src/index.ts @@ -30,7 +30,7 @@ import { createModel as leadModel } from '@anticrm/model-lead' import { createModel as serverCoreModel } from '@anticrm/model-server-core' import { createModel as serverChunterModel } from '@anticrm/model-server-chunter' import { createModel as serverRecruitModel } from '@anticrm/model-server-recruit' -import { createModel as serverViewModel } from '@anticrm/model-server-view' +import { createModel as serverViewModel } from '@anticrm/model-server-task' import { createModel as activityModel } from '@anticrm/model-activity' import { createDemo } from '@anticrm/model-demo' diff --git a/models/core/src/index.ts b/models/core/src/index.ts index db496cd0cd..1b984299af 100644 --- a/models/core/src/index.ts +++ b/models/core/src/index.ts @@ -16,7 +16,7 @@ import { Builder } from '@anticrm/model' import core from './component' import { TAttribute, TClass, TDoc, TMixin, TObj, TType, TTypeString, TTypeBoolean, TTypeTimestamp, TTypeDate, TAttachedDoc, TCollection, TRefTo } from './core' -import { TSpace, TAccount, TState, TDoneState, TWonState, TLostState, TSpaceWithStates, TDocWithState } from './security' +import { TSpace, TAccount } from './security' import { TTx, TTxCreateDoc, TTxMixin, TTxUpdateDoc, TTxCUD, TTxPutBag, TTxRemoveDoc, TTxBulkWrite, TTxCollectionCUD } from './tx' export * from './core' @@ -41,8 +41,6 @@ export function createModel (builder: Builder): void { TTxRemoveDoc, TTxBulkWrite, TSpace, - TDocWithState, - TSpaceWithStates, TAccount, TAttribute, TType, @@ -51,10 +49,6 @@ export function createModel (builder: Builder): void { TTypeTimestamp, TRefTo, TCollection, - TTypeDate, - TState, - TDoneState, - TWonState, - TLostState + TTypeDate ) } diff --git a/models/core/src/security.ts b/models/core/src/security.ts index 5fc6fc4ab9..60519dbcfe 100644 --- a/models/core/src/security.ts +++ b/models/core/src/security.ts @@ -13,15 +13,13 @@ // limitations under the License. // -import type { Account, Arr, Domain, Ref, Space, State, DoneState, WonState, LostState } from '@anticrm/core' +import type { Account, Arr, Ref, Space } from '@anticrm/core' import { DOMAIN_MODEL } from '@anticrm/core' -import { Implements, Model, Prop, TypeBoolean, TypeRef, TypeString } from '@anticrm/model' +import { Model, Prop, TypeBoolean, TypeString } from '@anticrm/model' import type { IntlString } from '@anticrm/platform' import core from './component' import { TDoc } from './core' -export const DOMAIN_STATE = 'state' as Domain - // S P A C E @Model(core.class.Space, core.class.Doc, DOMAIN_MODEL) @@ -42,39 +40,3 @@ export class TSpace extends TDoc implements Space { export class TAccount extends TDoc implements Account { email!: string } - -@Model(core.class.State, core.class.Doc, DOMAIN_STATE) -export class TState extends TDoc implements State { - @Prop(TypeString(), 'Title' as IntlString) - title!: string - - color!: string -} - -@Model(core.class.DoneState, core.class.Doc, DOMAIN_STATE) -export class TDoneState extends TDoc implements DoneState { - @Prop(TypeString(), 'Title' as IntlString) - title!: string -} - -@Model(core.class.WonState, core.class.DoneState, DOMAIN_STATE) -export class TWonState extends TDoneState implements WonState {} - -@Model(core.class.LostState, core.class.DoneState, DOMAIN_STATE) -export class TLostState extends TDoneState implements LostState {} - -@Implements(core.interface.DocWithState) -export class TDocWithState extends TDoc { - @Prop(TypeRef(core.class.State), 'State' as IntlString) - state!: Ref - - @Prop(TypeRef(core.class.DoneState), 'Done Status' as IntlString) - doneState!: Ref | null - - @Prop(TypeString(), 'No.' as IntlString) - number!: number -} - -@Model(core.class.SpaceWithStates, core.class.Space) -export class TSpaceWithStates extends TSpace { -} diff --git a/models/lead/package.json b/models/lead/package.json index c909ad1981..836059396b 100644 --- a/models/lead/package.json +++ b/models/lead/package.json @@ -38,6 +38,9 @@ "@anticrm/model-attachment": "~0.6.0", "@anticrm/lead": "~0.6.0", "@anticrm/lead-resources": "~0.6.0", - "@anticrm/view": "~0.6.0" + "@anticrm/view": "~0.6.0", + "@anticrm/task": "~0.6.0", + "@anticrm/model-task": "~0.6.0", + "@anticrm/workbench": "~0.6.1" } } diff --git a/models/lead/src/index.ts b/models/lead/src/index.ts index cb7c37e720..6753c96a26 100644 --- a/models/lead/src/index.ts +++ b/models/lead/src/index.ts @@ -15,31 +15,29 @@ // // To help typescript locate view plugin properly -import type {} from '@anticrm/view' - import type { Contact } from '@anticrm/contact' -import type { Doc, Domain, FindOptions, Ref } from '@anticrm/core' +import type { Doc, FindOptions, Ref } from '@anticrm/core' +import type { Funnel, Lead } from '@anticrm/lead' +import { createKanban } from '@anticrm/lead' import { Builder, Model, Prop, TypeRef, TypeString, UX } from '@anticrm/model' +import attachment from '@anticrm/model-attachment' import chunter from '@anticrm/model-chunter' import contact from '@anticrm/model-contact' -import core, { TDocWithState, TSpaceWithStates } from '@anticrm/model-core' +import core from '@anticrm/model-core' +import task, { TSpaceWithStates, TTask } from '@anticrm/model-task' import view from '@anticrm/model-view' import workbench from '@anticrm/model-workbench' import type { IntlString } from '@anticrm/platform' -import type { Funnel, Lead } from '@anticrm/lead' -import { createKanban } from '@anticrm/lead' +import type { } from '@anticrm/view' import lead from './plugin' -import attachment from '@anticrm/model-attachment' -export const DOMAIN_LEAD = 'lead' as Domain - -@Model(lead.class.Funnel, core.class.SpaceWithStates) +@Model(lead.class.Funnel, task.class.SpaceWithStates) @UX(lead.string.Funnel, lead.icon.Funnel) export class TFunnel extends TSpaceWithStates implements Funnel {} -@Model(lead.class.Lead, core.class.Doc, DOMAIN_LEAD, [core.interface.DocWithState]) +@Model(lead.class.Lead, task.class.Task) @UX('Lead' as IntlString) -export class TLead extends TDocWithState implements Lead { +export class TLead extends TTask implements Lead { @Prop(TypeString(), 'Title' as IntlString) title!: string @@ -77,7 +75,7 @@ export function createModel (builder: Builder): void { } ] } - }) + }, lead.app.Lead) builder.createDoc(lead.class.Funnel, core.space.Model, { name: 'Funnel', description: 'Default funnel', @@ -93,7 +91,7 @@ export function createModel (builder: Builder): void { options: { lookup: { customer: contact.class.Contact, - state: core.class.State + state: task.class.State } } as FindOptions, // TODO: fix config: [ @@ -108,19 +106,19 @@ export function createModel (builder: Builder): void { builder.createDoc(view.class.Viewlet, core.space.Model, { attachTo: lead.class.Lead, - descriptor: view.viewlet.Kanban, + descriptor: task.viewlet.Kanban, open: lead.component.EditLead, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions options: { lookup: { customer: contact.class.Contact, - state: core.class.State + state: task.class.State } } as FindOptions, // TODO: fix config: ['$lookup.customer', '$lookup.state'] }) - builder.mixin(lead.class.Lead, core.class.Class, view.mixin.KanbanCard, { + builder.mixin(lead.class.Lead, core.class.Class, task.mixin.KanbanCard, { card: lead.component.KanbanCard }) @@ -132,12 +130,12 @@ export function createModel (builder: Builder): void { presenter: lead.component.LeadPresenter }) - builder.createDoc(view.class.Sequence, view.space.Sequence, { + builder.createDoc(task.class.Sequence, task.space.Sequence, { attachedTo: lead.class.Lead, sequence: 0 }) - builder.createDoc(view.class.KanbanTemplateSpace, core.space.Model, { + builder.createDoc(task.class.KanbanTemplateSpace, core.space.Model, { name: 'Funnels', description: 'Manage funnel statuses', members: [], @@ -151,5 +149,5 @@ export function createModel (builder: Builder): void { }).catch((err) => console.error(err)) } -export { default } from './plugin' export { leadOperation } from './migration' +export { default } from './plugin' diff --git a/models/lead/src/migration.ts b/models/lead/src/migration.ts index 98577289eb..de27373f34 100644 --- a/models/lead/src/migration.ts +++ b/models/lead/src/migration.ts @@ -17,7 +17,7 @@ import { Doc, TxOperations } from '@anticrm/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' import core from '@anticrm/model-core' -import view from '@anticrm/model-view' +import task from '@anticrm/model-task' import { createKanban } from '@anticrm/lead' import lead from './plugin' @@ -29,7 +29,7 @@ export const leadOperation: MigrateOperation = { console.log('Lead: Performing model upgrades') const ops = new TxOperations(client, core.account.System) - if (await client.findOne(view.class.Kanban, { attachedTo: lead.space.DefaultFunnel }) === undefined) { + if (await client.findOne(task.class.Kanban, { attachedTo: lead.space.DefaultFunnel }) === undefined) { console.info('Create kanban for default funnel.') await createKanban(lead.space.DefaultFunnel, async (_class, space, data, id) => { const doc = await ops.findOne(_class, { _id: id }) @@ -43,6 +43,17 @@ export const leadOperation: MigrateOperation = { console.log('Lead: => default funnel Kanban is ok') } + if (await client.findOne(task.class.Sequence, { attachedTo: lead.class.Lead }) === undefined) { + console.info('Create sequence for default task project.') + // We need to create sequence + await ops.createDoc(task.class.Sequence, task.space.Sequence, { + attachedTo: lead.class.Lead, + sequence: 0 + }) + } else { + console.log('Task: => sequence is ok') + } + const outdatedLeads = (await client.findAll(lead.class.Lead, {})) .filter((x) => x.doneState === undefined) diff --git a/models/lead/src/plugin.ts b/models/lead/src/plugin.ts index 020d25305f..5ccd96af8f 100644 --- a/models/lead/src/plugin.ts +++ b/models/lead/src/plugin.ts @@ -15,13 +15,18 @@ // import type { Ref, Space } from '@anticrm/core' -import type { IntlString } from '@anticrm/platform' -import { mergeIds } from '@anticrm/platform' import { leadId } from '@anticrm/lead' import lead from '@anticrm/lead-resources/src/plugin' +import type { IntlString } from '@anticrm/platform' +import { mergeIds } from '@anticrm/platform' +import '@anticrm/task' import type { AnyComponent } from '@anticrm/ui' +import { Application } from '@anticrm/workbench' export default mergeIds(leadId, lead, { + app: { + Lead: '' as Ref + }, string: { Funnel: '' as IntlString, Funnels: '' as IntlString, diff --git a/models/recruit/package.json b/models/recruit/package.json index 8ec0746e36..9611e808ba 100644 --- a/models/recruit/package.json +++ b/models/recruit/package.json @@ -39,6 +39,9 @@ "@anticrm/chunter": "~0.6.0", "@anticrm/model-attachment": "~0.6.0", "@anticrm/model-chunter": "~0.6.0", - "@anticrm/view": "~0.6.0" + "@anticrm/view": "~0.6.0", + "@anticrm/task": "~0.6.0", + "@anticrm/model-task": "~0.6.0", + "@anticrm/workbench": "~0.6.1" } } diff --git a/models/recruit/src/index.ts b/models/recruit/src/index.ts index fd12b63967..002598335c 100644 --- a/models/recruit/src/index.ts +++ b/models/recruit/src/index.ts @@ -14,21 +14,20 @@ // import type { Employee } from '@anticrm/contact' -import { Doc, Domain, FindOptions, Ref, Timestamp } from '@anticrm/core' -import { Builder, Model, Prop, TypeBoolean, TypeDate, TypeRef, TypeString, UX, Collection } from '@anticrm/model' +import { Doc, FindOptions, Ref, Timestamp } from '@anticrm/core' +import { Builder, Collection, Model, Prop, TypeBoolean, TypeDate, TypeRef, TypeString, UX } from '@anticrm/model' +import attachment from '@anticrm/model-attachment' import chunter from '@anticrm/model-chunter' import contact, { TPerson } from '@anticrm/model-contact' -import core, { TAttachedDoc, TDocWithState, TSpace, TSpaceWithStates } from '@anticrm/model-core' +import core, { TSpace } from '@anticrm/model-core' +import task, { TSpaceWithStates, TTask } from '@anticrm/model-task' import view from '@anticrm/model-view' import workbench from '@anticrm/model-workbench' import type { IntlString } from '@anticrm/platform' import { Applicant, Candidate, Candidates, Vacancy } from '@anticrm/recruit' import recruit from './plugin' -import attachment from '@anticrm/model-attachment' -export const DOMAIN_RECRUIT = 'recruit' as Domain - -@Model(recruit.class.Vacancy, core.class.SpaceWithStates) +@Model(recruit.class.Vacancy, task.class.SpaceWithStates) @UX(recruit.string.Vacancy, recruit.icon.Vacancy) export class TVacancy extends TSpaceWithStates implements Vacancy { @Prop(TypeString(), 'Full description' as IntlString) @@ -76,9 +75,9 @@ export class TCandidate extends TPerson implements Candidate { source?: string } -@Model(recruit.class.Applicant, core.class.AttachedDoc, DOMAIN_RECRUIT, [core.interface.DocWithState]) +@Model(recruit.class.Applicant, task.class.Task) @UX('Application' as IntlString, recruit.icon.RecruitApplication, 'APP' as IntlString) -export class TApplicant extends TAttachedDoc implements Applicant { +export class TApplicant extends TTask implements Applicant { // We need to declare, to provide property with label @Prop(TypeRef(recruit.class.Candidate), 'Candidate' as IntlString) declare attachedTo: Ref @@ -90,12 +89,7 @@ export class TApplicant extends TAttachedDoc implements Applicant { comments?: number @Prop(TypeRef(contact.class.Employee), 'Assigned recruiter' as IntlString) - employee!: Ref | null - - // We need these to make typescript happy. - declare state: TDocWithState['state'] - declare doneState: TDocWithState['doneState'] - declare number: TDocWithState['number'] + declare assignee: Ref | null } export function createModel (builder: Builder): void { @@ -136,7 +130,7 @@ export function createModel (builder: Builder): void { } ] } - }) + }, recruit.app.Recruit) builder.createDoc( recruit.class.Candidates, core.space.Model, @@ -179,7 +173,7 @@ export function createModel (builder: Builder): void { options: { lookup: { attachedTo: recruit.class.Candidate, - state: core.class.State + state: task.class.State } } as FindOptions, // TODO: fix config: [ @@ -196,19 +190,19 @@ export function createModel (builder: Builder): void { builder.createDoc(view.class.Viewlet, core.space.Model, { attachTo: recruit.class.Applicant, - descriptor: view.viewlet.Kanban, + descriptor: task.viewlet.Kanban, open: recruit.component.EditCandidate, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions options: { lookup: { attachedTo: recruit.class.Candidate, - state: core.class.State + state: task.class.State } } as FindOptions, // TODO: fix config: ['$lookup.attachedTo', '$lookup.state', '$lookup.attachedTo.city', '$lookup.attachedTo.channels'] }) - builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.KanbanCard, { + builder.mixin(recruit.class.Applicant, core.class.Class, task.mixin.KanbanCard, { card: recruit.component.KanbanCard }) @@ -236,12 +230,17 @@ export function createModel (builder: Builder): void { action: recruit.action.CreateApplication }) - builder.createDoc(view.class.Sequence, view.space.Sequence, { + builder.createDoc(view.class.ActionTarget, core.space.Model, { + target: recruit.class.Candidate, + action: task.action.CreateTask + }) + + builder.createDoc(task.class.Sequence, task.space.Sequence, { attachedTo: recruit.class.Applicant, sequence: 0 }) - builder.createDoc(view.class.KanbanTemplateSpace, core.space.Model, { + builder.createDoc(task.class.KanbanTemplateSpace, core.space.Model, { name: 'Vacancies', description: 'Manage vacancy statuses', members: [], @@ -250,6 +249,5 @@ export function createModel (builder: Builder): void { }, recruit.space.VacancyTemplates) } -export { default } from './plugin' - export { recruitOperation } from './migration' +export { default } from './plugin' diff --git a/models/recruit/src/plugin.ts b/models/recruit/src/plugin.ts index 0e1d12cd3c..59464c0f4c 100644 --- a/models/recruit/src/plugin.ts +++ b/models/recruit/src/plugin.ts @@ -20,8 +20,13 @@ import { recruitId } from '@anticrm/recruit' import recruit from '@anticrm/recruit-resources/src/plugin' import type { AnyComponent } from '@anticrm/ui' import type { Action } from '@anticrm/view' +import { Application } from '@anticrm/workbench' +import '@anticrm/task' export default mergeIds(recruitId, recruit, { + app: { + Recruit: '' as Ref + }, action: { CreateApplication: '' as Ref }, diff --git a/models/server-view/.eslintrc.js b/models/server-task/.eslintrc.js similarity index 100% rename from models/server-view/.eslintrc.js rename to models/server-task/.eslintrc.js diff --git a/models/server-view/.npmignore b/models/server-task/.npmignore similarity index 100% rename from models/server-view/.npmignore rename to models/server-task/.npmignore diff --git a/models/server-view/config/rig.json b/models/server-task/config/rig.json similarity index 100% rename from models/server-view/config/rig.json rename to models/server-task/config/rig.json diff --git a/models/server-view/package.json b/models/server-task/package.json similarity index 92% rename from models/server-view/package.json rename to models/server-task/package.json index ec8cb55781..4c8f3f30f0 100644 --- a/models/server-view/package.json +++ b/models/server-task/package.json @@ -1,5 +1,5 @@ { - "name": "@anticrm/model-server-view", + "name": "@anticrm/model-server-task", "version": "0.6.0", "main": "lib/index.js", "author": "Anticrm Platform Contributors", @@ -28,7 +28,7 @@ "@anticrm/core": "~0.6.11", "@anticrm/model": "~0.6.0", "@anticrm/platform": "~0.6.5", - "@anticrm/server-view": "~0.6.0", + "@anticrm/server-task": "~0.6.0", "@anticrm/server-core": "~0.6.0" } } diff --git a/models/server-view/src/index.ts b/models/server-task/src/index.ts similarity index 90% rename from models/server-view/src/index.ts rename to models/server-task/src/index.ts index 5b4c1a9265..60b8ed850b 100644 --- a/models/server-view/src/index.ts +++ b/models/server-task/src/index.ts @@ -18,10 +18,10 @@ import { Builder } from '@anticrm/model' import serverCore from '@anticrm/server-core' import core from '@anticrm/core' -import serverView from '@anticrm/server-view' +import serverTask from '@anticrm/server-task' export function createModel (builder: Builder): void { builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverView.trigger.OnDocWithState + trigger: serverTask.trigger.OnTask }) } diff --git a/models/server-view/tsconfig.json b/models/server-task/tsconfig.json similarity index 100% rename from models/server-view/tsconfig.json rename to models/server-task/tsconfig.json diff --git a/models/task/src/index.ts b/models/task/src/index.ts index e87c9ec885..166338a7df 100644 --- a/models/task/src/index.ts +++ b/models/task/src/index.ts @@ -19,27 +19,77 @@ import type {} from '@anticrm/view' import attachment from '@anticrm/model-attachment' import type { Employee } from '@anticrm/contact' import contact from '@anticrm/contact' -import type { Doc, DocWithState, Domain, FindOptions, Ref } from '@anticrm/core' -import { Builder, Model, Prop, TypeRef, TypeString, UX } from '@anticrm/model' +import { Arr, Class, Doc, Domain, DOMAIN_MODEL, FindOptions, Ref, Space } from '@anticrm/core' +import { Builder, Collection, Mixin, Model, Prop, TypeRef, TypeString, UX } from '@anticrm/model' import chunter from '@anticrm/model-chunter' -import core, { TDoc, TSpaceWithStates } from '@anticrm/model-core' +import core, { TAttachedDoc, TClass, TDoc, TSpace } from '@anticrm/model-core' import view from '@anticrm/model-view' import workbench from '@anticrm/model-workbench' import type { IntlString } from '@anticrm/platform' -import type { Project, Task } from '@anticrm/task' +import type { Kanban, KanbanCard, Project, State, Issue, Sequence, DoneState, WonState, LostState, KanbanTemplateSpace, StateTemplate, DoneStateTemplate, WonStateTemplate, LostStateTemplate, KanbanTemplate, Task } from '@anticrm/task' import { createProjectKanban } from '@anticrm/task' import task from './plugin' +import { AnyComponent } from '@anticrm/ui' -@Model(task.class.Project, core.class.SpaceWithStates) +export { default } from './plugin' + +export const DOMAIN_TASK = 'task' as Domain +export const DOMAIN_STATE = 'state' as Domain +export const DOMAIN_KANBAN = 'kanban' as Domain +@Model(task.class.State, core.class.Doc, DOMAIN_STATE) +export class TState extends TDoc implements State { + @Prop(TypeString(), 'Title' as IntlString) + title!: string + + color!: string +} + +@Model(task.class.DoneState, core.class.Doc, DOMAIN_STATE) +export class TDoneState extends TDoc implements DoneState { + @Prop(TypeString(), 'Title' as IntlString) + title!: string +} + +@Model(task.class.WonState, task.class.DoneState, DOMAIN_STATE) +export class TWonState extends TDoneState implements WonState {} + +@Model(task.class.LostState, task.class.DoneState, DOMAIN_STATE) +export class TLostState extends TDoneState implements LostState {} + +/** + * @public + * + * No domain is specified, since pure Tasks could not exists + */ +@Model(task.class.Task, core.class.AttachedDoc, DOMAIN_TASK) +export class TTask extends TAttachedDoc implements Task { + @Prop(TypeRef(task.class.State), 'State' as IntlString) + state!: Ref + + @Prop(TypeRef(task.class.DoneState), 'Done Status' as IntlString) + doneState!: Ref | null + + @Prop(TypeString(), 'No.' as IntlString) + number!: number + + // @Prop(TypeRef(contact.class.Employee), 'Assignee' as IntlString) + assignee!: Ref | null +} + +@Model(task.class.SpaceWithStates, core.class.Space) +export class TSpaceWithStates extends TSpace { +} + +@Model(task.class.Project, task.class.SpaceWithStates) @UX('Project' as IntlString, task.icon.Task) export class TProject extends TSpaceWithStates implements Project {} -@Model(task.class.Task, core.class.Doc, 'task' as Domain, [core.interface.DocWithState]) -@UX('Task' as IntlString, task.icon.Task, 'TASK' as IntlString) -export class TTask extends TDoc implements Task { - declare number: DocWithState['number'] - declare state: DocWithState['state'] - declare doneState: DocWithState['doneState'] +@Model(task.class.Issue, task.class.Task, DOMAIN_TASK) +@UX('Task' as IntlString, task.icon.Task, 'Task' as IntlString) +export class TIssue extends TTask implements Issue { + // We need to declare, to provide property with label + @Prop(TypeRef(core.class.Doc), 'Parent' as IntlString) + declare attachedTo: Ref @Prop(TypeString(), 'Name' as IntlString) name!: string @@ -47,9 +97,6 @@ export class TTask extends TDoc implements Task { @Prop(TypeString(), 'Description' as IntlString) description!: string - @Prop(TypeRef(contact.class.Employee), 'Assignee' as IntlString) - assignee!: Ref | null - @Prop(TypeString(), 'Comments' as IntlString) comments!: number @@ -58,13 +105,93 @@ export class TTask extends TDoc implements Task { @Prop(TypeString(), 'Labels' as IntlString) labels!: string + + @Prop(TypeRef(contact.class.Employee), 'Assignee' as IntlString) + declare assignee: Ref | null +} + +@Mixin(task.mixin.KanbanCard, core.class.Class) +export class TKanbanCard extends TClass implements KanbanCard { + card!: AnyComponent +} + +@Model(task.class.Kanban, core.class.Doc, DOMAIN_KANBAN) +export class TKanban extends TDoc implements Kanban { + states!: Arr> + doneStates!: Arr> + attachedTo!: Ref + order!: Arr> +} + +@Model(task.class.KanbanTemplateSpace, core.class.Space, DOMAIN_MODEL) +export class TKanbanTemplateSpace extends TSpace implements KanbanTemplateSpace { + icon!: AnyComponent +} + +@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN) +export class TStateTemplate extends TAttachedDoc implements StateTemplate { + @Prop(TypeString(), 'Title' as IntlString) + title!: string + + @Prop(TypeString(), 'Color' as IntlString) + color!: string +} + +@Model(task.class.DoneStateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN) +export class TDoneStateTemplate extends TAttachedDoc implements DoneStateTemplate { + @Prop(TypeString(), 'Title' as IntlString) + title!: string +} + +@Model(task.class.WonStateTemplate, task.class.DoneStateTemplate, DOMAIN_KANBAN) +export class TWonStateTemplate extends TDoneStateTemplate implements WonStateTemplate {} + +@Model(task.class.LostStateTemplate, task.class.DoneStateTemplate, DOMAIN_KANBAN) +export class TLostStateTemplate extends TDoneStateTemplate implements LostStateTemplate {} + +@Model(task.class.KanbanTemplate, core.class.Doc, DOMAIN_KANBAN) +export class TKanbanTemplate extends TDoc implements KanbanTemplate { + @Prop(TypeString(), 'Title' as IntlString) + title!: string + + states!: Arr> + doneStates!: Arr> + + @Prop(Collection(task.class.StateTemplate), 'States' as IntlString) + statesC!: number + + @Prop(Collection(task.class.DoneStateTemplate), 'Done States' as IntlString) + doneStatesC!: number +} + +@Model(task.class.Sequence, core.class.Doc, DOMAIN_KANBAN) +export class TSequence extends TDoc implements Sequence { + attachedTo!: Ref> + sequence!: number } export function createModel (builder: Builder): void { - builder.createModel(TProject, TTask) + builder.createModel( + TState, + TDoneState, + TWonState, + TLostState, + TKanbanCard, + TKanban, + TKanbanTemplateSpace, + TStateTemplate, + TDoneStateTemplate, + TWonStateTemplate, + TLostStateTemplate, + TKanbanTemplate, + TSequence, + TTask, + TSpaceWithStates, + TProject, + TIssue) builder.mixin(task.class.Project, core.class.Class, workbench.mixin.SpaceView, { view: { - class: task.class.Task, + class: task.class.Issue, createItemDialog: task.component.CreateTask } }) @@ -86,7 +213,7 @@ export function createModel (builder: Builder): void { }, task.app.Tasks) builder.createDoc(view.class.Viewlet, core.space.Model, { - attachTo: task.class.Task, + attachTo: task.class.Issue, descriptor: view.viewlet.Table, open: task.component.EditTask, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions @@ -105,34 +232,38 @@ export function createModel (builder: Builder): void { ] }) - builder.mixin(task.class.Task, core.class.Class, view.mixin.AttributePresenter, { + builder.mixin(task.class.Issue, core.class.Class, view.mixin.AttributePresenter, { presenter: task.component.TaskPresenter }) - builder.mixin(task.class.Task, core.class.Class, view.mixin.ObjectEditor, { + builder.mixin(task.class.Issue, core.class.Class, view.mixin.ObjectEditor, { editor: task.component.EditTask }) - builder.createDoc(view.class.Sequence, view.space.Sequence, { - attachedTo: task.class.Task, + builder.createDoc(task.class.Sequence, task.space.Sequence, { + attachedTo: task.class.Issue, sequence: 0 }) builder.createDoc(view.class.Viewlet, core.space.Model, { - attachTo: task.class.Task, - descriptor: view.viewlet.Kanban, + attachTo: task.class.Issue, + descriptor: task.viewlet.Kanban, open: task.component.EditTask, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions options: { lookup: { assignee: contact.class.Employee, - state: core.class.State + state: task.class.State + // attachedTo: core.class.Doc } } as FindOptions, // TODO: fix - config: ['$lookup.attachedTo', '$lookup.state'] + config: [ + // '$lookup.attachedTo', + '$lookup.state', + '$lookup.assignee'] }) - builder.mixin(task.class.Task, core.class.Class, view.mixin.KanbanCard, { + builder.mixin(task.class.Issue, core.class.Class, task.mixin.KanbanCard, { card: task.component.KanbanCard }) @@ -143,7 +274,7 @@ export function createModel (builder: Builder): void { members: [] }, task.space.TasksPublic) - builder.createDoc(view.class.KanbanTemplateSpace, core.space.Model, { + builder.createDoc(task.class.KanbanTemplateSpace, core.space.Model, { name: 'Projects', description: 'Manage project statuses', members: [], @@ -155,6 +286,44 @@ export function createModel (builder: Builder): void { builder.createDoc(_class, space, data, id) return await Promise.resolve() }).catch((err) => console.error(err)) + + builder.createDoc(view.class.Action, core.space.Model, { + label: 'Create task' as IntlString, + icon: task.icon.Task, + action: task.actionImpl.CreateTask + }, task.action.CreateTask) + + builder.createDoc(view.class.Action, core.space.Model, { + label: 'Edit Statuses' as IntlString, + icon: view.icon.MoreH, + action: task.actionImpl.EditStatuses + }, task.action.EditStatuses) + + builder.createDoc(view.class.ActionTarget, core.space.Model, { + target: task.class.SpaceWithStates, + action: task.action.EditStatuses + }) + + builder.mixin(task.class.State, core.class.Class, view.mixin.AttributeEditor, { + editor: task.component.StateEditor + }) + + builder.mixin(task.class.State, core.class.Class, view.mixin.AttributePresenter, { + presenter: task.component.StatePresenter + }) + + builder.createDoc(view.class.ViewletDescriptor, core.space.Model, { + label: 'Kanban' as IntlString, + icon: task.icon.Kanban, + component: task.component.KanbanView + }, task.viewlet.Kanban) + + builder.createDoc(core.class.Space, core.space.Model, { + name: 'Sequences', + description: 'Internal space to store sequence numbers', + members: [], + private: false + }, task.space.Sequence) } export { taskOperation } from './migration' diff --git a/models/task/src/migration.ts b/models/task/src/migration.ts index 74a6f6fc5b..0e29308b9f 100644 --- a/models/task/src/migration.ts +++ b/models/task/src/migration.ts @@ -13,32 +13,64 @@ // limitations under the License. // -import { Doc, TxOperations } from '@anticrm/core' -import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' +import { Class, Doc, Domain, DOMAIN_TX, Ref, TxCUD, TxOperations } from '@anticrm/core' +import { MigrateOperation, MigrateUpdate, MigrationClient, MigrationResult, MigrationUpgradeClient } from '@anticrm/model' import core from '@anticrm/model-core' -import view from '@anticrm/model-view' import { createProjectKanban } from '@anticrm/task' +import { DOMAIN_TASK, DOMAIN_STATE, DOMAIN_KANBAN } from '.' import task from './plugin' +function logInfo (msg: string, result: MigrationResult): void { + if (result.updated > 0) { + console.log(`Tasks: Migrate ${msg} ${result.updated}`) + } +} +async function migrateClass (client: MigrationClient, domain: Domain, from: Ref>, to: Ref>, extraOps: MigrateUpdate = {}, txExtraOps: MigrateUpdate> = {}): Promise { + logInfo(`Migrate ${from} => ${to}: `, + await client.update(domain, { _class: from }, { ...extraOps, _class: to })) + logInfo(`Migrate ${from} => ${to} Transactions`, + await client.update>(DOMAIN_TX, { objectClass: from }, { ...txExtraOps, objectClass: to })) +} + export const taskOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { + // Since we should not have Task class instances, we convert them all to Issue. + await migrateClass(client, DOMAIN_TASK, task.class.Task, task.class.Issue) + await migrateClass(client, DOMAIN_STATE, 'core:class:State' as Ref>, task.class.State) + await migrateClass(client, DOMAIN_KANBAN, 'view:class:Kanban' as Ref>, task.class.Kanban) + await migrateClass(client, DOMAIN_KANBAN, 'view:class:Sequence' as Ref>, task.class.Sequence, { space: task.space.Sequence }, { objectSpace: task.space.Sequence }) + // Update attached to for task + await client.update(DOMAIN_KANBAN, { _class: task.class.Sequence, attachedTo: task.class.Task }, { attachedTo: task.class.Issue }) + + await migrateClass(client, DOMAIN_KANBAN, 'view:class:KanbanTemplate' as Ref>, task.class.KanbanTemplate) + await migrateClass(client, DOMAIN_KANBAN, 'view:class:StateTemplate' as Ref>, task.class.StateTemplate) + await migrateClass(client, DOMAIN_KANBAN, 'view:class:DoneStateTemplate' as Ref>, task.class.DoneStateTemplate) + await migrateClass(client, DOMAIN_KANBAN, 'view:class:LostStateTemplate' as Ref>, task.class.LostStateTemplate) + + await client.move('recruit' as Domain, { + _class: 'recruit:class:Applicant' as Ref> + }, DOMAIN_TASK) + + await client.move('lead' as Domain, { + _class: 'lead:class:Lead' as Ref> + }, DOMAIN_TASK) }, async upgrade (client: MigrationUpgradeClient): Promise { console.log('Task: Performing model upgrades') const ops = new TxOperations(client, core.account.System) - if (await client.findOne(view.class.Sequence, { attachedTo: task.class.Task }) === undefined) { + if (await client.findOne(task.class.Sequence, { attachedTo: task.class.Issue }) === undefined) { console.info('Create sequence for default task project.') // We need to create sequence - await ops.createDoc(view.class.Sequence, view.space.Sequence, { - attachedTo: task.class.Task, + await ops.createDoc(task.class.Sequence, task.space.Sequence, { + attachedTo: task.class.Issue, sequence: 0 }) } else { console.log('Task: => sequence is ok') } - if (await client.findOne(view.class.Kanban, { attachedTo: task.space.TasksPublic }) === undefined) { + if (await client.findOne(task.class.Kanban, { attachedTo: task.space.TasksPublic }) === undefined) { console.info('Create kanban for default task project.') await createProjectKanban(task.space.TasksPublic, async (_class, space, data, id) => { const doc = await ops.findOne(_class, { _id: id }) @@ -52,6 +84,33 @@ export const taskOperation: MigrateOperation = { console.log('Task: => public project Kanban is ok') } + console.log('View: Performing model upgrades') + + const kanbans = (await client.findAll(task.class.Kanban, {})) + .filter((kanban) => kanban.doneStates == null) + + await Promise.all( + kanbans + .map(async (kanban) => { + console.log(`Updating kanban: ${kanban._id}`) + try { + const doneStates = await Promise.all([ + ops.createDoc(task.class.WonState, kanban.space, { + title: 'Won' + }), + ops.createDoc(task.class.LostState, kanban.space, { + title: 'Lost' + }) + ]) + + await ops.updateDoc(kanban._class, kanban.space, kanban._id, { + doneStates + }) + } catch (e) { + console.error(e) + } + })) + const outdatedTasks = (await client.findAll(task.class.Task, {})) .filter((x) => x.doneState === undefined) diff --git a/models/task/src/plugin.ts b/models/task/src/plugin.ts index 4dcf761814..b141478d70 100644 --- a/models/task/src/plugin.ts +++ b/models/task/src/plugin.ts @@ -14,17 +14,26 @@ // limitations under the License. // -import type { Ref, Space } from '@anticrm/core' -import type { IntlString } from '@anticrm/platform' +import type { Doc, Ref, Space } from '@anticrm/core' +import type { IntlString, Resource } from '@anticrm/platform' import { mergeIds } from '@anticrm/platform' import task, { taskId } from '@anticrm/task' import type { AnyComponent } from '@anticrm/ui' import { Application } from '@anticrm/workbench' +import type { Action } from '@anticrm/view' export default mergeIds(taskId, task, { app: { Tasks: '' as Ref }, + action: { + CreateTask: '' as Ref, + EditStatuses: '' as Ref + }, + actionImpl: { + CreateTask: '' as Resource<(object: Doc) => Promise>, + EditStatuses: '' as Resource<(object: Doc) => Promise> + }, component: { ProjectView: '' as AnyComponent, CreateProject: '' as AnyComponent, @@ -32,7 +41,10 @@ export default mergeIds(taskId, task, { EditTask: '' as AnyComponent, TaskPresenter: '' as AnyComponent, KanbanCard: '' as AnyComponent, - TemplatesIcon: '' as AnyComponent + TemplatesIcon: '' as AnyComponent, + StatePresenter: '' as AnyComponent, + StateEditor: '' as AnyComponent, + KanbanView: '' as AnyComponent }, string: { Task: '' as IntlString, diff --git a/models/view/src/index.ts b/models/view/src/index.ts index e7138e85f4..769c715b4c 100644 --- a/models/view/src/index.ts +++ b/models/view/src/index.ts @@ -13,36 +13,15 @@ // limitations under the License. // -import type { IntlString, Asset, Resource } from '@anticrm/platform' -import type { Ref, Class, Space, Doc, Arr, Domain, State, DoneState } from '@anticrm/core' +import type { Class, Doc, Ref, Space } from '@anticrm/core' import { DOMAIN_MODEL } from '@anticrm/core' -import { Model, Mixin, Builder, Prop, Collection, TypeString } from '@anticrm/model' +import { Builder, Mixin, Model } from '@anticrm/model' +import core, { TClass, TDoc } from '@anticrm/model-core' +import type { Asset, IntlString, Resource } from '@anticrm/platform' import type { AnyComponent } from '@anticrm/ui' -import type { - ViewletDescriptor, - Viewlet, - AttributeEditor, - AttributePresenter, - KanbanCard, - ObjectEditor, - Action, - ActionTarget, - Kanban, - Sequence, - KanbanTemplateSpace, - KanbanTemplate, - StateTemplate, - DoneStateTemplate, - WonStateTemplate, - LostStateTemplate -} from '@anticrm/view' - -import core, { TDoc, TClass, TSpace, TAttachedDoc } from '@anticrm/model-core' - +import type { Action, ActionTarget, AttributeEditor, AttributePresenter, ObjectEditor, Viewlet, ViewletDescriptor } from '@anticrm/view' import view from './plugin' -const DOMAIN_KANBAN = 'kanban' as Domain - @Mixin(view.mixin.AttributeEditor, core.class.Class) export class TAttributeEditor extends TClass implements AttributeEditor { editor!: AnyComponent @@ -53,11 +32,6 @@ export class TAttributePresenter extends TClass implements AttributePresenter { presenter!: AnyComponent } -@Mixin(view.mixin.KanbanCard, core.class.Class) -export class TKanbanCard extends TClass implements KanbanCard { - card!: AnyComponent -} - @Mixin(view.mixin.ObjectEditor, core.class.Class) export class TObjectEditor extends TClass implements ObjectEditor { editor!: AnyComponent @@ -90,80 +64,8 @@ export class TActionTarget extends TDoc implements ActionTarget { action!: Ref } -@Model(view.class.Kanban, core.class.Doc, DOMAIN_KANBAN) -export class TKanban extends TDoc implements Kanban { - states!: Arr> - doneStates!: Arr> - attachedTo!: Ref - order!: Arr> -} - -@Model(view.class.KanbanTemplateSpace, core.class.Space, DOMAIN_MODEL) -export class TKanbanTemplateSpace extends TSpace implements KanbanTemplateSpace { - icon!: AnyComponent -} - -@Model(view.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN) -export class TStateTemplate extends TAttachedDoc implements StateTemplate { - @Prop(TypeString(), 'Title' as IntlString) - title!: string - - @Prop(TypeString(), 'Color' as IntlString) - color!: string -} - -@Model(view.class.DoneStateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN) -export class TDoneStateTemplate extends TAttachedDoc implements DoneStateTemplate { - @Prop(TypeString(), 'Title' as IntlString) - title!: string -} - -@Model(view.class.WonStateTemplate, view.class.DoneStateTemplate, DOMAIN_KANBAN) -export class TWonStateTemplate extends TDoneStateTemplate implements WonStateTemplate {} - -@Model(view.class.LostStateTemplate, view.class.DoneStateTemplate, DOMAIN_KANBAN) -export class TLostStateTemplate extends TDoneStateTemplate implements LostStateTemplate {} - -@Model(view.class.KanbanTemplate, core.class.Doc, DOMAIN_KANBAN) -export class TKanbanTemplate extends TDoc implements KanbanTemplate { - @Prop(TypeString(), 'Title' as IntlString) - title!: string - - states!: Arr> - doneStates!: Arr> - - @Prop(Collection(view.class.StateTemplate), 'States' as IntlString) - statesC!: number - - @Prop(Collection(view.class.DoneStateTemplate), 'Done States' as IntlString) - doneStatesC!: number -} - -@Model(view.class.Sequence, core.class.Doc, DOMAIN_KANBAN) -export class TSequence extends TDoc implements Sequence { - attachedTo!: Ref> - sequence!: number -} - export function createModel (builder: Builder): void { - builder.createModel( - TAttributeEditor, - TAttributePresenter, - TKanbanCard, - TObjectEditor, - TViewletDescriptor, - TViewlet, - TAction, - TActionTarget, - TKanban, - TSequence, - TKanbanTemplateSpace, - TStateTemplate, - TDoneStateTemplate, - TWonStateTemplate, - TLostStateTemplate, - TKanbanTemplate - ) + builder.createModel(TAttributeEditor, TAttributePresenter, TObjectEditor, TViewletDescriptor, TViewlet, TAction, TActionTarget) builder.mixin(core.class.TypeString, core.class.Class, view.mixin.AttributeEditor, { editor: view.component.StringEditor @@ -193,46 +95,17 @@ export function createModel (builder: Builder): void { editor: view.component.DateEditor }) - builder.mixin(core.class.State, core.class.Class, view.mixin.AttributeEditor, { - editor: view.component.StateEditor - }) + builder.createDoc(view.class.ViewletDescriptor, core.space.Model, { + label: 'Table' as IntlString, + icon: view.icon.Table, + component: view.component.TableView + }, view.viewlet.Table) - builder.mixin(core.class.State, core.class.Class, view.mixin.AttributePresenter, { - presenter: view.component.StatePresenter - }) - - builder.createDoc( - view.class.ViewletDescriptor, - core.space.Model, - { - label: 'Table' as IntlString, - icon: view.icon.Table, - component: view.component.TableView - }, - view.viewlet.Table - ) - - builder.createDoc( - view.class.ViewletDescriptor, - core.space.Model, - { - label: 'Kanban' as IntlString, - icon: view.icon.Kanban, - component: view.component.KanbanView - }, - view.viewlet.Kanban - ) - - builder.createDoc( - view.class.Action, - core.space.Model, - { - label: 'Delete' as IntlString, - icon: view.icon.Delete, - action: view.actionImpl.Delete - }, - view.action.Delete - ) + builder.createDoc(view.class.Action, core.space.Model, { + label: 'Delete' as IntlString, + icon: view.icon.Delete, + action: view.actionImpl.Delete + }, view.action.Delete) builder.createDoc(view.class.ActionTarget, core.space.Model, { target: core.class.Doc, @@ -249,13 +122,6 @@ export function createModel (builder: Builder): void { target: core.class.Doc, action: view.action.Move }) - - builder.createDoc(core.class.Space, core.space.Model, { - name: 'Sequences', - description: 'Internal space to store sequence numbers', - members: [], - private: false - }, view.space.Sequence) } export default view diff --git a/models/view/src/migration.ts b/models/view/src/migration.ts index a08a4d7a43..a2032b3a70 100644 --- a/models/view/src/migration.ts +++ b/models/view/src/migration.ts @@ -13,42 +13,12 @@ // limitations under the License. // -import { TxOperations } from '@anticrm/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' -import core from '@anticrm/model-core' -import view from './plugin' export const viewOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { }, async upgrade (client: MigrationUpgradeClient): Promise { - console.log('View: Performing model upgrades') - - const ops = new TxOperations(client, core.account.System) - const kanbans = (await client.findAll(view.class.Kanban, {})) - .filter((kanban) => kanban.doneStates == null) - - await Promise.all( - kanbans - .map(async (kanban) => { - console.log(`Updating kanban: ${kanban._id}`) - try { - const doneStates = await Promise.all([ - ops.createDoc(core.class.WonState, kanban.space, { - title: 'Won' - }), - ops.createDoc(core.class.LostState, kanban.space, { - title: 'Lost' - }) - ]) - - await ops.updateDoc(kanban._class, kanban.space, kanban._id, { - doneStates - }) - } catch (e) { - console.error(e) - } - })) } } diff --git a/models/view/src/plugin.ts b/models/view/src/plugin.ts index f78cb62d55..8bfdca16b1 100644 --- a/models/view/src/plugin.ts +++ b/models/view/src/plugin.ts @@ -33,12 +33,9 @@ export default mergeIds(viewId, view, { StringPresenter: '' as AnyComponent, BooleanPresenter: '' as AnyComponent, BooleanEditor: '' as AnyComponent, - StatePresenter: '' as AnyComponent, - StateEditor: '' as AnyComponent, TimestampPresenter: '' as AnyComponent, DateEditor: '' as AnyComponent, DatePresenter: '' as AnyComponent, - TableView: '' as AnyComponent, - KanbanView: '' as AnyComponent + TableView: '' as AnyComponent } }) diff --git a/packages/core/src/__tests__/hierarchy.test.ts b/packages/core/src/__tests__/hierarchy.test.ts index d4f6605b63..9fbad6bf03 100644 --- a/packages/core/src/__tests__/hierarchy.test.ts +++ b/packages/core/src/__tests__/hierarchy.test.ts @@ -44,13 +44,13 @@ describe('hierarchy', () => { it('isImplements', async () => { const hierarchy = prepare() - let isImplements = hierarchy.isImplements(test.class.Task, core.interface.DocWithState) + let isImplements = hierarchy.isImplements(test.class.Task, test.interface.WithState) expect(isImplements).toBeTruthy() - isImplements = hierarchy.isImplements(test.class.TaskCheckItem, core.interface.DocWithState) + isImplements = hierarchy.isImplements(test.class.TaskCheckItem, test.interface.WithState) expect(isImplements).toBeTruthy() - const notImplements = hierarchy.isImplements(core.class.Space, core.interface.DocWithState) + const notImplements = hierarchy.isImplements(core.class.Space, test.interface.WithState) expect(notImplements).not.toBeTruthy() }) diff --git a/packages/core/src/__tests__/minmodel.ts b/packages/core/src/__tests__/minmodel.ts index 89ed7d8f2f..9a898385a6 100644 --- a/packages/core/src/__tests__/minmodel.ts +++ b/packages/core/src/__tests__/minmodel.ts @@ -15,7 +15,6 @@ import type { IntlString, Plugin } from '@anticrm/platform' import { plugin } from '@anticrm/platform' -import { DocWithState } from '..' import type { Arr, Class, Data, Doc, Interface, Mixin, Obj, Ref } from '../classes' import { AttachedDoc, ClassifierKind, DOMAIN_MODEL } from '../classes' import core from '../component' @@ -44,11 +43,15 @@ export interface AttachedComment extends AttachedDoc { message: string } -export interface Task extends Doc, DocWithState { +export interface WithState extends Doc { + state: number + number: number +} +export interface Task extends Doc, WithState { name: string } -export interface TaskCheckItem extends AttachedDoc, DocWithState { +export interface TaskCheckItem extends AttachedDoc, WithState { name: string complete: boolean } @@ -63,7 +66,8 @@ export const test = plugin('test' as Plugin, { TestComment: '' as Ref> }, interface: { - DummyDocWithState: '' as Ref> + WithState: '' as Ref>, + DummyWithState: '' as Ref> } }) @@ -82,7 +86,7 @@ export function genMinModel (): TxCUD[] { txes.push(createClass(core.class.Space, { label: 'Space' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL })) txes.push(createClass(core.class.Account, { label: 'Account' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL })) - txes.push(createInterface(core.interface.DocWithState, { label: 'DocWithState' as IntlString, extends: [], kind: ClassifierKind.INTERFACE })) + txes.push(createInterface(test.interface.WithState, { label: 'WithState' as IntlString, extends: [], kind: ClassifierKind.INTERFACE })) txes.push(createClass(core.class.Tx, { label: 'Tx' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_TX })) txes.push(createClass(core.class.TxCUD, { label: 'TxCUD' as IntlString, extends: core.class.Tx, kind: ClassifierKind.CLASS, domain: DOMAIN_TX })) @@ -93,10 +97,10 @@ export function genMinModel (): TxCUD[] { txes.push(createClass(test.mixin.TestMixin, { label: 'TestMixin' as IntlString, extends: core.class.Doc, kind: ClassifierKind.MIXIN })) - txes.push(createInterface(test.interface.DummyDocWithState, { label: 'DummyDocWithState' as IntlString, extends: [core.interface.DocWithState], kind: ClassifierKind.INTERFACE })) + txes.push(createInterface(test.interface.DummyWithState, { label: 'DummyWithState' as IntlString, extends: [test.interface.WithState], kind: ClassifierKind.INTERFACE })) txes.push(createClass(test.class.TestComment, { label: 'TestComment' as IntlString, extends: core.class.AttachedDoc, kind: ClassifierKind.CLASS })) - txes.push(createClass(test.class.Task, { label: 'Task' as IntlString, extends: core.class.Doc, implements: [test.interface.DummyDocWithState], kind: ClassifierKind.CLASS })) - txes.push(createClass(test.class.TaskCheckItem, { label: 'Task' as IntlString, extends: core.class.AttachedDoc, implements: [core.interface.DocWithState], kind: ClassifierKind.CLASS })) + txes.push(createClass(test.class.Task, { label: 'Task' as IntlString, extends: core.class.Doc, implements: [test.interface.DummyWithState], kind: ClassifierKind.CLASS })) + txes.push(createClass(test.class.TaskCheckItem, { label: 'Task' as IntlString, extends: core.class.AttachedDoc, implements: [test.interface.WithState], kind: ClassifierKind.CLASS })) txes.push( createDoc(core.class.Space, { diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index af9762e656..efb9566a74 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -218,45 +218,3 @@ export interface Space extends Doc { export interface Account extends Doc { email: string } - -// S T A T E - -/** - * @public - */ -export interface State extends Doc { - title: string - color: string -} - -/** - * @public - */ -export interface DoneState extends Doc { - title: string -} - -/** - * @public - */ -export interface WonState extends DoneState {} - -/** - * @public - */ -export interface LostState extends DoneState {} - -/** - * @public - */ -export interface DocWithState extends Doc { - state: Ref - doneState: Ref | null - number: number -} - -/** - * @public - */ -export interface SpaceWithStates extends Space { -} diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index faebf1c738..1dc695287b 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -14,8 +14,7 @@ // import type { Plugin, StatusCode } from '@anticrm/platform' import { plugin } from '@anticrm/platform' -import { DoneState, LostState, WonState } from '.' -import type { Account, AnyAttribute, AttachedDoc, Class, Doc, DocWithState, Interface, Obj, PropertyType, Ref, Space, SpaceWithStates, State, Timestamp, Type, Collection, RefTo } from './classes' +import type { Account, AnyAttribute, AttachedDoc, Class, Doc, Interface, Obj, PropertyType, Ref, Space, Timestamp, Type, Collection, RefTo } from './classes' import type { Tx, TxBulkWrite, TxCollectionCUD, TxCreateDoc, TxCUD, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx' /** @@ -41,12 +40,7 @@ export default plugin(coreId, { TxRemoveDoc: '' as Ref>>, TxPutBag: '' as Ref>>, Space: '' as Ref>, - SpaceWithStates: '' as Ref>, Account: '' as Ref>, - State: '' as Ref>, - DoneState: '' as Ref>, - WonState: '' as Ref>, - LostState: '' as Ref>, TypeString: '' as Ref>>, TypeBoolean: '' as Ref>>, TypeTimestamp: '' as Ref>>, @@ -55,9 +49,6 @@ export default plugin(coreId, { Collection: '' as Ref>>, Bag: '' as Ref>>> }, - interface: { - DocWithState: '' as Ref> - }, space: { Tx: '' as Ref, Model: '' as Ref diff --git a/packages/model/src/migration.ts b/packages/model/src/migration.ts index 2ca6b8669e..bc20f8223e 100644 --- a/packages/model/src/migration.ts +++ b/packages/model/src/migration.ts @@ -28,6 +28,9 @@ export interface MigrationClient { // Allow to raw update documents inside domain. update: (domain: Domain, query: DocumentQuery, operations: MigrateUpdate) => Promise + + // Move documents per domain + move: (sourceDomain: Domain, query: DocumentQuery, targetDomain: Domain) => Promise } /** diff --git a/packages/platform/src/status.ts b/packages/platform/src/status.ts index 83c1209e84..758ec7c104 100644 --- a/packages/platform/src/status.ts +++ b/packages/platform/src/status.ts @@ -56,7 +56,7 @@ export class PlatformError

> extends Error { readonly status: Status

constructor (status: Status

) { - super(`${status.severity}: ${status.code}`) + super(`${status.severity}: ${status.code} ${JSON.stringify(status.params)}`) this.status = status } } diff --git a/plugins/devmodel-resources/src/components/QueryView.svelte b/plugins/devmodel-resources/src/components/QueryView.svelte index 25f809b29f..963fa1611b 100644 --- a/plugins/devmodel-resources/src/components/QueryView.svelte +++ b/plugins/devmodel-resources/src/components/QueryView.svelte @@ -49,7 +49,7 @@ - { + { }}/> diff --git a/plugins/lead-resources/package.json b/plugins/lead-resources/package.json index fe0148075b..e0acc9b5a2 100644 --- a/plugins/lead-resources/package.json +++ b/plugins/lead-resources/package.json @@ -39,6 +39,8 @@ "@anticrm/panel": "~0.6.0", "@anticrm/contact": "~0.6.2", "@anticrm/view": "~0.6.0", + "@anticrm/task": "~0.6.0", + "@anticrm/task-resources": "~0.6.0", "@anticrm/view-resources": "~0.6.0", "@anticrm/attachment-resources": "~0.6.0", "@anticrm/contact-resources": "~0.6.0", diff --git a/plugins/lead-resources/src/components/CreateFunnel.svelte b/plugins/lead-resources/src/components/CreateFunnel.svelte index dd9ef2a7a7..20f5501211 100644 --- a/plugins/lead-resources/src/components/CreateFunnel.svelte +++ b/plugins/lead-resources/src/components/CreateFunnel.svelte @@ -19,8 +19,8 @@ import { EditBox, Grid, IconFolder, ToggleWithLabel } from '@anticrm/ui' import { createEventDispatcher } from 'svelte' import lead from '../plugin' - import view, { createKanban, KanbanTemplate } from '@anticrm/view' - import { KanbanTemplateSelector } from '@anticrm/view-resources' + import task, { createKanban, KanbanTemplate } from '@anticrm/task' + import { KanbanTemplateSelector } from '@anticrm/task-resources' const dispatch = createEventDispatcher() @@ -35,7 +35,7 @@ const client = getClient() async function createFunnel (): Promise { - if (templateId !== undefined && await client.findOne(view.class.KanbanTemplate, { _id: templateId }) === undefined) { + if (templateId !== undefined && await client.findOne(task.class.KanbanTemplate, { _id: templateId }) === undefined) { throw Error(`Failed to find target kanban template: ${templateId}`) } diff --git a/plugins/lead-resources/src/components/CreateLead.svelte b/plugins/lead-resources/src/components/CreateLead.svelte index c08e4938bf..9d6f1bb8e4 100644 --- a/plugins/lead-resources/src/components/CreateLead.svelte +++ b/plugins/lead-resources/src/components/CreateLead.svelte @@ -15,15 +15,15 @@ --> @@ -39,7 +39,7 @@ _class={contact.class.Employee} title="Assigned recruiter" caption="Recruiters" - bind:value={object.employee} + bind:value={object.assignee} on:change={change} allowDeselect titleDeselect={'Unassign recruiter'} diff --git a/plugins/recruit-resources/src/components/Applications.svelte b/plugins/recruit-resources/src/components/Applications.svelte index bc6a19bf63..64fa8e51f0 100644 --- a/plugins/recruit-resources/src/components/Applications.svelte +++ b/plugins/recruit-resources/src/components/Applications.svelte @@ -22,7 +22,7 @@ import FileDuo from "./icons/FileDuo.svelte" import { Table } from '@anticrm/view-resources' - import core from '@anticrm/core' + import task from '@anticrm/task' import recruit from '../plugin' export let objectId: Ref @@ -50,8 +50,8 @@ options={ { lookup: { - state: core.class.State, - space: core.class.Space + state: task.class.State, + space: task.class.Space } } } diff --git a/plugins/recruit-resources/src/components/ApplicationsPopup.svelte b/plugins/recruit-resources/src/components/ApplicationsPopup.svelte index f02a4b5c41..bed8e229b8 100644 --- a/plugins/recruit-resources/src/components/ApplicationsPopup.svelte +++ b/plugins/recruit-resources/src/components/ApplicationsPopup.svelte @@ -16,15 +16,11 @@ diff --git a/plugins/setting-resources/src/components/statuses/Templates.svelte b/plugins/setting-resources/src/components/statuses/Templates.svelte index 91da0e7123..927a1c8f69 100644 --- a/plugins/setting-resources/src/components/statuses/Templates.svelte +++ b/plugins/setting-resources/src/components/statuses/Templates.svelte @@ -19,7 +19,7 @@ import type { Ref } from '@anticrm/core' import { AttributeEditor, createQuery, getClient } from '@anticrm/presentation' import { CircleButton, IconAdd, IconMoreH, Label, showPopup } from '@anticrm/ui' - import view, { KanbanTemplate, KanbanTemplateSpace, LostStateTemplate, WonStateTemplate } from '@anticrm/view' + import task, { KanbanTemplate, KanbanTemplateSpace, LostStateTemplate, WonStateTemplate } from '@anticrm/task' import { ContextMenu } from '@anticrm/view-resources' import setting from '@anticrm/setting' @@ -30,7 +30,7 @@ let templateMap = new Map, KanbanTemplate>() const templatesQ = createQuery() $: if (folder !== undefined) { - templatesQ.query(view.class.KanbanTemplate, { space: folder._id }, (result) => { + templatesQ.query(task.class.KanbanTemplate, { space: folder._id }, (result) => { templates = result }) } @@ -51,7 +51,7 @@ const space = folder._id - const template = await client.createDoc(view.class.KanbanTemplate, space, { + const template = await client.createDoc(task.class.KanbanTemplate, space, { states: [], doneStates: [], doneStatesC: 0, @@ -62,12 +62,12 @@ const doneStates = [ { id: generateId(), - class: view.class.WonStateTemplate, + class: task.class.WonStateTemplate, title: 'Won' }, { id: generateId(), - class: view.class.LostStateTemplate, + class: task.class.LostStateTemplate, title: 'Lost' } ] @@ -77,7 +77,7 @@ ds.class, space, template, - view.class.KanbanTemplate, + task.class.KanbanTemplate, 'doneStatesC', { title: ds.title @@ -87,7 +87,7 @@ })) for (const ds of doneStates) { - await client.updateDoc(view.class.KanbanTemplate, space, template, { + await client.updateDoc(task.class.KanbanTemplate, space, template, { $push: { doneStates: ds.id } @@ -108,7 +108,7 @@

{#each templates as t (t._id)}
select(t)}> - +
{ showPopup(ContextMenu, { object: t }, ev.target, () => {}) diff --git a/plugins/task-assets/assets/icons.svg b/plugins/task-assets/assets/icons.svg index d115480b9e..3f4e1a9256 100644 --- a/plugins/task-assets/assets/icons.svg +++ b/plugins/task-assets/assets/icons.svg @@ -5,4 +5,11 @@ + + + + + + + diff --git a/plugins/task-assets/lang/en.json b/plugins/task-assets/lang/en.json index 0329e97f43..927beff651 100644 --- a/plugins/task-assets/lang/en.json +++ b/plugins/task-assets/lang/en.json @@ -16,6 +16,8 @@ "NoAttachmentsForTask": "There are no attachments for this task.", "AssigneeRequired": "Assignee is required", "More": "Options", - "TaskUnAssign": "Unassign" + "TaskUnAssign": "Unassign", + "NoTaskForObject": "No tasks defined", + "Delete": "Delete" } } \ No newline at end of file diff --git a/plugins/task-assets/src/index.ts b/plugins/task-assets/src/index.ts index 738984d455..a579fc4198 100644 --- a/plugins/task-assets/src/index.ts +++ b/plugins/task-assets/src/index.ts @@ -19,6 +19,8 @@ import task, {taskId} from '@anticrm/task' const icons = require('../assets/icons.svg') loadMetadata(task.icon, { Task: `${icons}#task`, + Kanban: `${icons}#kanban`, + Status: `${icons}#status` }) addStringsLoader(taskId, async (lang: string) => await import(`../lang/${lang}.json`)) diff --git a/plugins/task-resources/package.json b/plugins/task-resources/package.json index 80f0493bf3..c37d4e6db7 100644 --- a/plugins/task-resources/package.json +++ b/plugins/task-resources/package.json @@ -44,6 +44,7 @@ "@anticrm/view-resources": "~0.6.0", "@anticrm/login": "~0.6.1", "@anticrm/attachment-resources": "~0.6.0", - "@anticrm/chunter-resources": "~0.6.0" + "@anticrm/chunter-resources": "~0.6.0", + "@anticrm/workbench": "~0.6.1" } } diff --git a/plugins/task-resources/src/components/CreateProject.svelte b/plugins/task-resources/src/components/CreateProject.svelte index 4e99560993..aac95bda71 100644 --- a/plugins/task-resources/src/components/CreateProject.svelte +++ b/plugins/task-resources/src/components/CreateProject.svelte @@ -18,8 +18,8 @@ import { EditBox, Grid, IconFolder, ToggleWithLabel } from '@anticrm/ui' import { createEventDispatcher } from 'svelte' import task from '../plugin' - import view, { createKanban, KanbanTemplate } from '@anticrm/view' - import { KanbanTemplateSelector } from '@anticrm/view-resources' + import { createKanban, KanbanTemplate } from '@anticrm/task' + import KanbanTemplateSelector from './kanban/KanbanTemplateSelector.svelte' const dispatch = createEventDispatcher() @@ -34,7 +34,7 @@ const client = getClient() async function createProject (): Promise { - if (templateId !== undefined && await client.findOne(view.class.KanbanTemplate, { _id: templateId }) === undefined) { + if (templateId !== undefined && await client.findOne(task.class.KanbanTemplate, { _id: templateId }) === undefined) { throw Error(`Failed to find target kanban template: ${templateId}`) } diff --git a/plugins/task-resources/src/components/CreateTask.svelte b/plugins/task-resources/src/components/CreateTask.svelte index 08f6551ac7..985fc989a2 100644 --- a/plugins/task-resources/src/components/CreateTask.svelte +++ b/plugins/task-resources/src/components/CreateTask.svelte @@ -14,53 +14,58 @@ --> @@ -87,7 +91,7 @@ 0} + canSave={object.name.length > 0 && _space != null} spaceClass={task.class.Project} spaceLabel={task.string.ProjectName} spacePlaceholder={task.string.SelectProject} diff --git a/plugins/task-resources/src/components/EditTask.svelte b/plugins/task-resources/src/components/EditTask.svelte index 6c64666f26..d3f3b7d87b 100644 --- a/plugins/task-resources/src/components/EditTask.svelte +++ b/plugins/task-resources/src/components/EditTask.svelte @@ -16,7 +16,7 @@ import type { Ref } from '@anticrm/core' import { Panel } from '@anticrm/panel' import { createQuery, getClient } from '@anticrm/presentation' - import type { Task } from '@anticrm/task' + import type { Issue } from '@anticrm/task' import { EditBox, Grid } from '@anticrm/ui' import view from '@anticrm/view' import { createEventDispatcher } from 'svelte' @@ -24,11 +24,11 @@ import { Attachments } from '@anticrm/attachment-resources' import TaskHeader from './TaskHeader.svelte' - export let _id: Ref - let object: Task + export let _id: Ref + let object: Issue const query = createQuery() - $: query.query(task.class.Task, { _id }, (result) => { + $: query.query(task.class.Issue, { _id }, (result) => { object = result[0] }) @@ -36,7 +36,7 @@ const client = getClient() function change (field: string, value: any) { - client.updateDoc(task.class.Task, object.space, object._id, { [field]: value }) + client.updateCollection(object._class, object.space, object._id, object.attachedTo, object.attachedToClass, object.collection, { [field]: value }) } diff --git a/plugins/task-resources/src/components/KanbanCard.svelte b/plugins/task-resources/src/components/KanbanCard.svelte index a23a613437..0c1d179b97 100644 --- a/plugins/task-resources/src/components/KanbanCard.svelte +++ b/plugins/task-resources/src/components/KanbanCard.svelte @@ -18,13 +18,13 @@ import { formatName } from '@anticrm/contact' import type { WithLookup } from '@anticrm/core' import { Avatar } from '@anticrm/presentation' - import type { Task } from '@anticrm/task' + import type { Issue } from '@anticrm/task' import { ActionIcon, IconMoreH, Label, showPopup } from '@anticrm/ui' import { ContextMenu } from '@anticrm/view-resources' import task from '../plugin' import TaskPresenter from './TaskPresenter.svelte' - export let object: WithLookup + export let object: WithLookup export let draggable: boolean const showMenu = (ev?: Event): void => { diff --git a/plugins/task-resources/src/components/TaskHeader.svelte b/plugins/task-resources/src/components/TaskHeader.svelte index 0ce4430b22..415b08218d 100644 --- a/plugins/task-resources/src/components/TaskHeader.svelte +++ b/plugins/task-resources/src/components/TaskHeader.svelte @@ -16,14 +16,14 @@ diff --git a/plugins/task-resources/src/components/TaskPresenter.svelte b/plugins/task-resources/src/components/TaskPresenter.svelte index 704288bc17..08c34dbcd6 100644 --- a/plugins/task-resources/src/components/TaskPresenter.svelte +++ b/plugins/task-resources/src/components/TaskPresenter.svelte @@ -14,13 +14,13 @@ // limitations under the License. --> + +
+
+
Tasks
+ +
+ {#if tasks.length > 0} + + {:else} +
+ +
+
+
+ +
+
+ {/if} + + + diff --git a/plugins/view-resources/src/components/KanbanCardEmpty.svelte b/plugins/task-resources/src/components/kanban/KanbanCardEmpty.svelte similarity index 100% rename from plugins/view-resources/src/components/KanbanCardEmpty.svelte rename to plugins/task-resources/src/components/kanban/KanbanCardEmpty.svelte diff --git a/plugins/view-resources/src/components/KanbanEditor.svelte b/plugins/task-resources/src/components/kanban/KanbanEditor.svelte similarity index 74% rename from plugins/view-resources/src/components/KanbanEditor.svelte rename to plugins/task-resources/src/components/kanban/KanbanEditor.svelte index cda2f1f749..8038900c76 100644 --- a/plugins/view-resources/src/components/KanbanEditor.svelte +++ b/plugins/task-resources/src/components/kanban/KanbanEditor.svelte @@ -14,12 +14,12 @@ // limitations under the License. --> + + + + + + + + + + + + + diff --git a/plugins/task-resources/src/components/state/ColorsPopup.svelte b/plugins/task-resources/src/components/state/ColorsPopup.svelte new file mode 100644 index 0000000000..42a96978c1 --- /dev/null +++ b/plugins/task-resources/src/components/state/ColorsPopup.svelte @@ -0,0 +1,50 @@ + + + + + +
+ {#each colors as color} +
{ dispatch('close', color) }} /> + {/each} +
+ + + diff --git a/plugins/workbench-resources/src/components/EditStatuses.svelte b/plugins/task-resources/src/components/state/EditStatuses.svelte similarity index 85% rename from plugins/workbench-resources/src/components/EditStatuses.svelte rename to plugins/task-resources/src/components/state/EditStatuses.svelte index 147e700912..6453aed092 100644 --- a/plugins/workbench-resources/src/components/EditStatuses.svelte +++ b/plugins/task-resources/src/components/state/EditStatuses.svelte @@ -15,19 +15,15 @@ --> + +
+
+
+
+
+ + diff --git a/plugins/view-resources/src/components/StateEditor.svelte b/plugins/task-resources/src/components/state/StateEditor.svelte similarity index 90% rename from plugins/view-resources/src/components/StateEditor.svelte rename to plugins/task-resources/src/components/state/StateEditor.svelte index dfde2a4602..7068a076bc 100644 --- a/plugins/view-resources/src/components/StateEditor.svelte +++ b/plugins/task-resources/src/components/state/StateEditor.svelte @@ -15,7 +15,8 @@ --> @@ -39,7 +40,7 @@ if (!opened) { opened = true showPopup(StatesPopup, { space: state.space }, container, (result) => { - if (result) { + if (result) { value = result._id onChange(value) } diff --git a/plugins/view-resources/src/components/StatePresenter.svelte b/plugins/task-resources/src/components/state/StatePresenter.svelte similarity index 100% rename from plugins/view-resources/src/components/StatePresenter.svelte rename to plugins/task-resources/src/components/state/StatePresenter.svelte diff --git a/plugins/view-resources/src/components/StatesEditor.svelte b/plugins/task-resources/src/components/state/StatesEditor.svelte similarity index 95% rename from plugins/view-resources/src/components/StatesEditor.svelte rename to plugins/task-resources/src/components/state/StatesEditor.svelte index 0a1f3546c6..74ff4673a0 100644 --- a/plugins/view-resources/src/components/StatesEditor.svelte +++ b/plugins/task-resources/src/components/state/StatesEditor.svelte @@ -14,16 +14,15 @@ // limitations under the License. --> diff --git a/plugins/view-resources/src/components/StatusesPopup.svelte b/plugins/task-resources/src/components/state/StatusesPopup.svelte similarity index 94% rename from plugins/view-resources/src/components/StatusesPopup.svelte rename to plugins/task-resources/src/components/state/StatusesPopup.svelte index e41959b0cb..d10213a9f0 100644 --- a/plugins/view-resources/src/components/StatusesPopup.svelte +++ b/plugins/task-resources/src/components/state/StatusesPopup.svelte @@ -16,7 +16,7 @@ - - - - - diff --git a/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte b/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte index 74929a37f7..6929e3e3dd 100644 --- a/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte +++ b/plugins/workbench-resources/src/components/navigator/SpacesNav.svelte @@ -14,24 +14,18 @@ -->