mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-29 09:09:15 +03:00
parent
34b9495631
commit
b0ffc0ed46
@ -51,7 +51,6 @@ specifiers:
|
|||||||
'@rush-temp/model-server-chunter': file:./projects/model-server-chunter.tgz
|
'@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-core': file:./projects/model-server-core.tgz
|
||||||
'@rush-temp/model-server-recruit': file:./projects/model-server-recruit.tgz
|
'@rush-temp/model-server-recruit': file:./projects/model-server-recruit.tgz
|
||||||
'@rush-temp/model-server-task': file:./projects/model-server-task.tgz
|
|
||||||
'@rush-temp/model-setting': file:./projects/model-setting.tgz
|
'@rush-temp/model-setting': file:./projects/model-setting.tgz
|
||||||
'@rush-temp/model-task': file:./projects/model-task.tgz
|
'@rush-temp/model-task': file:./projects/model-task.tgz
|
||||||
'@rush-temp/model-telegram': file:./projects/model-telegram.tgz
|
'@rush-temp/model-telegram': file:./projects/model-telegram.tgz
|
||||||
@ -74,8 +73,6 @@ specifiers:
|
|||||||
'@rush-temp/server-core': file:./projects/server-core.tgz
|
'@rush-temp/server-core': file:./projects/server-core.tgz
|
||||||
'@rush-temp/server-recruit': file:./projects/server-recruit.tgz
|
'@rush-temp/server-recruit': file:./projects/server-recruit.tgz
|
||||||
'@rush-temp/server-recruit-resources': file:./projects/server-recruit-resources.tgz
|
'@rush-temp/server-recruit-resources': file:./projects/server-recruit-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/server-ws': file:./projects/server-ws.tgz
|
||||||
'@rush-temp/setting': file:./projects/setting.tgz
|
'@rush-temp/setting': file:./projects/setting.tgz
|
||||||
'@rush-temp/setting-assets': file:./projects/setting-assets.tgz
|
'@rush-temp/setting-assets': file:./projects/setting-assets.tgz
|
||||||
@ -144,6 +141,7 @@ specifiers:
|
|||||||
koa: ^2.13.1
|
koa: ^2.13.1
|
||||||
koa-bodyparser: ^4.3.0
|
koa-bodyparser: ^4.3.0
|
||||||
koa-router: ^10.1.1
|
koa-router: ^10.1.1
|
||||||
|
lexorank: ~1.0.4
|
||||||
mini-css-extract-plugin: ^2.2.0
|
mini-css-extract-plugin: ^2.2.0
|
||||||
minio: ^7.0.19
|
minio: ^7.0.19
|
||||||
node-html-parser: ^4.1.3
|
node-html-parser: ^4.1.3
|
||||||
@ -220,7 +218,6 @@ dependencies:
|
|||||||
'@rush-temp/model-server-chunter': file:projects/model-server-chunter.tgz_typescript@4.4.3
|
'@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-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-recruit': file:projects/model-server-recruit.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-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-task': file:projects/model-task.tgz_typescript@4.4.3
|
||||||
'@rush-temp/model-telegram': file:projects/model-telegram.tgz_typescript@4.4.3
|
'@rush-temp/model-telegram': file:projects/model-telegram.tgz_typescript@4.4.3
|
||||||
@ -243,8 +240,6 @@ dependencies:
|
|||||||
'@rush-temp/server-core': file:projects/server-core.tgz
|
'@rush-temp/server-core': file:projects/server-core.tgz
|
||||||
'@rush-temp/server-recruit': file:projects/server-recruit.tgz
|
'@rush-temp/server-recruit': file:projects/server-recruit.tgz
|
||||||
'@rush-temp/server-recruit-resources': file:projects/server-recruit-resources.tgz
|
'@rush-temp/server-recruit-resources': file:projects/server-recruit-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/server-ws': file:projects/server-ws.tgz
|
||||||
'@rush-temp/setting': file:projects/setting.tgz
|
'@rush-temp/setting': file:projects/setting.tgz
|
||||||
'@rush-temp/setting-assets': file:projects/setting-assets.tgz
|
'@rush-temp/setting-assets': file:projects/setting-assets.tgz
|
||||||
@ -313,6 +308,7 @@ dependencies:
|
|||||||
koa: 2.13.3
|
koa: 2.13.3
|
||||||
koa-bodyparser: 4.3.0
|
koa-bodyparser: 4.3.0
|
||||||
koa-router: 10.1.1
|
koa-router: 10.1.1
|
||||||
|
lexorank: 1.0.4
|
||||||
mini-css-extract-plugin: 2.4.1_webpack@5.57.1
|
mini-css-extract-plugin: 2.4.1_webpack@5.57.1
|
||||||
minio: 7.0.19
|
minio: 7.0.19
|
||||||
node-html-parser: 4.1.5
|
node-html-parser: 4.1.5
|
||||||
@ -6409,6 +6405,10 @@ packages:
|
|||||||
type-check: 0.4.0
|
type-check: 0.4.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/lexorank/1.0.4:
|
||||||
|
resolution: {integrity: sha512-CMgA8AMJIX/QfoYHKyjg0hv9W1SGL2xRkt0uLyhT9xKKRj73fHi+IhsrB3W36wwk4I0iz8YlKHfdW14QDwerMA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/lilconfig/2.0.3:
|
/lilconfig/2.0.3:
|
||||||
resolution: {integrity: sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==}
|
resolution: {integrity: sha512-EHKqr/+ZvdKCifpNrJCKxBTgk5XupZA3y/aCPY9mxfgBzmgh93Mt/WqjjQ38oMxXuvDokaKiM3lAgvSH2sjtHg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@ -10345,7 +10345,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/core.tgz:
|
file:projects/core.tgz:
|
||||||
resolution: {integrity: sha512-1RXdycw5v+KGu+kmqXvnrKAZpNYbc0U/rInLVwKYJ17U/hED4ONAIPEaVDxp+fxgyPHpEo7AQjZe2aD87ogwtg==, tarball: file:projects/core.tgz}
|
resolution: {integrity: sha512-Xjk/aGZgRnNWYrQpTy8f2H8oQVVIvbkX6MdesJnRH7AjJTI2RtloF+8sUQMSjSahPh7thHwaYyDVlJ37vMXXNQ==, tarball: file:projects/core.tgz}
|
||||||
name: '@rush-temp/core'
|
name: '@rush-temp/core'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -10359,6 +10359,7 @@ packages:
|
|||||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||||
eslint-plugin-promise: 5.1.1_eslint@7.32.0
|
eslint-plugin-promise: 5.1.1_eslint@7.32.0
|
||||||
just-clone: 3.2.1
|
just-clone: 3.2.1
|
||||||
|
lexorank: 1.0.4
|
||||||
prettier: 2.4.1
|
prettier: 2.4.1
|
||||||
simplytyped: 3.3.0_typescript@4.4.3
|
simplytyped: 3.3.0_typescript@4.4.3
|
||||||
typescript: 4.4.3
|
typescript: 4.4.3
|
||||||
@ -10770,7 +10771,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/model-all.tgz_typescript@4.4.3:
|
file:projects/model-all.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-XyhGIWfnSxUKXSXQ/yfvCx+S5xqBMJ4eko1pDFv0v048sQJy6fefxg3LOLyCDodNzsa5KxGdqvk7Y8H7Izop0g==, tarball: file:projects/model-all.tgz}
|
resolution: {integrity: sha512-iCugm1e/KTBXZ0FNnog/eP07l49sFIDU2orN0vAMUJ5pgZC7T38LSjnOL2y80OmoTbQK/3G2eH7Or+bxOYk2Cg==, tarball: file:projects/model-all.tgz}
|
||||||
id: file:projects/model-all.tgz
|
id: file:projects/model-all.tgz
|
||||||
name: '@rush-temp/model-all'
|
name: '@rush-temp/model-all'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -10837,7 +10838,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/model-contact.tgz_typescript@4.4.3:
|
file:projects/model-contact.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-qZPBOQC2Oi/Qxpjt91OM1tGBPwShe2SLIHKmDNGSsk79zzdmW3+ZDrge4VVrK/ngc5P2fJQwpQRXgOkNgz2vnA==, tarball: file:projects/model-contact.tgz}
|
resolution: {integrity: sha512-ffJA0hXhTeEjKGbCFKTgYk9ch8JsAnZKmDOtyTSzE+tmIklA0Q1gWQGwqttPSgrGVQuy2UXkYXv1m7cnhBICxg==, tarball: file:projects/model-contact.tgz}
|
||||||
id: file:projects/model-contact.tgz
|
id: file:projects/model-contact.tgz
|
||||||
name: '@rush-temp/model-contact'
|
name: '@rush-temp/model-contact'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -11023,27 +11024,6 @@ packages:
|
|||||||
- typescript
|
- typescript
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
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
|
|
||||||
'@types/heft-jest': 1.0.2
|
|
||||||
'@typescript-eslint/eslint-plugin': 5.4.0_87dbf04088b125598d0271706532eaf3
|
|
||||||
'@typescript-eslint/parser': 5.4.0_eslint@7.32.0+typescript@4.4.3
|
|
||||||
eslint: 7.32.0
|
|
||||||
eslint-config-standard-with-typescript: 21.0.1_05a8ea1454e6ca4c9f98b94b8f3abf9c
|
|
||||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
|
||||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
|
||||||
eslint-plugin-promise: 5.1.1_eslint@7.32.0
|
|
||||||
prettier: 2.4.1
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
- typescript
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
file:projects/model-setting.tgz_typescript@4.4.3:
|
file:projects/model-setting.tgz_typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-U6P3iLbt33/iJI21fs7trAHtpwWzmI/zJn+3qyxjjnFP88i11vmbd1zfb6+GYu5muRCutqNi1pTX/5cDo+NtrA==, tarball: file:projects/model-setting.tgz}
|
resolution: {integrity: sha512-U6P3iLbt33/iJI21fs7trAHtpwWzmI/zJn+3qyxjjnFP88i11vmbd1zfb6+GYu5muRCutqNi1pTX/5cDo+NtrA==, tarball: file:projects/model-setting.tgz}
|
||||||
id: file:projects/model-setting.tgz
|
id: file:projects/model-setting.tgz
|
||||||
@ -11339,7 +11319,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3:
|
file:projects/prod.tgz_sass@1.42.1+typescript@4.4.3:
|
||||||
resolution: {integrity: sha512-jgSulZmT4Kq28boQo8BJQrdkcN660EtY7XUH0QWcgGYHDBXFiGfP4eoIxAJL4wtb/JKwKLEkwG+SwTUIuIb7Xw==, tarball: file:projects/prod.tgz}
|
resolution: {integrity: sha512-cWieTfrEsukKvJvSGr/ZOX6Vo4aZQHGDpOrE2smLt21Rk+/lSNpUcpAKKGRoFmW08sWkQoYrU6BdPMgw4+/UNQ==, tarball: file:projects/prod.tgz}
|
||||||
id: file:projects/prod.tgz
|
id: file:projects/prod.tgz
|
||||||
name: '@rush-temp/prod'
|
name: '@rush-temp/prod'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -11573,47 +11553,6 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
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
|
|
||||||
'@types/heft-jest': 1.0.2
|
|
||||||
'@typescript-eslint/eslint-plugin': 5.4.0_87dbf04088b125598d0271706532eaf3
|
|
||||||
'@typescript-eslint/parser': 5.4.0_eslint@7.32.0+typescript@4.4.3
|
|
||||||
eslint: 7.32.0
|
|
||||||
eslint-config-standard-with-typescript: 21.0.1_05a8ea1454e6ca4c9f98b94b8f3abf9c
|
|
||||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
|
||||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
|
||||||
eslint-plugin-promise: 5.1.1_eslint@7.32.0
|
|
||||||
prettier: 2.4.1
|
|
||||||
typescript: 4.4.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
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
|
|
||||||
'@types/heft-jest': 1.0.2
|
|
||||||
'@types/node': 16.11.12
|
|
||||||
'@typescript-eslint/eslint-plugin': 5.4.0_87dbf04088b125598d0271706532eaf3
|
|
||||||
'@typescript-eslint/parser': 5.4.0_eslint@7.32.0+typescript@4.4.3
|
|
||||||
eslint: 7.32.0
|
|
||||||
eslint-config-standard-with-typescript: 21.0.1_05a8ea1454e6ca4c9f98b94b8f3abf9c
|
|
||||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
|
||||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
|
||||||
eslint-plugin-promise: 5.1.1_eslint@7.32.0
|
|
||||||
prettier: 2.4.1
|
|
||||||
typescript: 4.4.3
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
file:projects/server-ws.tgz:
|
file:projects/server-ws.tgz:
|
||||||
resolution: {integrity: sha512-MSFFpLjIMFt0oyH4+8JUkNOkCNtdEtMDoxcyN7+kDdz44wSZjSOmheJHYkXO6JTEffcaaRhQ9vO/e7MBNMeoxQ==, tarball: file:projects/server-ws.tgz}
|
resolution: {integrity: sha512-MSFFpLjIMFt0oyH4+8JUkNOkCNtdEtMDoxcyN7+kDdz44wSZjSOmheJHYkXO6JTEffcaaRhQ9vO/e7MBNMeoxQ==, tarball: file:projects/server-ws.tgz}
|
||||||
name: '@rush-temp/server-ws'
|
name: '@rush-temp/server-ws'
|
||||||
@ -11641,7 +11580,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/server.tgz:
|
file:projects/server.tgz:
|
||||||
resolution: {integrity: sha512-fFYknnDfAOz+iq8INHKSgCjYUkbxqLiHIBM55W8QtmZq0R8hMLEwCcLiyNqL1iCgXKs8sGHf+aMbZcciBNi1Ow==, tarball: file:projects/server.tgz}
|
resolution: {integrity: sha512-UBFOAisptjpTNIZoU6hWJVBKTk7mftZU0Dz+pJiVhMBJSD+iW393yv4v9GedEpor5rIYDGGcps7IVCXZlr76tw==, tarball: file:projects/server.tgz}
|
||||||
name: '@rush-temp/server'
|
name: '@rush-temp/server'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import { Ref, TxOperations } from '@anticrm/core'
|
import { genRanks, Ref, TxOperations } from '@anticrm/core'
|
||||||
import task, { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task'
|
import task, { DoneState, Kanban, SpaceWithStates, State } from '@anticrm/task'
|
||||||
import { findOrUpdate } from './utils'
|
import { findOrUpdate } from './utils'
|
||||||
|
|
||||||
@ -12,42 +12,55 @@ export async function createUpdateSpaceKanban (spaceId: Ref<SpaceWithStates>, cl
|
|||||||
{ color: '#F28469', name: 'Invalid' }
|
{ color: '#F28469', name: 'Invalid' }
|
||||||
]
|
]
|
||||||
const states: Array<Ref<State>> = []
|
const states: Array<Ref<State>> = []
|
||||||
|
const stateRanks = genRanks(rawStates.length)
|
||||||
for (const st of rawStates) {
|
for (const st of rawStates) {
|
||||||
|
const rank = stateRanks.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
console.error('Failed to generate rank')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
const sid = ('generated-' + spaceId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref<State>
|
const sid = ('generated-' + spaceId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref<State>
|
||||||
await findOrUpdate(client, spaceId, task.class.State,
|
await findOrUpdate(client, spaceId, task.class.State,
|
||||||
sid,
|
sid,
|
||||||
{
|
{
|
||||||
title: st.name,
|
title: st.name,
|
||||||
color: st.color
|
color: st.color,
|
||||||
|
rank
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
states.push(sid)
|
states.push(sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawDoneStates = [
|
const doneStates = [
|
||||||
{ class: task.class.WonState, title: 'Won' },
|
{ class: task.class.WonState, title: 'Won' },
|
||||||
{ class: task.class.LostState, title: 'Lost' }
|
{ class: task.class.LostState, title: 'Lost' }
|
||||||
]
|
]
|
||||||
const doneStates: Array<Ref<DoneState>> = []
|
const doneStateRanks = genRanks(doneStates.length)
|
||||||
for (const st of rawDoneStates) {
|
for (const st of doneStates) {
|
||||||
|
const rank = doneStateRanks.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
console.error('Failed to generate rank')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
const sid = ('generated-' + spaceId + '.done-state.' + st.title.toLowerCase().replace(' ', '_')) as Ref<DoneState>
|
const sid = ('generated-' + spaceId + '.done-state.' + st.title.toLowerCase().replace(' ', '_')) as Ref<DoneState>
|
||||||
await findOrUpdate(client, spaceId, st.class,
|
await findOrUpdate(client, spaceId, st.class,
|
||||||
sid,
|
sid,
|
||||||
{
|
{
|
||||||
title: st.title
|
title: st.title,
|
||||||
|
rank
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
doneStates.push(sid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await findOrUpdate(client, spaceId,
|
await findOrUpdate(client, spaceId,
|
||||||
task.class.Kanban,
|
task.class.Kanban,
|
||||||
('generated-' + spaceId + '.kanban') as Ref<Kanban>,
|
('generated-' + spaceId + '.kanban') as Ref<Kanban>,
|
||||||
{
|
{
|
||||||
attachedTo: spaceId,
|
attachedTo: spaceId
|
||||||
states,
|
|
||||||
doneStates,
|
|
||||||
order: []
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return states
|
return states
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import contact from '@anticrm/contact'
|
import contact from '@anticrm/contact'
|
||||||
import core, { AttachedData, Data, generateId, Ref, TxOperations } from '@anticrm/core'
|
import core, { AttachedData, Data, generateId, genRanks, Ref, TxOperations } from '@anticrm/core'
|
||||||
import recruit from '@anticrm/model-recruit'
|
import recruit from '@anticrm/model-recruit'
|
||||||
import { Applicant, Candidate, Vacancy } from '@anticrm/recruit'
|
import { Applicant, Candidate, Vacancy } from '@anticrm/recruit'
|
||||||
import faker from 'faker'
|
import faker from 'faker'
|
||||||
@ -79,7 +79,7 @@ export async function generateContacts (transactorUrl: string, dbName: string, o
|
|||||||
}
|
}
|
||||||
const vacancyId = (options.random ? `vacancy-${generateId()}-${i}` : `vacancy-genid-${i}`) as Ref<Vacancy>
|
const vacancyId = (options.random ? `vacancy-${generateId()}-${i}` : `vacancy-genid-${i}`) as Ref<Vacancy>
|
||||||
|
|
||||||
console.log('Creating vacandy', vacancy.name)
|
console.log('Creating vacancy', vacancy.name)
|
||||||
// Update or create candidate
|
// Update or create candidate
|
||||||
await findOrUpdate(client, core.space.Model, recruit.class.Vacancy, vacancyId, vacancy)
|
await findOrUpdate(client, core.space.Model, recruit.class.Vacancy, vacancyId, vacancy)
|
||||||
|
|
||||||
@ -93,14 +93,22 @@ export async function generateContacts (transactorUrl: string, dbName: string, o
|
|||||||
|
|
||||||
console.log('States generated', vacancy.name)
|
console.log('States generated', vacancy.name)
|
||||||
|
|
||||||
|
const rankGen = genRanks(candidates.length)
|
||||||
for (const candidateId of candidates) {
|
for (const candidateId of candidates) {
|
||||||
|
const rank = rankGen.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
throw Error('Failed to generate rank')
|
||||||
|
}
|
||||||
|
|
||||||
const applicantId = `vacancy-${vacancyId}-${candidateId}` as Ref<Applicant>
|
const applicantId = `vacancy-${vacancyId}-${candidateId}` as Ref<Applicant>
|
||||||
|
|
||||||
const applicant: AttachedData<Applicant> = {
|
const applicant: AttachedData<Applicant> = {
|
||||||
number: faker.datatype.number(),
|
number: faker.datatype.number(),
|
||||||
assignee: faker.random.arrayElement(emoloyeeIds),
|
assignee: faker.random.arrayElement(emoloyeeIds),
|
||||||
state: faker.random.arrayElement(states),
|
state: faker.random.arrayElement(states),
|
||||||
doneState: null
|
doneState: null,
|
||||||
|
rank
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update or create candidate
|
// Update or create candidate
|
||||||
|
@ -71,8 +71,6 @@
|
|||||||
"@anticrm/contact-assets": "~0.6.0",
|
"@anticrm/contact-assets": "~0.6.0",
|
||||||
"@anticrm/server-recruit": "~0.6.1",
|
"@anticrm/server-recruit": "~0.6.1",
|
||||||
"@anticrm/server-recruit-resources": "~0.6.0",
|
"@anticrm/server-recruit-resources": "~0.6.0",
|
||||||
"@anticrm/server-task": "~0.6.0",
|
|
||||||
"@anticrm/server-task-resources": "~0.6.0",
|
|
||||||
"@anticrm/activity": "~0.6.0",
|
"@anticrm/activity": "~0.6.0",
|
||||||
"@anticrm/activity-assets": "~0.6.0",
|
"@anticrm/activity-assets": "~0.6.0",
|
||||||
"@anticrm/activity-resources": "~0.6.0",
|
"@anticrm/activity-resources": "~0.6.0",
|
||||||
|
@ -19,7 +19,6 @@ import login from '@anticrm/login'
|
|||||||
import { clientId } from '@anticrm/client'
|
import { clientId } from '@anticrm/client'
|
||||||
import { serverChunterId } from '@anticrm/server-chunter'
|
import { serverChunterId } from '@anticrm/server-chunter'
|
||||||
import { serverRecruitId } from '@anticrm/server-recruit'
|
import { serverRecruitId } from '@anticrm/server-recruit'
|
||||||
import { serverViewId } from '@anticrm/server-task'
|
|
||||||
|
|
||||||
import { setMetadata } from '@anticrm/platform'
|
import { setMetadata } from '@anticrm/platform'
|
||||||
|
|
||||||
@ -33,7 +32,6 @@ export function configurePlatformDev() {
|
|||||||
addLocation(clientId, () => import(/* webpackChunkName: "client-dev" */ '@anticrm/dev-client-resources'))
|
addLocation(clientId, () => import(/* webpackChunkName: "client-dev" */ '@anticrm/dev-client-resources'))
|
||||||
addLocation(serverChunterId, () => import(/* webpackChunkName: "server-chunter" */ '@anticrm/dev-server-chunter-resources'))
|
addLocation(serverChunterId, () => import(/* webpackChunkName: "server-chunter" */ '@anticrm/dev-server-chunter-resources'))
|
||||||
addLocation(serverRecruitId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-recruit-resources'))
|
addLocation(serverRecruitId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-recruit-resources'))
|
||||||
addLocation(serverViewId, () => import(/* webpackChunkName: "server-task" */ '@anticrm/server-task-resources'))
|
|
||||||
|
|
||||||
// Set devmodel to hook client to be able to present all activity
|
// Set devmodel to hook client to be able to present all activity
|
||||||
enableDevModel()
|
enableDevModel()
|
||||||
|
@ -43,7 +43,6 @@
|
|||||||
"@anticrm/model-server-core": "~0.6.0",
|
"@anticrm/model-server-core": "~0.6.0",
|
||||||
"@anticrm/model-server-chunter": "~0.6.0",
|
"@anticrm/model-server-chunter": "~0.6.0",
|
||||||
"@anticrm/model-server-recruit": "~0.6.0",
|
"@anticrm/model-server-recruit": "~0.6.0",
|
||||||
"@anticrm/model-server-task": "~0.6.0",
|
|
||||||
"@anticrm/model-activity": "~0.6.0",
|
"@anticrm/model-activity": "~0.6.0",
|
||||||
"@anticrm/model-attachment": "~0.6.0",
|
"@anticrm/model-attachment": "~0.6.0",
|
||||||
"@anticrm/core": "~0.6.13"
|
"@anticrm/core": "~0.6.13"
|
||||||
|
@ -30,7 +30,6 @@ import { createModel as leadModel } from '@anticrm/model-lead'
|
|||||||
import { createModel as serverCoreModel } from '@anticrm/model-server-core'
|
import { createModel as serverCoreModel } from '@anticrm/model-server-core'
|
||||||
import { createModel as serverChunterModel } from '@anticrm/model-server-chunter'
|
import { createModel as serverChunterModel } from '@anticrm/model-server-chunter'
|
||||||
import { createModel as serverRecruitModel } from '@anticrm/model-server-recruit'
|
import { createModel as serverRecruitModel } from '@anticrm/model-server-recruit'
|
||||||
import { createModel as serverViewModel } from '@anticrm/model-server-task'
|
|
||||||
import { createModel as activityModel } from '@anticrm/model-activity'
|
import { createModel as activityModel } from '@anticrm/model-activity'
|
||||||
|
|
||||||
import { createDemo } from '@anticrm/model-demo'
|
import { createDemo } from '@anticrm/model-demo'
|
||||||
@ -53,7 +52,6 @@ leadModel(builder)
|
|||||||
serverCoreModel(builder)
|
serverCoreModel(builder)
|
||||||
serverChunterModel(builder)
|
serverChunterModel(builder)
|
||||||
serverRecruitModel(builder)
|
serverRecruitModel(builder)
|
||||||
serverViewModel(builder)
|
|
||||||
|
|
||||||
createDemo(builder)
|
createDemo(builder)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import type { Account, Arr, Ref, Space } from '@anticrm/core'
|
import type { Account, Arr, Ref, Space } from '@anticrm/core'
|
||||||
import { DOMAIN_MODEL } from '@anticrm/core'
|
import { DOMAIN_MODEL } from '@anticrm/core'
|
||||||
import { Model, Prop, TypeBoolean, TypeString } from '@anticrm/model'
|
import { Implements, Model, Prop, TypeBoolean, TypeString } from '@anticrm/model'
|
||||||
import type { IntlString } from '@anticrm/platform'
|
import type { IntlString } from '@anticrm/platform'
|
||||||
import core from './component'
|
import core from './component'
|
||||||
import { TDoc } from './core'
|
import { TDoc } from './core'
|
||||||
@ -40,3 +40,8 @@ export class TSpace extends TDoc implements Space {
|
|||||||
export class TAccount extends TDoc implements Account {
|
export class TAccount extends TDoc implements Account {
|
||||||
email!: string
|
email!: string
|
||||||
}
|
}
|
||||||
|
@Implements(core.interface.DocWithRank)
|
||||||
|
export class TDocWithRank extends TDoc {
|
||||||
|
@Prop(TypeString(), 'Rank' as IntlString)
|
||||||
|
rank!: string
|
||||||
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: './tsconfig.json'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
*
|
|
||||||
!/lib/**
|
|
||||||
!CHANGELOG.md
|
|
||||||
/lib/**/__tests__/
|
|
@ -1,18 +0,0 @@
|
|||||||
// The "rig.json" file directs tools to look for their config files in an external package.
|
|
||||||
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
|
|
||||||
{
|
|
||||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Required) The name of the rig package to inherit from.
|
|
||||||
* It should be an NPM package name with the "-rig" suffix.
|
|
||||||
*/
|
|
||||||
"rigPackageName": "@anticrm/model-rig"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Optional) Selects a config profile from the rig package. The name must consist of
|
|
||||||
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
|
|
||||||
* If omitted, then the "default" profile will be used."
|
|
||||||
*/
|
|
||||||
// "rigProfile": "your-profile-name"
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@anticrm/model-server-task",
|
|
||||||
"version": "0.6.0",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"author": "Anticrm Platform Contributors",
|
|
||||||
"license": "EPL-2.0",
|
|
||||||
"scripts": {
|
|
||||||
"build": "heft build",
|
|
||||||
"build:watch": "tsc",
|
|
||||||
"lint:fix": "eslint --fix src",
|
|
||||||
"lint": "eslint src",
|
|
||||||
"format": "prettier --write src && eslint --fix src"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@anticrm/model-rig": "~0.6.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
||||||
"eslint-plugin-import": "^2.25.3",
|
|
||||||
"eslint-plugin-promise": "^5.1.1",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"eslint": "^7.32.0",
|
|
||||||
"@types/heft-jest": "^1.0.2",
|
|
||||||
"@typescript-eslint/parser": "^5.4.0",
|
|
||||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
|
||||||
"prettier": "^2.4.1",
|
|
||||||
"@rushstack/heft": "^0.41.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@anticrm/core": "~0.6.11",
|
|
||||||
"@anticrm/model": "~0.6.0",
|
|
||||||
"@anticrm/platform": "~0.6.5",
|
|
||||||
"@anticrm/server-task": "~0.6.0",
|
|
||||||
"@anticrm/server-core": "~0.6.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
|
||||||
// Copyright © 2021 Hardcore Engineering Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License. You may
|
|
||||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
import { Builder } from '@anticrm/model'
|
|
||||||
|
|
||||||
import serverCore from '@anticrm/server-core'
|
|
||||||
import core from '@anticrm/core'
|
|
||||||
import serverTask from '@anticrm/server-task'
|
|
||||||
|
|
||||||
export function createModel (builder: Builder): void {
|
|
||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
|
||||||
trigger: serverTask.trigger.OnTask
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
|
|
||||||
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": "./src",
|
|
||||||
"outDir": "./lib",
|
|
||||||
}
|
|
||||||
}
|
|
@ -53,18 +53,22 @@ export { default } from './plugin'
|
|||||||
export const DOMAIN_TASK = 'task' as Domain
|
export const DOMAIN_TASK = 'task' as Domain
|
||||||
export const DOMAIN_STATE = 'state' as Domain
|
export const DOMAIN_STATE = 'state' as Domain
|
||||||
export const DOMAIN_KANBAN = 'kanban' as Domain
|
export const DOMAIN_KANBAN = 'kanban' as Domain
|
||||||
@Model(task.class.State, core.class.Doc, DOMAIN_STATE)
|
@Model(task.class.State, core.class.Doc, DOMAIN_STATE, [core.interface.DocWithRank])
|
||||||
export class TState extends TDoc implements State {
|
export class TState extends TDoc implements State {
|
||||||
@Prop(TypeString(), 'Title' as IntlString)
|
@Prop(TypeString(), 'Title' as IntlString)
|
||||||
title!: string
|
title!: string
|
||||||
|
|
||||||
color!: string
|
color!: string
|
||||||
|
|
||||||
|
declare rank: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.DoneState, core.class.Doc, DOMAIN_STATE)
|
@Model(task.class.DoneState, core.class.Doc, DOMAIN_STATE, [core.interface.DocWithRank])
|
||||||
export class TDoneState extends TDoc implements DoneState {
|
export class TDoneState extends TDoc implements DoneState {
|
||||||
@Prop(TypeString(), 'Title' as IntlString)
|
@Prop(TypeString(), 'Title' as IntlString)
|
||||||
title!: string
|
title!: string
|
||||||
|
|
||||||
|
declare rank: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.WonState, task.class.DoneState, DOMAIN_STATE)
|
@Model(task.class.WonState, task.class.DoneState, DOMAIN_STATE)
|
||||||
@ -78,7 +82,7 @@ export class TLostState extends TDoneState implements LostState {}
|
|||||||
*
|
*
|
||||||
* No domain is specified, since pure Tasks could not exists
|
* No domain is specified, since pure Tasks could not exists
|
||||||
*/
|
*/
|
||||||
@Model(task.class.Task, core.class.AttachedDoc, DOMAIN_TASK)
|
@Model(task.class.Task, core.class.AttachedDoc, DOMAIN_TASK, [core.interface.DocWithRank])
|
||||||
export class TTask extends TAttachedDoc implements Task {
|
export class TTask extends TAttachedDoc implements Task {
|
||||||
@Prop(TypeRef(task.class.State), 'State' as IntlString)
|
@Prop(TypeRef(task.class.State), 'State' as IntlString)
|
||||||
state!: Ref<State>
|
state!: Ref<State>
|
||||||
@ -91,6 +95,8 @@ export class TTask extends TAttachedDoc implements Task {
|
|||||||
|
|
||||||
// @Prop(TypeRef(contact.class.Employee), 'Assignee' as IntlString)
|
// @Prop(TypeRef(contact.class.Employee), 'Assignee' as IntlString)
|
||||||
assignee!: Ref<Employee> | null
|
assignee!: Ref<Employee> | null
|
||||||
|
|
||||||
|
declare rank: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.SpaceWithStates, core.class.Space)
|
@Model(task.class.SpaceWithStates, core.class.Space)
|
||||||
@ -136,7 +142,6 @@ export class TKanban extends TDoc implements Kanban {
|
|||||||
states!: Arr<Ref<State>>
|
states!: Arr<Ref<State>>
|
||||||
doneStates!: Arr<Ref<DoneState>>
|
doneStates!: Arr<Ref<DoneState>>
|
||||||
attachedTo!: Ref<Space>
|
attachedTo!: Ref<Space>
|
||||||
order!: Arr<Ref<Doc>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.KanbanTemplateSpace, core.class.Space, DOMAIN_MODEL)
|
@Model(task.class.KanbanTemplateSpace, core.class.Space, DOMAIN_MODEL)
|
||||||
@ -144,19 +149,23 @@ export class TKanbanTemplateSpace extends TSpace implements KanbanTemplateSpace
|
|||||||
icon!: AnyComponent
|
icon!: AnyComponent
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN)
|
@Model(task.class.StateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [core.interface.DocWithRank])
|
||||||
export class TStateTemplate extends TAttachedDoc implements StateTemplate {
|
export class TStateTemplate extends TAttachedDoc implements StateTemplate {
|
||||||
@Prop(TypeString(), 'Title' as IntlString)
|
@Prop(TypeString(), 'Title' as IntlString)
|
||||||
title!: string
|
title!: string
|
||||||
|
|
||||||
@Prop(TypeString(), 'Color' as IntlString)
|
@Prop(TypeString(), 'Color' as IntlString)
|
||||||
color!: string
|
color!: string
|
||||||
|
|
||||||
|
declare rank: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.DoneStateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN)
|
@Model(task.class.DoneStateTemplate, core.class.AttachedDoc, DOMAIN_KANBAN, [core.interface.DocWithRank])
|
||||||
export class TDoneStateTemplate extends TAttachedDoc implements DoneStateTemplate {
|
export class TDoneStateTemplate extends TAttachedDoc implements DoneStateTemplate {
|
||||||
@Prop(TypeString(), 'Title' as IntlString)
|
@Prop(TypeString(), 'Title' as IntlString)
|
||||||
title!: string
|
title!: string
|
||||||
|
|
||||||
|
declare rank: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(task.class.WonStateTemplate, task.class.DoneStateTemplate, DOMAIN_KANBAN)
|
@Model(task.class.WonStateTemplate, task.class.DoneStateTemplate, DOMAIN_KANBAN)
|
||||||
@ -170,9 +179,6 @@ export class TKanbanTemplate extends TDoc implements KanbanTemplate {
|
|||||||
@Prop(TypeString(), 'Title' as IntlString)
|
@Prop(TypeString(), 'Title' as IntlString)
|
||||||
title!: string
|
title!: string
|
||||||
|
|
||||||
states!: Arr<Ref<StateTemplate>>
|
|
||||||
doneStates!: Arr<Ref<DoneStateTemplate>>
|
|
||||||
|
|
||||||
@Prop(Collection(task.class.StateTemplate), 'States' as IntlString)
|
@Prop(Collection(task.class.StateTemplate), 'States' as IntlString)
|
||||||
statesC!: number
|
statesC!: number
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { Class, Doc, Domain, DOMAIN_TX, Ref, TxCUD, TxOperations } from '@anticrm/core'
|
import { AttachedDoc, Class, Client, Doc, DocWithRank, Domain, DOMAIN_TX, genRanks, Ref, Space, TxCUD, TxOperations } from '@anticrm/core'
|
||||||
import {
|
import {
|
||||||
MigrateOperation,
|
MigrateOperation,
|
||||||
MigrateUpdate,
|
MigrateUpdate,
|
||||||
@ -22,7 +22,7 @@ import {
|
|||||||
MigrationUpgradeClient
|
MigrationUpgradeClient
|
||||||
} from '@anticrm/model'
|
} from '@anticrm/model'
|
||||||
import core from '@anticrm/model-core'
|
import core from '@anticrm/model-core'
|
||||||
import { createProjectKanban } from '@anticrm/task'
|
import { createProjectKanban, KanbanTemplate } from '@anticrm/task'
|
||||||
import { DOMAIN_TASK, DOMAIN_STATE, DOMAIN_KANBAN } from '.'
|
import { DOMAIN_TASK, DOMAIN_STATE, DOMAIN_KANBAN } from '.'
|
||||||
import task from './plugin'
|
import task from './plugin'
|
||||||
|
|
||||||
@ -134,28 +134,148 @@ export const taskOperation: MigrateOperation = {
|
|||||||
|
|
||||||
console.log('View: Performing model upgrades')
|
console.log('View: Performing model upgrades')
|
||||||
|
|
||||||
const kanbans = (await client.findAll(task.class.Kanban, {})).filter((kanban) => kanban.doneStates == null)
|
await createMissingDoneStates(client, ops)
|
||||||
|
await updateRankItems({ client, ops, _class: task.class.State, extractOrder: (kanban) => kanban.states })
|
||||||
|
await updateRankItems({ client, ops, _class: task.class.DoneState, extractOrder: (kanban) => kanban.doneStates })
|
||||||
|
await updateRankItems({ client, ops, _class: task.class.Task, extractOrder: (kanban) => kanban.order })
|
||||||
|
await updateTemplateRankItems({ client, ops, _class: task.class.StateTemplate, extractOrder: (kanban) => kanban.states })
|
||||||
|
await updateTemplateRankItems({ client, ops, _class: task.class.DoneStateTemplate, extractOrder: (kanban) => kanban.doneStates })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
async function createMissingDoneStates (client: Client, ops: TxOperations): Promise<void> {
|
||||||
kanbans.map(async (kanban) => {
|
const spacesWithStates = await client.findAll(task.class.SpaceWithStates, {})
|
||||||
console.log(`Updating kanban: ${kanban._id}`)
|
const doneStates = await client.findAll(task.class.DoneState, {})
|
||||||
|
const spaceIdsWithDoneStates = new Set(doneStates.map(x => x.space))
|
||||||
|
const outdatedSpaces = spacesWithStates.filter((space) => !spaceIdsWithDoneStates.has(space._id))
|
||||||
|
|
||||||
|
const pairRanks = [...genRanks(2)]
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
outdatedSpaces
|
||||||
|
.map(async (space) => {
|
||||||
|
console.log(`Creating done states for space: ${space._id}`)
|
||||||
try {
|
try {
|
||||||
const doneStates = await Promise.all([
|
await Promise.all([
|
||||||
ops.createDoc(task.class.WonState, kanban.space, {
|
ops.createDoc(task.class.WonState, space._id, {
|
||||||
title: 'Won'
|
title: 'Won',
|
||||||
|
rank: pairRanks[0]
|
||||||
}),
|
}),
|
||||||
ops.createDoc(task.class.LostState, kanban.space, {
|
ops.createDoc(task.class.LostState, space._id, {
|
||||||
title: 'Lost'
|
title: 'Lost',
|
||||||
|
rank: pairRanks[1]
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
|
|
||||||
await ops.updateDoc(kanban._class, kanban.space, kanban._id, {
|
|
||||||
doneStates
|
|
||||||
})
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
)
|
}
|
||||||
|
|
||||||
|
async function updateRankItems<T extends DocWithRank> ({
|
||||||
|
client,
|
||||||
|
ops,
|
||||||
|
_class,
|
||||||
|
extractOrder
|
||||||
|
}: {
|
||||||
|
client: Client
|
||||||
|
ops: TxOperations
|
||||||
|
_class: Ref<Class<T>>
|
||||||
|
extractOrder: (kanban: any) => Ref<T>[]
|
||||||
|
}): Promise<void> {
|
||||||
|
const allItems = await client.findAll(_class, {})
|
||||||
|
const unorderedItems = allItems
|
||||||
|
.filter((item) => item.rank === undefined)
|
||||||
|
const groupedUnsortedItems = new Map<Ref<Space>, T[]>()
|
||||||
|
|
||||||
|
unorderedItems.forEach((item) => {
|
||||||
|
const existing = groupedUnsortedItems.get(item.space) ?? []
|
||||||
|
groupedUnsortedItems.set(item.space, [...existing, item])
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const [space, items] of groupedUnsortedItems.entries()) {
|
||||||
|
const kanban = await client.findOne(task.class.Kanban, { attachedTo: space })
|
||||||
|
|
||||||
|
if (kanban === undefined) {
|
||||||
|
console.error(`Failed to find kanban attached to space '${space}'`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const order = extractOrder(kanban)
|
||||||
|
|
||||||
|
if (order === undefined) {
|
||||||
|
console.error(`Kanban doesn't contain items order: ${kanban._id}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderedItems = order
|
||||||
|
.map((id) => items.find(x => x._id === id))
|
||||||
|
.filter((items): items is T => items !== undefined)
|
||||||
|
const ranks = genRanks(orderedItems.length)
|
||||||
|
|
||||||
|
for (const item of orderedItems) {
|
||||||
|
const rank = ranks.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
console.error('Failed to generate rank')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
await ops.updateDoc(item._class as Ref<Class<DocWithRank>>, item.space, item._id, { rank })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateTemplateRankItems<T extends DocWithRank & AttachedDoc> ({
|
||||||
|
client,
|
||||||
|
ops,
|
||||||
|
_class,
|
||||||
|
extractOrder
|
||||||
|
}: {
|
||||||
|
client: Client
|
||||||
|
ops: TxOperations
|
||||||
|
_class: Ref<Class<T>>
|
||||||
|
extractOrder: (kanban: any) => Ref<T>[]
|
||||||
|
}): Promise<void> {
|
||||||
|
const allItems = await client.findAll(_class, {})
|
||||||
|
const unorderedItems = allItems
|
||||||
|
.filter((state) => state.rank === undefined)
|
||||||
|
const groupedUnsortedItems = new Map<Ref<Doc>, T[]>()
|
||||||
|
|
||||||
|
unorderedItems.forEach((item) => {
|
||||||
|
const existing = groupedUnsortedItems.get(item.attachedTo) ?? []
|
||||||
|
groupedUnsortedItems.set(item.attachedTo, [...existing, item])
|
||||||
|
})
|
||||||
|
|
||||||
|
for (const [attachedTo, items] of groupedUnsortedItems.entries()) {
|
||||||
|
const kanban = await client.findOne(task.class.KanbanTemplate, { _id: attachedTo as Ref<KanbanTemplate> })
|
||||||
|
|
||||||
|
if (kanban === undefined) {
|
||||||
|
console.error(`Failed to find kanban '${attachedTo}'`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const order = extractOrder(kanban)
|
||||||
|
|
||||||
|
if (order === undefined) {
|
||||||
|
console.error(`Kanban doesn't contain items order: ${kanban._id}`)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderedItems = order
|
||||||
|
.map((id) => items.find(x => x._id === id))
|
||||||
|
.filter((items): items is T => items !== undefined)
|
||||||
|
const ranks = genRanks(orderedItems.length)
|
||||||
|
|
||||||
|
for (const item of orderedItems) {
|
||||||
|
const rank = ranks.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
console.error('Failed to generate rank')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
await ops.updateDoc(item._class as Ref<Class<DocWithRank>>, item.space, item._id, { rank })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anticrm/platform": "~0.6.5",
|
"@anticrm/platform": "~0.6.5",
|
||||||
"just-clone": "^3.2.1"
|
"just-clone": "^3.2.1",
|
||||||
|
"lexorank": "~1.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,3 +218,10 @@ export interface Space extends Doc {
|
|||||||
export interface Account extends Doc {
|
export interface Account extends Doc {
|
||||||
email: string
|
email: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface DocWithRank extends Doc {
|
||||||
|
rank: string
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
import type { Plugin, StatusCode } from '@anticrm/platform'
|
import type { Plugin, StatusCode } from '@anticrm/platform'
|
||||||
import { plugin } from '@anticrm/platform'
|
import { plugin } from '@anticrm/platform'
|
||||||
import type { Account, AnyAttribute, AttachedDoc, Class, Doc, Interface, Obj, PropertyType, Ref, Space, Timestamp, Type, Collection, RefTo } from './classes'
|
import type { Account, AnyAttribute, AttachedDoc, DocWithRank, 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'
|
import type { Tx, TxBulkWrite, TxCollectionCUD, TxCreateDoc, TxCUD, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +49,9 @@ export default plugin(coreId, {
|
|||||||
Collection: '' as Ref<Class<Collection<AttachedDoc>>>,
|
Collection: '' as Ref<Class<Collection<AttachedDoc>>>,
|
||||||
Bag: '' as Ref<Class<Type<Record<string, PropertyType>>>>
|
Bag: '' as Ref<Class<Type<Record<string, PropertyType>>>>
|
||||||
},
|
},
|
||||||
|
interface: {
|
||||||
|
DocWithRank: '' as Ref<Interface<DocWithRank>>
|
||||||
|
},
|
||||||
space: {
|
space: {
|
||||||
Tx: '' as Ref<Space>,
|
Tx: '' as Ref<Space>,
|
||||||
Model: '' as Ref<Space>
|
Model: '' as Ref<Space>
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import { LexoRank, LexoDecimal, LexoNumeralSystem36 } from 'lexorank'
|
||||||
|
import LexoRankBucket from 'lexorank/lib/lexoRank/lexoRankBucket'
|
||||||
|
|
||||||
import type { Doc, Ref, Account } from './classes'
|
import type { Doc, Ref, Account } from './classes'
|
||||||
|
|
||||||
function toHex (value: number, chars: number): string {
|
function toHex (value: number, chars: number): string {
|
||||||
@ -59,3 +62,30 @@ export function getCurrentAccount (): Account { return currentAccount }
|
|||||||
export function setCurrentAccount (account: Account): void {
|
export function setCurrentAccount (account: Account): void {
|
||||||
currentAccount = account
|
currentAccount = account
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export const genRanks = (count: number): Generator<string, void, unknown> =>
|
||||||
|
(function * () {
|
||||||
|
const sys = new LexoNumeralSystem36()
|
||||||
|
const base = 36
|
||||||
|
const max = base ** 6
|
||||||
|
const gap = LexoDecimal.parse(Math.trunc(max / (count + 2)).toString(base), sys)
|
||||||
|
let cur = LexoDecimal.parse('0', sys)
|
||||||
|
|
||||||
|
for (let i = 0; i < count; i++) {
|
||||||
|
cur = cur.add(gap)
|
||||||
|
yield new LexoRank(LexoRankBucket.BUCKET_0, cur).toString()
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export const calcRank = (prev?: { rank: string }, next?: { rank: string }): string => {
|
||||||
|
const a = prev?.rank !== undefined ? LexoRank.parse(prev.rank) : LexoRank.min()
|
||||||
|
const b = next?.rank !== undefined ? LexoRank.parse(next.rank) : LexoRank.max()
|
||||||
|
|
||||||
|
return a.between(b).toString()
|
||||||
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import contact, { Contact } from '@anticrm/contact'
|
import contact, { Contact } from '@anticrm/contact'
|
||||||
import { Data, Ref, Space } from '@anticrm/core'
|
import { calcRank, Data, Ref, SortingOrder, Space } from '@anticrm/core'
|
||||||
import { generateId } from '@anticrm/core'
|
import { generateId } from '@anticrm/core'
|
||||||
import { OK, Status } from '@anticrm/platform'
|
import { OK, Status } from '@anticrm/platform'
|
||||||
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
||||||
@ -52,6 +52,11 @@
|
|||||||
throw new Error('sequence object not found')
|
throw new Error('sequence object not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lastOne = await client.findOne(
|
||||||
|
lead.class.Lead,
|
||||||
|
{ state: state._id },
|
||||||
|
{ sort: { rank: SortingOrder.Descending } }
|
||||||
|
)
|
||||||
const incResult = await client.updateDoc(
|
const incResult = await client.updateDoc(
|
||||||
task.class.Sequence,
|
task.class.Sequence,
|
||||||
task.space.Sequence,
|
task.space.Sequence,
|
||||||
@ -70,7 +75,8 @@
|
|||||||
customer: customer!,
|
customer: customer!,
|
||||||
attachedTo: customer!,
|
attachedTo: customer!,
|
||||||
attachedToClass: contact.class.Contact,
|
attachedToClass: contact.class.Contact,
|
||||||
collection: 'leads'
|
collection: 'leads',
|
||||||
|
rank: calcRank(lastOne, undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.createDoc(lead.class.Lead, _space, value, leadId)
|
await client.createDoc(lead.class.Lead, _space, value, leadId)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import type { Contact } from '@anticrm/contact'
|
import type { Contact } from '@anticrm/contact'
|
||||||
import type { Class, Data, Doc, Ref, Space } from '@anticrm/core'
|
import { Class, Data, Doc, genRanks, Ref, Space } from '@anticrm/core'
|
||||||
import type { Asset, Plugin } from '@anticrm/platform'
|
import type { Asset, Plugin } from '@anticrm/platform'
|
||||||
import { plugin } from '@anticrm/platform'
|
import { plugin } from '@anticrm/platform'
|
||||||
import task, { DoneState, Kanban, KanbanTemplateSpace, SpaceWithStates, State, Task } from '@anticrm/task'
|
import task, { DoneState, Kanban, KanbanTemplateSpace, SpaceWithStates, State, Task } from '@anticrm/task'
|
||||||
@ -71,46 +71,55 @@ export async function createKanban (
|
|||||||
{ color: '#F28469', name: 'Contract conclusion' },
|
{ color: '#F28469', name: 'Contract conclusion' },
|
||||||
{ color: '#7C6FCD', name: 'Done' }
|
{ color: '#7C6FCD', name: 'Done' }
|
||||||
]
|
]
|
||||||
const ids: Array<Ref<State>> = []
|
const stateRank = genRanks(states.length)
|
||||||
for (const st of states) {
|
for (const st of states) {
|
||||||
const sid = (funnelId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref<State>
|
const sid = (funnelId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref<State>
|
||||||
|
const rank = stateRank.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
throw Error('Failed to generate rank')
|
||||||
|
}
|
||||||
|
|
||||||
await factory(
|
await factory(
|
||||||
task.class.State,
|
task.class.State,
|
||||||
funnelId,
|
funnelId,
|
||||||
{
|
{
|
||||||
title: st.name,
|
title: st.name,
|
||||||
color: st.color
|
color: st.color,
|
||||||
|
rank
|
||||||
},
|
},
|
||||||
sid
|
sid
|
||||||
)
|
)
|
||||||
ids.push(sid)
|
|
||||||
}
|
}
|
||||||
const rawDoneStates = [
|
const doneStates = [
|
||||||
{ class: task.class.WonState, title: 'Won' },
|
{ class: task.class.WonState, title: 'Won' },
|
||||||
{ class: task.class.LostState, title: 'Lost' }
|
{ class: task.class.LostState, title: 'Lost' }
|
||||||
]
|
]
|
||||||
const doneStates: Array<Ref<DoneState>> = []
|
const doneStateRank = genRanks(doneStates.length)
|
||||||
for (const st of rawDoneStates) {
|
for (const st of doneStates) {
|
||||||
|
const rank = doneStateRank.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
throw Error('Failed to generate rank')
|
||||||
|
}
|
||||||
|
|
||||||
const sid = (funnelId + '.done-state.' + st.title.toLowerCase().replace(' ', '_')) as Ref<DoneState>
|
const sid = (funnelId + '.done-state.' + st.title.toLowerCase().replace(' ', '_')) as Ref<DoneState>
|
||||||
await factory(
|
await factory(
|
||||||
st.class,
|
st.class,
|
||||||
funnelId,
|
funnelId,
|
||||||
{
|
{
|
||||||
title: st.title
|
title: st.title,
|
||||||
|
rank
|
||||||
},
|
},
|
||||||
sid
|
sid
|
||||||
)
|
)
|
||||||
doneStates.push(sid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await factory(
|
await factory(
|
||||||
task.class.Kanban,
|
task.class.Kanban,
|
||||||
funnelId,
|
funnelId,
|
||||||
{
|
{
|
||||||
attachedTo: funnelId,
|
attachedTo: funnelId
|
||||||
states: ids,
|
|
||||||
doneStates,
|
|
||||||
order: []
|
|
||||||
},
|
},
|
||||||
(funnelId + '.kanban') as Ref<Kanban>
|
(funnelId + '.kanban') as Ref<Kanban>
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Employee } from '@anticrm/contact'
|
import type { Employee } from '@anticrm/contact'
|
||||||
import contact from '@anticrm/contact'
|
import contact from '@anticrm/contact'
|
||||||
import type { Ref, Space } from '@anticrm/core'
|
import { Ref, SortingOrder, Space } from '@anticrm/core'
|
||||||
|
import { calcRank } from '@anticrm/core'
|
||||||
import { OK, Severity, Status } from '@anticrm/platform'
|
import { OK, Severity, Status } from '@anticrm/platform'
|
||||||
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
||||||
import type { Candidate } from '@anticrm/recruit'
|
import type { Candidate } from '@anticrm/recruit'
|
||||||
@ -50,6 +51,12 @@
|
|||||||
if (sequence === undefined) {
|
if (sequence === undefined) {
|
||||||
throw new Error('sequence object not found')
|
throw new Error('sequence object not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lastOne = await client.findOne(
|
||||||
|
recruit.class.Applicant,
|
||||||
|
{ state: state._id },
|
||||||
|
{ sort: { rank: SortingOrder.Descending } }
|
||||||
|
)
|
||||||
const incResult = await client.updateDoc(
|
const incResult = await client.updateDoc(
|
||||||
task.class.Sequence,
|
task.class.Sequence,
|
||||||
task.space.Sequence,
|
task.space.Sequence,
|
||||||
@ -59,7 +66,7 @@
|
|||||||
},
|
},
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
const id = await client.addCollection(
|
await client.addCollection(
|
||||||
recruit.class.Applicant,
|
recruit.class.Applicant,
|
||||||
_space,
|
_space,
|
||||||
candidate,
|
candidate,
|
||||||
@ -69,7 +76,8 @@
|
|||||||
state: state._id,
|
state: state._id,
|
||||||
doneState: null,
|
doneState: null,
|
||||||
number: incResult.object.sequence,
|
number: incResult.object.sequence,
|
||||||
assignee: assignee
|
assignee: assignee,
|
||||||
|
rank: calcRank(lastOne, undefined)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import core, { generateId } from '@anticrm/core'
|
import core, { generateId, genRanks } from '@anticrm/core'
|
||||||
import type { Ref } from '@anticrm/core'
|
import type { Ref } from '@anticrm/core'
|
||||||
import { AttributeEditor, createQuery, getClient } from '@anticrm/presentation'
|
import { AttributeEditor, createQuery, getClient } from '@anticrm/presentation'
|
||||||
import { CircleButton, IconAdd, IconMoreH, Label, showPopup } from '@anticrm/ui'
|
import { CircleButton, IconAdd, IconMoreH, Label, showPopup } from '@anticrm/ui'
|
||||||
@ -52,23 +52,22 @@
|
|||||||
const space = folder._id
|
const space = folder._id
|
||||||
|
|
||||||
const template = await client.createDoc(task.class.KanbanTemplate, space, {
|
const template = await client.createDoc(task.class.KanbanTemplate, space, {
|
||||||
states: [],
|
|
||||||
doneStates: [],
|
|
||||||
doneStatesC: 0,
|
doneStatesC: 0,
|
||||||
statesC: 0,
|
statesC: 0,
|
||||||
title: 'New Template'
|
title: 'New Template'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const ranks = [...genRanks(2)]
|
||||||
const doneStates = [
|
const doneStates = [
|
||||||
{
|
{
|
||||||
id: generateId<WonStateTemplate>(),
|
|
||||||
class: task.class.WonStateTemplate,
|
class: task.class.WonStateTemplate,
|
||||||
title: 'Won'
|
title: 'Won',
|
||||||
|
rank: ranks[0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: generateId<LostStateTemplate>(),
|
|
||||||
class: task.class.LostStateTemplate,
|
class: task.class.LostStateTemplate,
|
||||||
title: 'Lost'
|
title: 'Lost',
|
||||||
|
rank: ranks[1]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -80,19 +79,11 @@
|
|||||||
task.class.KanbanTemplate,
|
task.class.KanbanTemplate,
|
||||||
'doneStatesC',
|
'doneStatesC',
|
||||||
{
|
{
|
||||||
title: ds.title
|
title: ds.title,
|
||||||
},
|
rank: ds.rank
|
||||||
ds.id
|
}
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
for (const ds of doneStates) {
|
|
||||||
await client.updateDoc(task.class.KanbanTemplate, space, template, {
|
|
||||||
$push: {
|
|
||||||
doneStates: ds.id
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function select (item: KanbanTemplate) {
|
function select (item: KanbanTemplate) {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import contact, { Employee } from '@anticrm/contact'
|
import contact, { Employee } from '@anticrm/contact'
|
||||||
import type { AttachedData, Data, Doc, Ref, Space } from '@anticrm/core'
|
import { AttachedData, calcRank, Data, Doc, Ref, Space } from '@anticrm/core'
|
||||||
import { generateId } from '@anticrm/core'
|
import { generateId } from '@anticrm/core'
|
||||||
import { OK, Status } from '@anticrm/platform'
|
import { OK, Status } from '@anticrm/platform'
|
||||||
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
||||||
@ -63,6 +63,11 @@
|
|||||||
throw new Error('sequence object not found')
|
throw new Error('sequence object not found')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const lastOne = await client.findOne(
|
||||||
|
task.class.Task,
|
||||||
|
{ state: state._id },
|
||||||
|
{ sort: { rank: SortingOrder.Descending } }
|
||||||
|
)
|
||||||
const incResult = await client.updateDoc(
|
const incResult = await client.updateDoc(
|
||||||
task.class.Sequence,
|
task.class.Sequence,
|
||||||
task.space.Sequence,
|
task.space.Sequence,
|
||||||
@ -79,7 +84,8 @@
|
|||||||
assignee,
|
assignee,
|
||||||
number: (incResult as any).object.sequence,
|
number: (incResult as any).object.sequence,
|
||||||
doneState: null,
|
doneState: null,
|
||||||
state: state._id
|
state: state._id,
|
||||||
|
rank: calcRank(lastOne, undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.addCollection(task.class.Issue, _space, parent?._id ?? task.global.Task, parent?._class ?? task.class.Issue, 'tasks', value, taskId)
|
await client.addCollection(task.class.Issue, _space, parent?._id ?? task.global.Task, parent?._class ?? task.class.Issue, 'tasks', value, taskId)
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Ref, Doc } from '@anticrm/core'
|
import { Ref, Doc, SortingOrder, calcRank } from '@anticrm/core'
|
||||||
import { createQuery, getClient } from '@anticrm/presentation'
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
import type { Kanban, State, DoneState } from '@anticrm/task'
|
import type { Kanban, State, DoneState } from '@anticrm/task'
|
||||||
import task from '@anticrm/task'
|
import task from '@anticrm/task'
|
||||||
@ -33,45 +33,49 @@
|
|||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
function sort <T extends Doc> (order: Ref<T>[], items: T[]): T[] {
|
|
||||||
if (items.length === 0) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemMap = new Map(items.map(x => [x._id, x]))
|
|
||||||
const x = order
|
|
||||||
.map(id => itemMap.get(id))
|
|
||||||
.filter((x): x is T => x !== undefined)
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
const statesQ = createQuery()
|
const statesQ = createQuery()
|
||||||
$: statesQ.query(task.class.State, { _id: { $in: kanban.states ?? [] } }, result => { states = sort(kanban.states, result) })
|
$: statesQ.query(task.class.State, { space: kanban.space }, result => { states = result}, {
|
||||||
|
sort: {
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const doneStatesQ = createQuery()
|
const doneStatesQ = createQuery()
|
||||||
$: doneStatesQ.query(task.class.DoneState, { _id: { $in: kanban.doneStates } }, (result) => { doneStates = sort(kanban.doneStates, result) })
|
$: doneStatesQ.query(task.class.DoneState, { space: kanban.space }, (result) => { doneStates = result }, {
|
||||||
|
sort: {
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
async function onMove ({ detail: { stateID, position } }: { detail: { stateID: Ref<State>, position: number } }) {
|
async function onMove ({ detail: { stateID, position } }: { detail: { stateID: Ref<State>, position: number } }) {
|
||||||
client.updateDoc(kanban._class, kanban.space, kanban._id, {
|
const [prev, next] = [states[position - 1], states[position + 1]]
|
||||||
$move: {
|
const state = states.find((x) => x._id === stateID)
|
||||||
states: {
|
|
||||||
$value: stateID,
|
if (state === undefined) {
|
||||||
$position: position
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await client.updateDoc(
|
||||||
|
state._class,
|
||||||
|
state.space,
|
||||||
|
state._id,
|
||||||
|
{
|
||||||
|
rank: calcRank(prev, next)
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onAdd () {
|
async function onAdd () {
|
||||||
const state = await client.createDoc(task.class.State, kanban.space, {
|
const lastOne = await client.findOne(
|
||||||
|
task.class.State,
|
||||||
|
{ space: kanban.space },
|
||||||
|
{ sort: { rank: SortingOrder.Descending } }
|
||||||
|
)
|
||||||
|
|
||||||
|
await client.createDoc(task.class.State, kanban.space, {
|
||||||
title: 'New State',
|
title: 'New State',
|
||||||
color: '#7C6FCD'
|
color: '#7C6FCD',
|
||||||
})
|
rank: calcRank(lastOne, undefined)
|
||||||
await client.updateDoc(kanban._class, kanban.space, kanban._id, {
|
|
||||||
$push: {
|
|
||||||
states: state
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
import { Ref, Space, Doc, generateId } from '@anticrm/core'
|
import { Ref, Space, SortingOrder, calcRank } from '@anticrm/core'
|
||||||
import core from '@anticrm/core'
|
import core from '@anticrm/core'
|
||||||
import { createQuery, getClient } from '@anticrm/presentation'
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
import type { State, DoneStateTemplate, KanbanTemplate, StateTemplate } from '@anticrm/task'
|
import type { State, DoneStateTemplate, KanbanTemplate, StateTemplate } from '@anticrm/task'
|
||||||
@ -35,42 +35,49 @@
|
|||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
function sort <T extends Doc>(order: Ref<T>[], items: T[]): T[] {
|
|
||||||
if (items.length === 0) {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemMap = new Map(items.map(x => [x._id, x]))
|
|
||||||
const x = order
|
|
||||||
.map(id => itemMap.get(id))
|
|
||||||
.filter((x): x is T => x !== undefined)
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
const statesQ = createQuery()
|
const statesQ = createQuery()
|
||||||
$: statesQ.query(task.class.StateTemplate, { attachedTo: kanban._id }, result => { states = sort(kanban.states, result) })
|
$: statesQ.query(task.class.StateTemplate, { attachedTo: kanban._id }, result => { states = result }, {
|
||||||
|
sort: {
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const doneStatesQ = createQuery()
|
const doneStatesQ = createQuery()
|
||||||
$: doneStatesQ.query(task.class.DoneStateTemplate, { attachedTo: kanban._id }, (result) => { doneStates = sort(kanban.doneStates, result) })
|
$: doneStatesQ.query(task.class.DoneStateTemplate, { attachedTo: kanban._id }, (result) => { doneStates = result }, {
|
||||||
|
sort: {
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
let space: Space | undefined
|
let space: Space | undefined
|
||||||
const spaceQ = createQuery()
|
const spaceQ = createQuery()
|
||||||
$: spaceQ.query(core.class.Space, { _id: kanban.space }, (result) => { space = result[0] })
|
$: spaceQ.query(core.class.Space, { _id: kanban.space }, (result) => { space = result[0] })
|
||||||
|
|
||||||
async function onMove ({ detail: { stateID, position } }: { detail: { stateID: Ref<StateTemplate>, position: number } }) {
|
async function onMove ({ detail: { stateID, position } }: { detail: { stateID: Ref<StateTemplate>, position: number } }) {
|
||||||
client.updateDoc(kanban._class, kanban.space, kanban._id, {
|
const [prev, next] = [states[position - 1], states[position + 1]]
|
||||||
$move: {
|
const state = states.find((x) => x._id === stateID)
|
||||||
states: {
|
|
||||||
$value: stateID,
|
if (state === undefined) {
|
||||||
$position: position
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await client.updateDoc(
|
||||||
|
state._class,
|
||||||
|
state.space,
|
||||||
|
state._id,
|
||||||
|
{
|
||||||
|
rank: calcRank(prev, next)
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onAdd () {
|
async function onAdd () {
|
||||||
const stateID = generateId<StateTemplate>()
|
const lastOne = await client.findOne(
|
||||||
|
task.class.StateTemplate,
|
||||||
|
{ attachedTo: kanban._id },
|
||||||
|
{ sort: { rank: SortingOrder.Descending } }
|
||||||
|
)
|
||||||
|
|
||||||
await client.addCollection(
|
await client.addCollection(
|
||||||
task.class.StateTemplate,
|
task.class.StateTemplate,
|
||||||
kanban.space,
|
kanban.space,
|
||||||
@ -79,16 +86,10 @@
|
|||||||
'statesC',
|
'statesC',
|
||||||
{
|
{
|
||||||
title: 'New State',
|
title: 'New State',
|
||||||
color: '#7C6FCD'
|
color: '#7C6FCD',
|
||||||
},
|
rank: calcRank(lastOne, undefined)
|
||||||
stateID
|
|
||||||
)
|
|
||||||
|
|
||||||
await client.updateDoc(kanban._class, kanban.space, kanban._id, {
|
|
||||||
$push: {
|
|
||||||
states: stateID
|
|
||||||
}
|
}
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onDelete ({ detail: { state } }: { detail: { state: State }}) {
|
function onDelete ({ detail: { state } }: { detail: { state: State }}) {
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { AttachedDoc, Class, Doc, FindOptions, Ref } from '@anticrm/core'
|
import { AttachedDoc, calcRank, Class, Doc, DocumentUpdate, DocWithRank, FindOptions, Ref, SortingOrder } from '@anticrm/core'
|
||||||
import core from '@anticrm/core'
|
import core from '@anticrm/core'
|
||||||
import { getResource } from '@anticrm/platform'
|
import { getResource } from '@anticrm/platform'
|
||||||
import { createQuery, getClient } from '@anticrm/presentation'
|
import { createQuery, getClient } from '@anticrm/presentation'
|
||||||
@ -26,7 +26,7 @@
|
|||||||
import KanbanPanel from './KanbanPanel.svelte'
|
import KanbanPanel from './KanbanPanel.svelte'
|
||||||
// import KanbanPanelEmpty from './KanbanPanelEmpty.svelte'
|
// import KanbanPanelEmpty from './KanbanPanelEmpty.svelte'
|
||||||
|
|
||||||
type Item = Doc & { state: Ref<State>, doneState: Ref<DoneState> | null }
|
type Item = DocWithRank & { state: Ref<State>, doneState: Ref<DoneState> | null }
|
||||||
|
|
||||||
export let _class: Ref<Class<Item>>
|
export let _class: Ref<Class<Item>>
|
||||||
export let space: Ref<SpaceWithStates>
|
export let space: Ref<SpaceWithStates>
|
||||||
@ -36,50 +36,38 @@
|
|||||||
|
|
||||||
let kanban: Kanban
|
let kanban: Kanban
|
||||||
let states: State[] = []
|
let states: State[] = []
|
||||||
let rawStates: State[] = []
|
|
||||||
|
|
||||||
let objects: (Item | undefined)[] = []
|
let objects: Item[] = []
|
||||||
let rawObjects: Item[] = []
|
|
||||||
let kanbanStates: Ref<State>[] = []
|
|
||||||
let kanbanDoneStates: Ref<DoneState>[] = []
|
|
||||||
let wonState: WonState | undefined
|
let wonState: WonState | undefined
|
||||||
let lostState: LostState | undefined
|
let lostState: LostState | undefined
|
||||||
|
|
||||||
const kanbanQuery = createQuery()
|
const kanbanQuery = createQuery()
|
||||||
$: kanbanQuery.query(task.class.Kanban, { attachedTo: space }, result => { kanban = result[0] })
|
$: kanbanQuery.query(task.class.Kanban, { attachedTo: space }, result => { kanban = result[0] })
|
||||||
|
|
||||||
$: kanbanStates = kanban?.states ?? []
|
|
||||||
$: kanbanDoneStates = kanban?.doneStates ?? []
|
|
||||||
|
|
||||||
function sort (kanban: Kanban, states: State[]): State[] {
|
|
||||||
if (kanban === undefined || states.length === 0) { return [] }
|
|
||||||
const map = states.reduce((map, state) => { map.set(state._id, state); return map }, new Map<Ref<State>, State>())
|
|
||||||
return kanban.states.map(id => map.get(id) as State)
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortObjects<T extends Doc> (kanban: Kanban, objects: T[]): (T | undefined)[] {
|
|
||||||
if (kanban === undefined || objects.length === 0) { return [] }
|
|
||||||
const map = objects.reduce((map, doc) => { map.set(doc._id, doc); return map }, new Map<Ref<T>, T>())
|
|
||||||
return kanban.order
|
|
||||||
.map(id => map.get(id as Ref<T>))
|
|
||||||
}
|
|
||||||
|
|
||||||
const statesQuery = createQuery()
|
const statesQuery = createQuery()
|
||||||
$: if (kanbanStates.length > 0) statesQuery.query(task.class.State, { _id: { $in: kanbanStates } }, result => { rawStates = result })
|
$: if (kanban !== undefined) {
|
||||||
$: states = sort(kanban, rawStates)
|
statesQuery.query(task.class.State, { space: kanban.space }, result => { states = result }, {
|
||||||
|
sort: {
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const doneStatesQ = createQuery()
|
const doneStatesQ = createQuery()
|
||||||
$: if (kanbanDoneStates.length > 0) {
|
$: if (kanban !== undefined) {
|
||||||
doneStatesQ.query(task.class.DoneState, { _id: { $in: kanbanDoneStates } }, (result) => {
|
doneStatesQ.query(task.class.DoneState, { space: kanban.space }, (result) => {
|
||||||
wonState = result.find((x) => x._class === task.class.WonState)
|
wonState = result.find((x) => x._class === task.class.WonState)
|
||||||
lostState = result.find((x) => x._class === task.class.LostState)
|
lostState = result.find((x) => x._class === task.class.LostState)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = createQuery()
|
const query = createQuery()
|
||||||
$: query.query(_class, { space, doneState: null }, result => { rawObjects = result }, options)
|
$: query.query(_class, { space, doneState: null }, result => { objects = result }, {
|
||||||
|
...options,
|
||||||
$: objects = sortObjects(kanban, rawObjects)
|
sort: {
|
||||||
|
rank: SortingOrder.Ascending
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
function dragover (ev: MouseEvent, object: Item) {
|
function dragover (ev: MouseEvent, object: Item) {
|
||||||
if (dragCard !== object) {
|
if (dragCard !== object) {
|
||||||
@ -89,28 +77,44 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateItem (item: Item, update: DocumentUpdate<Item>) {
|
||||||
|
if (client.getHierarchy().isDerived(_class, core.class.AttachedDoc)) {
|
||||||
|
const adoc: AttachedDoc = item as Doc as AttachedDoc
|
||||||
|
await client.updateCollection(
|
||||||
|
_class,
|
||||||
|
space,
|
||||||
|
adoc._id as Ref<Doc> as Ref<AttachedDoc>,
|
||||||
|
adoc.attachedTo,
|
||||||
|
adoc.attachedToClass,
|
||||||
|
adoc.collection,
|
||||||
|
update
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
await client.updateDoc(item._class, item.space, item._id, update)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function move (state: Ref<State>) {
|
async function move (state: Ref<State>) {
|
||||||
const id = dragCard._id
|
let updates: DocumentUpdate<Item> = {}
|
||||||
|
|
||||||
if (dragCardInitialState !== state) {
|
if (dragCardInitialState !== state) {
|
||||||
if (client.getHierarchy().isDerived(_class, core.class.AttachedDoc)) {
|
updates = {
|
||||||
const adoc: AttachedDoc = dragCard as Doc as AttachedDoc
|
...updates,
|
||||||
// We need to update using updateCollection
|
state
|
||||||
client.updateCollection(_class, space, id as Ref<Doc> as Ref<AttachedDoc>, adoc.attachedTo, adoc.attachedToClass, adoc.collection, { state })
|
|
||||||
} else {
|
|
||||||
client.updateDoc<Task>(_class, space, id as Ref<Task>, { state })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dragCardInitialPosition !== dragCardEndPosition) {
|
if (dragCardInitialPosition !== dragCardEndPosition) {
|
||||||
client.updateDoc(task.class.Kanban, space, kanban._id, {
|
const [prev, next] = [objects[dragCardEndPosition - 1], objects[dragCardEndPosition + 1]]
|
||||||
$move: {
|
|
||||||
order: {
|
updates = {
|
||||||
$value: id,
|
...updates,
|
||||||
$position: dragCardEndPosition
|
rank: calcRank(prev, next)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
if (Object.keys(updates).length > 0) {
|
||||||
|
await updateItem(dragCard, updates)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,25 +132,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const onDone = (state: DoneState) => async () => {
|
const onDone = (state: DoneState) => async () => {
|
||||||
if (client.getHierarchy().isDerived(_class, core.class.AttachedDoc)) {
|
|
||||||
const adoc: AttachedDoc = dragCard as Doc as AttachedDoc
|
|
||||||
await client.updateCollection<Doc, Task>(
|
|
||||||
_class,
|
|
||||||
space,
|
|
||||||
adoc._id as Ref<Task>,
|
|
||||||
adoc.attachedTo,
|
|
||||||
adoc.attachedToClass,
|
|
||||||
adoc.collection,
|
|
||||||
{ doneState: state._id }
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
await client.updateDoc(dragCard._class, dragCard.space, dragCard._id, {
|
|
||||||
doneState: state._id
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
isDragging = false
|
isDragging = false
|
||||||
hoveredDoneState = undefined
|
hoveredDoneState = undefined
|
||||||
|
await updateItem(dragCard, { doneState: state._id })
|
||||||
}
|
}
|
||||||
|
|
||||||
let isDragging = false
|
let isDragging = false
|
||||||
@ -174,7 +162,7 @@
|
|||||||
}}>
|
}}>
|
||||||
<!-- <KanbanCardEmpty label={'Create new application'} /> -->
|
<!-- <KanbanCardEmpty label={'Create new application'} /> -->
|
||||||
{#each objects as object, j (object)}
|
{#each objects as object, j (object)}
|
||||||
{#if object !== undefined && object.state === state._id}
|
{#if object.state === state._id}
|
||||||
<div
|
<div
|
||||||
class="step-tb75"
|
class="step-tb75"
|
||||||
on:dragover|preventDefault={(ev) => {
|
on:dragover|preventDefault={(ev) => {
|
||||||
@ -226,11 +214,9 @@
|
|||||||
class="flex-grow flex-center done-item"
|
class="flex-grow flex-center done-item"
|
||||||
class:hovered={hoveredDoneState === lostState._id}
|
class:hovered={hoveredDoneState === lostState._id}
|
||||||
on:dragenter={() => {
|
on:dragenter={() => {
|
||||||
console.log('enter')
|
|
||||||
hoveredDoneState = lostState?._id
|
hoveredDoneState = lostState?._id
|
||||||
}}
|
}}
|
||||||
on:dragleave={() => {
|
on:dragleave={() => {
|
||||||
console.log('leave')
|
|
||||||
hoveredDoneState = undefined
|
hoveredDoneState = undefined
|
||||||
}}
|
}}
|
||||||
on:dragover|preventDefault={() => {}}
|
on:dragover|preventDefault={() => {}}
|
||||||
|
@ -14,8 +14,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import type { Employee } from '@anticrm/contact'
|
import type { Employee } from '@anticrm/contact'
|
||||||
import type { AttachedDoc, Class, Client, Data, Doc, Mixin, Ref, Space, TxOperations } from '@anticrm/core'
|
import { AttachedDoc, Class, Client, Data, Doc, DocWithRank, genRanks, Mixin, Ref, Space, TxOperations } from '@anticrm/core'
|
||||||
import { Arr } from '@anticrm/core'
|
|
||||||
import type { Asset, Plugin } from '@anticrm/platform'
|
import type { Asset, Plugin } from '@anticrm/platform'
|
||||||
import { plugin } from '@anticrm/platform'
|
import { plugin } from '@anticrm/platform'
|
||||||
import type { AnyComponent } from '@anticrm/ui'
|
import type { AnyComponent } from '@anticrm/ui'
|
||||||
@ -26,7 +25,7 @@ import { ViewletDescriptor } from '@anticrm/view'
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface State extends Doc {
|
export interface State extends DocWithRank {
|
||||||
title: string
|
title: string
|
||||||
color: string
|
color: string
|
||||||
}
|
}
|
||||||
@ -34,7 +33,7 @@ export interface State extends Doc {
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface DoneState extends Doc {
|
export interface DoneState extends DocWithRank {
|
||||||
title: string
|
title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ export interface LostState extends DoneState {}
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export interface Task extends AttachedDoc {
|
export interface Task extends AttachedDoc, DocWithRank {
|
||||||
state: Ref<State>
|
state: Ref<State>
|
||||||
doneState: Ref<DoneState> | null
|
doneState: Ref<DoneState> | null
|
||||||
number: number
|
number: number
|
||||||
@ -95,9 +94,6 @@ export interface KanbanCard extends Class<Doc> {
|
|||||||
*/
|
*/
|
||||||
export interface Kanban extends Doc {
|
export interface Kanban extends Doc {
|
||||||
attachedTo: Ref<Space>
|
attachedTo: Ref<Space>
|
||||||
states: Arr<Ref<State>>
|
|
||||||
doneStates: Arr<Ref<DoneState>>
|
|
||||||
order: Arr<Ref<Doc>>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,8 +129,6 @@ export interface LostStateTemplate extends DoneStateTemplate, LostState {}
|
|||||||
*/
|
*/
|
||||||
export interface KanbanTemplate extends Doc {
|
export interface KanbanTemplate extends Doc {
|
||||||
title: string
|
title: string
|
||||||
states: Arr<Ref<StateTemplate>>
|
|
||||||
doneStates: Arr<Ref<DoneStateTemplate>>
|
|
||||||
statesC: number
|
statesC: number
|
||||||
doneStatesC: number
|
doneStatesC: number
|
||||||
}
|
}
|
||||||
@ -209,47 +203,56 @@ export async function createProjectKanban (
|
|||||||
{ color: '#A5D179', name: 'Done' },
|
{ color: '#A5D179', name: 'Done' },
|
||||||
{ color: '#F28469', name: 'Invalid' }
|
{ color: '#F28469', name: 'Invalid' }
|
||||||
]
|
]
|
||||||
const ids: Array<Ref<State>> = []
|
const stateRank = genRanks(states.length)
|
||||||
for (const st of states) {
|
for (const st of states) {
|
||||||
|
const rank = stateRank.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
throw Error('Failed to generate rank')
|
||||||
|
}
|
||||||
|
|
||||||
const sid = (projectId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref<State>
|
const sid = (projectId + '.state.' + st.name.toLowerCase().replace(' ', '_')) as Ref<State>
|
||||||
await factory(
|
await factory(
|
||||||
task.class.State,
|
task.class.State,
|
||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
title: st.name,
|
title: st.name,
|
||||||
color: st.color
|
color: st.color,
|
||||||
|
rank
|
||||||
},
|
},
|
||||||
sid
|
sid
|
||||||
)
|
)
|
||||||
ids.push(sid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawDoneStates = [
|
const doneStates = [
|
||||||
{ class: task.class.WonState, title: 'Won' },
|
{ class: task.class.WonState, title: 'Won' },
|
||||||
{ class: task.class.LostState, title: 'Lost' }
|
{ class: task.class.LostState, title: 'Lost' }
|
||||||
]
|
]
|
||||||
const doneStates: Array<Ref<DoneState>> = []
|
const doneStateRank = genRanks(doneStates.length)
|
||||||
for (const st of rawDoneStates) {
|
for (const st of doneStates) {
|
||||||
|
const rank = doneStateRank.next().value
|
||||||
|
|
||||||
|
if (rank === undefined) {
|
||||||
|
throw Error('Failed to generate rank')
|
||||||
|
}
|
||||||
|
|
||||||
const sid = (projectId + '.done-state.' + st.title.toLowerCase().replace(' ', '_')) as Ref<DoneState>
|
const sid = (projectId + '.done-state.' + st.title.toLowerCase().replace(' ', '_')) as Ref<DoneState>
|
||||||
await factory(
|
await factory(
|
||||||
st.class,
|
st.class,
|
||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
title: st.title
|
title: st.title,
|
||||||
|
rank
|
||||||
},
|
},
|
||||||
sid
|
sid
|
||||||
)
|
)
|
||||||
doneStates.push(sid)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await factory(
|
await factory(
|
||||||
task.class.Kanban,
|
task.class.Kanban,
|
||||||
projectId,
|
projectId,
|
||||||
{
|
{
|
||||||
attachedTo: projectId,
|
attachedTo: projectId
|
||||||
states: ids,
|
|
||||||
doneStates,
|
|
||||||
order: []
|
|
||||||
},
|
},
|
||||||
(projectId + '.kanban') as Ref<Kanban>
|
(projectId + '.kanban') as Ref<Kanban>
|
||||||
)
|
)
|
||||||
@ -260,18 +263,19 @@ export async function createProjectKanban (
|
|||||||
*/
|
*/
|
||||||
export async function createKanban (client: Client & TxOperations, attachedTo: Ref<Space>, templateId?: Ref<KanbanTemplate>): Promise<Ref<Kanban>> {
|
export async function createKanban (client: Client & TxOperations, attachedTo: Ref<Space>, templateId?: Ref<KanbanTemplate>): Promise<Ref<Kanban>> {
|
||||||
if (templateId === undefined) {
|
if (templateId === undefined) {
|
||||||
|
const ranks = [...genRanks(2)]
|
||||||
|
await Promise.all([
|
||||||
|
client.createDoc(task.class.WonState, attachedTo, {
|
||||||
|
title: 'Won',
|
||||||
|
rank: ranks[0]
|
||||||
|
}),
|
||||||
|
client.createDoc(task.class.LostState, attachedTo, {
|
||||||
|
title: 'Lost',
|
||||||
|
rank: ranks[1]
|
||||||
|
})
|
||||||
|
])
|
||||||
return await client.createDoc(task.class.Kanban, attachedTo, {
|
return await client.createDoc(task.class.Kanban, attachedTo, {
|
||||||
attachedTo,
|
attachedTo
|
||||||
states: [],
|
|
||||||
doneStates: await Promise.all([
|
|
||||||
client.createDoc(task.class.WonState, attachedTo, {
|
|
||||||
title: 'Won'
|
|
||||||
}),
|
|
||||||
client.createDoc(task.class.LostState, attachedTo, {
|
|
||||||
title: 'Lost'
|
|
||||||
})
|
|
||||||
]),
|
|
||||||
order: []
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,37 +286,34 @@ export async function createKanban (client: Client & TxOperations, attachedTo: R
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tmplStates = await client.findAll(task.class.StateTemplate, { attachedTo: template._id })
|
const tmplStates = await client.findAll(task.class.StateTemplate, { attachedTo: template._id })
|
||||||
const states = await Promise.all(
|
await Promise.all(
|
||||||
template.states
|
tmplStates.map(async (state) => await client.createDoc(
|
||||||
.map((id) => tmplStates.find((x) => x._id === id))
|
task.class.State,
|
||||||
.filter((tstate): tstate is StateTemplate => tstate !== undefined)
|
attachedTo,
|
||||||
.map(async (state) => await client.createDoc(task.class.State, attachedTo, { color: state.color, title: state.title }))
|
{
|
||||||
)
|
color: state.color,
|
||||||
|
title: state.title,
|
||||||
|
rank: state.rank
|
||||||
|
})))
|
||||||
|
|
||||||
const doneClassMap = new Map<Ref<Class<DoneStateTemplate>>, Ref<Class<DoneState>>>([
|
const doneClassMap = new Map<Ref<Class<DoneStateTemplate>>, Ref<Class<DoneState>>>([
|
||||||
[task.class.WonStateTemplate, task.class.WonState],
|
[task.class.WonStateTemplate, task.class.WonState],
|
||||||
[task.class.LostStateTemplate, task.class.LostState]
|
[task.class.LostStateTemplate, task.class.LostState]
|
||||||
])
|
])
|
||||||
const tmplDoneStates = await client.findAll(task.class.DoneStateTemplate, { attachedTo: template._id })
|
const tmplDoneStates = await client.findAll(task.class.DoneStateTemplate, { attachedTo: template._id })
|
||||||
const doneStates = (await Promise.all(
|
await Promise.all(
|
||||||
template.doneStates
|
tmplDoneStates.map(async (state) => {
|
||||||
.map((id) => tmplDoneStates.find((x) => x._id === id))
|
const cl = doneClassMap.get(state._class)
|
||||||
.filter((tstate): tstate is DoneStateTemplate => tstate !== undefined)
|
|
||||||
.map(async (state) => {
|
|
||||||
const cl = doneClassMap.get(state._class)
|
|
||||||
|
|
||||||
if (cl === undefined) {
|
if (cl === undefined) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return await client.createDoc(cl, attachedTo, { title: state.title })
|
return await client.createDoc(cl, attachedTo, { title: state.title, rank: state.rank })
|
||||||
})
|
})
|
||||||
)).filter((x): x is Ref<DoneState> => x !== undefined)
|
)
|
||||||
|
|
||||||
return await client.createDoc(task.class.Kanban, attachedTo, {
|
return await client.createDoc(task.class.Kanban, attachedTo, {
|
||||||
attachedTo,
|
attachedTo
|
||||||
states,
|
|
||||||
doneStates,
|
|
||||||
order: []
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
15
rush.json
15
rush.json
@ -736,21 +736,6 @@
|
|||||||
"projectFolder": "server/recruit-resources",
|
"projectFolder": "server/recruit-resources",
|
||||||
"shouldPublish": true
|
"shouldPublish": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"packageName": "@anticrm/server-task-resources",
|
|
||||||
"projectFolder": "server/task-resources",
|
|
||||||
"shouldPublish": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"packageName": "@anticrm/server-task",
|
|
||||||
"projectFolder": "server/task",
|
|
||||||
"shouldPublish": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"packageName": "@anticrm/model-server-task",
|
|
||||||
"projectFolder": "models/server-task",
|
|
||||||
"shouldPublish": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"packageName": "@anticrm/mongo",
|
"packageName": "@anticrm/mongo",
|
||||||
"projectFolder": "server/mongo",
|
"projectFolder": "server/mongo",
|
||||||
|
@ -43,8 +43,6 @@
|
|||||||
"@anticrm/server-recruit": "~0.6.0",
|
"@anticrm/server-recruit": "~0.6.0",
|
||||||
"@anticrm/server-recruit-resources": "~0.6.0",
|
"@anticrm/server-recruit-resources": "~0.6.0",
|
||||||
"@anticrm/mongo": "~0.6.1",
|
"@anticrm/mongo": "~0.6.1",
|
||||||
"@anticrm/elastic": "~0.6.0",
|
"@anticrm/elastic": "~0.6.0"
|
||||||
"@anticrm/server-task": "~0.6.0",
|
|
||||||
"@anticrm/server-task-resources": "~0.6.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import type { DbConfiguration, DbAdapter } from '@anticrm/server-core'
|
|||||||
import { addLocation } from '@anticrm/platform'
|
import { addLocation } from '@anticrm/platform'
|
||||||
import { serverChunterId } from '@anticrm/server-chunter'
|
import { serverChunterId } from '@anticrm/server-chunter'
|
||||||
import { serverRecruitId } from '@anticrm/server-recruit'
|
import { serverRecruitId } from '@anticrm/server-recruit'
|
||||||
import { serverViewId } from '@anticrm/server-task'
|
|
||||||
|
|
||||||
class NullDbAdapter implements DbAdapter {
|
class NullDbAdapter implements DbAdapter {
|
||||||
async init (model: Tx[]): Promise<void> {}
|
async init (model: Tx[]): Promise<void> {}
|
||||||
@ -42,7 +41,6 @@ async function createNullAdapter (hierarchy: Hierarchy, url: string, db: string,
|
|||||||
export function start (dbUrl: string, fullTextUrl: string, port: number, host?: string): () => void {
|
export function start (dbUrl: string, fullTextUrl: string, port: number, host?: string): () => void {
|
||||||
addLocation(serverChunterId, () => import('@anticrm/server-chunter-resources'))
|
addLocation(serverChunterId, () => import('@anticrm/server-chunter-resources'))
|
||||||
addLocation(serverRecruitId, () => import('@anticrm/server-recruit-resources'))
|
addLocation(serverRecruitId, () => import('@anticrm/server-recruit-resources'))
|
||||||
addLocation(serverViewId, () => import('@anticrm/server-task-resources'))
|
|
||||||
|
|
||||||
return startJsonRpc((workspace: string) => {
|
return startJsonRpc((workspace: string) => {
|
||||||
const conf: DbConfiguration = {
|
const conf: DbConfiguration = {
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: './tsconfig.json'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
*
|
|
||||||
!/lib/**
|
|
||||||
!CHANGELOG.md
|
|
||||||
/lib/**/__tests__/
|
|
@ -1,18 +0,0 @@
|
|||||||
// The "rig.json" file directs tools to look for their config files in an external package.
|
|
||||||
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
|
|
||||||
{
|
|
||||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Required) The name of the rig package to inherit from.
|
|
||||||
* It should be an NPM package name with the "-rig" suffix.
|
|
||||||
*/
|
|
||||||
"rigPackageName": "@anticrm/platform-rig"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Optional) Selects a config profile from the rig package. The name must consist of
|
|
||||||
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
|
|
||||||
* If omitted, then the "default" profile will be used."
|
|
||||||
*/
|
|
||||||
// "rigProfile": "your-profile-name"
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@anticrm/server-task-resources",
|
|
||||||
"version": "0.6.0",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"author": "Anticrm Platform Contributors",
|
|
||||||
"license": "EPL-2.0",
|
|
||||||
"scripts": {
|
|
||||||
"build": "heft build",
|
|
||||||
"build:watch": "tsc",
|
|
||||||
"lint:fix": "eslint --fix src",
|
|
||||||
"lint": "eslint src",
|
|
||||||
"format": "prettier --write src && eslint --fix src"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@anticrm/platform-rig": "~0.6.0",
|
|
||||||
"@types/heft-jest": "^1.0.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
||||||
"eslint-plugin-import": "^2.25.3",
|
|
||||||
"eslint-plugin-promise": "^5.1.1",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"eslint": "^7.32.0",
|
|
||||||
"@typescript-eslint/parser": "^5.4.0",
|
|
||||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
|
||||||
"prettier": "^2.4.1",
|
|
||||||
"@rushstack/heft": "^0.41.1",
|
|
||||||
"typescript": "^4.3.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@anticrm/core": "~0.6.12",
|
|
||||||
"@anticrm/platform": "~0.6.5",
|
|
||||||
"@anticrm/server-core": "~0.6.1",
|
|
||||||
"@anticrm/task": "~0.6.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
|
||||||
// Copyright © 2021 Hardcore Engineering Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License. You may
|
|
||||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
import type { Tx, TxFactory, Doc, TxCreateDoc, TxRemoveDoc, TxCollectionCUD, AttachedDoc } from '@anticrm/core'
|
|
||||||
import type { FindAll } from '@anticrm/server-core'
|
|
||||||
|
|
||||||
import core, { Hierarchy } from '@anticrm/core'
|
|
||||||
import task, { Kanban, Task, State } from '@anticrm/task'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export async function OnTask (tx: Tx, txFactory: TxFactory, findAll: FindAll<Doc>, hierarchy: Hierarchy): Promise<Tx[]> {
|
|
||||||
if (tx._class === core.class.TxCollectionCUD) {
|
|
||||||
tx = (tx as TxCollectionCUD<Doc, AttachedDoc>).tx
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) {
|
|
||||||
const createTx = tx as TxCreateDoc<Task>
|
|
||||||
if (hierarchy.isDerived(createTx.objectClass, task.class.Task)) {
|
|
||||||
const state = (await (findAll as FindAll<State>)(task.class.State, { space: createTx.objectSpace }))[0] // TODO: make FindAll generic
|
|
||||||
if (state === undefined) {
|
|
||||||
throw new Error('OnTask: state not found')
|
|
||||||
}
|
|
||||||
const kanban = (await (findAll as FindAll<Kanban>)(task.class.Kanban, { attachedTo: createTx.objectSpace }))[0]
|
|
||||||
if (kanban === undefined) {
|
|
||||||
throw new Error('OnTask: kanban not found')
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
txFactory.createTxUpdateDoc(createTx.objectClass, createTx.objectSpace, createTx.objectId, { state: state._id }),
|
|
||||||
txFactory.createTxUpdateDoc(task.class.Kanban, createTx.objectSpace, kanban._id, { $push: { order: createTx.objectId } })
|
|
||||||
]
|
|
||||||
}
|
|
||||||
} else if (tx._class === core.class.TxRemoveDoc) {
|
|
||||||
const removeTx = tx as TxRemoveDoc<Task>
|
|
||||||
if (hierarchy.isDerived(removeTx.objectClass, task.class.Task)) {
|
|
||||||
const kanban = (await (findAll as FindAll<Kanban>)(task.class.Kanban, { attachedTo: removeTx.objectSpace }))[0]
|
|
||||||
if (kanban === undefined) {
|
|
||||||
throw new Error('OnTask: kanban not found')
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
txFactory.createTxUpdateDoc(task.class.Kanban, removeTx.objectSpace, kanban._id, { $pull: { order: removeTx.objectId } })
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
||||||
export default async () => ({
|
|
||||||
trigger: {
|
|
||||||
OnTask
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
|
|
||||||
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": "./src",
|
|
||||||
"outDir": "./lib"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
|
|
||||||
parserOptions: {
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
project: './tsconfig.json'
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
*
|
|
||||||
!/lib/**
|
|
||||||
!CHANGELOG.md
|
|
||||||
/lib/**/__tests__/
|
|
@ -1,18 +0,0 @@
|
|||||||
// The "rig.json" file directs tools to look for their config files in an external package.
|
|
||||||
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
|
|
||||||
{
|
|
||||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Required) The name of the rig package to inherit from.
|
|
||||||
* It should be an NPM package name with the "-rig" suffix.
|
|
||||||
*/
|
|
||||||
"rigPackageName": "@anticrm/platform-rig"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (Optional) Selects a config profile from the rig package. The name must consist of
|
|
||||||
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
|
|
||||||
* If omitted, then the "default" profile will be used."
|
|
||||||
*/
|
|
||||||
// "rigProfile": "your-profile-name"
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@anticrm/server-task",
|
|
||||||
"version": "0.6.0",
|
|
||||||
"main": "lib/index.js",
|
|
||||||
"author": "Anticrm Platform Contributors",
|
|
||||||
"license": "EPL-2.0",
|
|
||||||
"scripts": {
|
|
||||||
"build": "heft build",
|
|
||||||
"build:watch": "tsc",
|
|
||||||
"lint:fix": "eslint --fix src",
|
|
||||||
"lint": "eslint src",
|
|
||||||
"format": "prettier --write src && eslint --fix src"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@anticrm/platform-rig": "~0.6.0",
|
|
||||||
"@types/heft-jest": "^1.0.2",
|
|
||||||
"@types/node": "^16.4.10",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
|
||||||
"eslint-plugin-import": "^2.25.3",
|
|
||||||
"eslint-plugin-promise": "^5.1.1",
|
|
||||||
"eslint-plugin-node": "^11.1.0",
|
|
||||||
"eslint": "^7.32.0",
|
|
||||||
"@typescript-eslint/parser": "^5.4.0",
|
|
||||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
|
||||||
"prettier": "^2.4.1",
|
|
||||||
"@rushstack/heft": "^0.41.1",
|
|
||||||
"typescript": "^4.3.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@anticrm/core": "~0.6.11",
|
|
||||||
"@anticrm/platform": "~0.6.5",
|
|
||||||
"@anticrm/server-core": "~0.6.0"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
|
||||||
// Copyright © 2021, 2022 Hardcore Engineering Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License. You may
|
|
||||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
//
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
import type { Resource, Plugin } from '@anticrm/platform'
|
|
||||||
import { plugin } from '@anticrm/platform'
|
|
||||||
import type { TriggerFunc } from '@anticrm/server-core'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export const serverViewId = 'server-task' as Plugin
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export default plugin(serverViewId, {
|
|
||||||
trigger: {
|
|
||||||
OnTask: '' as Resource<TriggerFunc>
|
|
||||||
}
|
|
||||||
})
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
|
|
||||||
|
|
||||||
"compilerOptions": {
|
|
||||||
"rootDir": "./src",
|
|
||||||
"outDir": "./lib",
|
|
||||||
"esModuleInterop": true
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user