mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 11:42:30 +03:00
Rework reviews (#1156)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
c37d6b8e0e
commit
a4af938871
@ -13,6 +13,9 @@ specifiers:
|
||||
'@rush-temp/attachment': file:./projects/attachment.tgz
|
||||
'@rush-temp/attachment-assets': file:./projects/attachment-assets.tgz
|
||||
'@rush-temp/attachment-resources': file:./projects/attachment-resources.tgz
|
||||
'@rush-temp/calendar': file:./projects/calendar.tgz
|
||||
'@rush-temp/calendar-assets': file:./projects/calendar-assets.tgz
|
||||
'@rush-temp/calendar-resources': file:./projects/calendar-resources.tgz
|
||||
'@rush-temp/chunter': file:./projects/chunter.tgz
|
||||
'@rush-temp/chunter-assets': file:./projects/chunter-assets.tgz
|
||||
'@rush-temp/chunter-resources': file:./projects/chunter-resources.tgz
|
||||
@ -50,6 +53,7 @@ specifiers:
|
||||
'@rush-temp/model-activity': file:./projects/model-activity.tgz
|
||||
'@rush-temp/model-all': file:./projects/model-all.tgz
|
||||
'@rush-temp/model-attachment': file:./projects/model-attachment.tgz
|
||||
'@rush-temp/model-calendar': file:./projects/model-calendar.tgz
|
||||
'@rush-temp/model-chunter': file:./projects/model-chunter.tgz
|
||||
'@rush-temp/model-contact': file:./projects/model-contact.tgz
|
||||
'@rush-temp/model-core': file:./projects/model-core.tgz
|
||||
@ -167,7 +171,6 @@ specifiers:
|
||||
'@types/koa__cors': ^3.0.3
|
||||
'@types/mime-types': ~2.1.1
|
||||
'@types/minio': ~7.0.11
|
||||
'@types/node': ~16.11.12
|
||||
'@types/pdfkit': ~0.12.3
|
||||
'@types/prosemirror-model': ~1.16.0
|
||||
'@types/request': ~2.48.8
|
||||
@ -257,6 +260,9 @@ dependencies:
|
||||
'@rush-temp/attachment': file:projects/attachment.tgz
|
||||
'@rush-temp/attachment-assets': file:projects/attachment-assets.tgz_typescript@4.5.4
|
||||
'@rush-temp/attachment-resources': file:projects/attachment-resources.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
'@rush-temp/calendar': file:projects/calendar.tgz
|
||||
'@rush-temp/calendar-assets': file:projects/calendar-assets.tgz_typescript@4.5.4
|
||||
'@rush-temp/calendar-resources': file:projects/calendar-resources.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
'@rush-temp/chunter': file:projects/chunter.tgz
|
||||
'@rush-temp/chunter-assets': file:projects/chunter-assets.tgz_typescript@4.5.4
|
||||
'@rush-temp/chunter-resources': file:projects/chunter-resources.tgz_096c09b0b673a57c275d9767a12070b1
|
||||
@ -269,11 +275,11 @@ dependencies:
|
||||
'@rush-temp/core': file:projects/core.tgz
|
||||
'@rush-temp/dev-account': file:projects/dev-account.tgz
|
||||
'@rush-temp/dev-client-resources': file:projects/dev-client-resources.tgz
|
||||
'@rush-temp/dev-server': file:projects/dev-server.tgz_@types+node@16.11.14
|
||||
'@rush-temp/dev-server': file:projects/dev-server.tgz
|
||||
'@rush-temp/dev-storage': file:projects/dev-storage.tgz
|
||||
'@rush-temp/devmodel': file:projects/devmodel.tgz_typescript@4.5.4
|
||||
'@rush-temp/devmodel-resources': file:projects/devmodel-resources.tgz_6cae74ea501386c76c405ad0408e0339
|
||||
'@rush-temp/elastic': file:projects/elastic.tgz_@types+node@16.11.14
|
||||
'@rush-temp/elastic': file:projects/elastic.tgz
|
||||
'@rush-temp/front': file:projects/front.tgz
|
||||
'@rush-temp/generator': file:projects/generator.tgz
|
||||
'@rush-temp/gmail': file:projects/gmail.tgz
|
||||
@ -294,6 +300,7 @@ dependencies:
|
||||
'@rush-temp/model-activity': file:projects/model-activity.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-all': file:projects/model-all.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-attachment': file:projects/model-attachment.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-calendar': file:projects/model-calendar.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-chunter': file:projects/model-chunter.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-contact': file:projects/model-contact.tgz_typescript@4.5.4
|
||||
'@rush-temp/model-core': file:projects/model-core.tgz_typescript@4.5.4
|
||||
@ -411,7 +418,6 @@ dependencies:
|
||||
'@types/koa__cors': 3.1.0
|
||||
'@types/mime-types': 2.1.1
|
||||
'@types/minio': 7.0.11
|
||||
'@types/node': 16.11.14
|
||||
'@types/pdfkit': 0.12.3
|
||||
'@types/prosemirror-model': 1.16.0
|
||||
'@types/request': 2.48.8
|
||||
@ -478,7 +484,7 @@ dependencies:
|
||||
svgo-loader: 3.0.0
|
||||
toposort: 2.0.2
|
||||
ts-loader: 9.2.6_typescript@4.5.4+webpack@5.65.0
|
||||
ts-node: 10.5.0_5d12c2add188ff0e728b4ade3dacd39b
|
||||
ts-node: 10.5.0_typescript@4.5.4
|
||||
typescript: 4.5.4
|
||||
uuid: 8.3.2
|
||||
webpack: 5.65.0_9def3870c80213359789f9191dbd286a
|
||||
@ -8563,7 +8569,7 @@ packages:
|
||||
dependencies:
|
||||
import-cwd: 3.0.0
|
||||
lilconfig: 2.0.4
|
||||
ts-node: 10.5.0_5d12c2add188ff0e728b4ade3dacd39b
|
||||
ts-node: 10.5.0_typescript@4.5.4
|
||||
yaml: 1.10.2
|
||||
dev: false
|
||||
|
||||
@ -10452,6 +10458,36 @@ packages:
|
||||
yn: 3.1.1
|
||||
dev: false
|
||||
|
||||
/ts-node/10.5.0_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-6kEJKwVxAJ35W4akuiysfKwKmjkbYxwQMTBaAxo9KKAx/Yd26mPUyhGz3ji+EsJoAgrLqVsYHNuuYwQe22lbtw==}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@swc/core': '>=1.2.50'
|
||||
'@swc/wasm': '>=1.2.50'
|
||||
'@types/node': '*'
|
||||
typescript: '>=2.7'
|
||||
peerDependenciesMeta:
|
||||
'@swc/core':
|
||||
optional: true
|
||||
'@swc/wasm':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.7.0
|
||||
'@tsconfig/node10': 1.0.8
|
||||
'@tsconfig/node12': 1.0.9
|
||||
'@tsconfig/node14': 1.0.1
|
||||
'@tsconfig/node16': 1.0.2
|
||||
acorn: 8.6.0
|
||||
acorn-walk: 8.2.0
|
||||
arg: 4.1.3
|
||||
create-require: 1.1.1
|
||||
diff: 4.0.2
|
||||
make-error: 1.3.6
|
||||
typescript: 4.5.4
|
||||
v8-compile-cache-lib: 3.0.0
|
||||
yn: 3.1.1
|
||||
dev: false
|
||||
|
||||
/tsconfig-paths/3.12.0:
|
||||
resolution: {integrity: sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==}
|
||||
dependencies:
|
||||
@ -11416,6 +11452,83 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/calendar-assets.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-muyoJ0EuKPUpsAEL1bLgdR90OqIoohgdfUFDwyWP1qmtAe9k1my76bJSIiU1JSfybyssHYiR8jpM/SuIonWg3Q==, tarball: file:projects/calendar-assets.tgz}
|
||||
id: file:projects/calendar-assets.tgz
|
||||
name: '@rush-temp/calendar-assets'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@types/node': 16.11.14
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/calendar-resources.tgz_096c09b0b673a57c275d9767a12070b1:
|
||||
resolution: {integrity: sha512-UZIMmHCGB+XoLDkyP1A/+ot4oc0POAPYCVOtiPI3vQtVWuTIPquMM4pPX3HxkvfpWqblXburuJx3j18rfA5Mgw==, tarball: file:projects/calendar-resources.tgz}
|
||||
id: file:projects/calendar-resources.tgz
|
||||
name: '@rush-temp/calendar-resources'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
eslint-plugin-svelte3: 3.2.1_eslint@7.32.0+svelte@3.44.3
|
||||
prettier: 2.5.1
|
||||
prettier-plugin-svelte: 2.5.1_prettier@2.5.1+svelte@3.44.3
|
||||
sass: 1.45.0
|
||||
svelte: 3.44.3
|
||||
svelte-check: 2.3.0_4374c622c67ed7479ff0e44c29d09bce
|
||||
svelte-loader: 3.1.2_svelte@3.44.3
|
||||
svelte-preprocess: 4.10.3_14d64cad431e31f100de7363af24a44f
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- coffeescript
|
||||
- less
|
||||
- node-sass
|
||||
- postcss
|
||||
- postcss-load-config
|
||||
- pug
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/calendar.tgz:
|
||||
resolution: {integrity: sha512-mN4GfaHpyGzuLV59eFw3c3R6p2r4ewEumsIhzyifgeXaXSD9Bnm06LG5LvFgF5G5TmDquUFcIq88w3Zzd20cQA==, tarball: file:projects/calendar.tgz}
|
||||
name: '@rush-temp/calendar'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/chunter-assets.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-2EQgdQ62vXKYpX9iOtOaCRt1GZliFiJpPPBZbOMHjaeWLye+/zYXlffkBbjVUSfR894cBlrtZBVRapjJU2T3uA==, tarball: file:projects/chunter-assets.tgz}
|
||||
id: file:projects/chunter-assets.tgz
|
||||
@ -11713,9 +11826,8 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/dev-server.tgz_@types+node@16.11.14:
|
||||
file:projects/dev-server.tgz:
|
||||
resolution: {integrity: sha512-pv0DpcojPAreq3xXTnbl3Rj2UwEy97zRPmXU2lJsM0pKc6dVpmicD+/Bq4laIWx5qhvzfLurbwjBV4/0mLeuYw==, tarball: file:projects/dev-server.tgz}
|
||||
id: file:projects/dev-server.tgz
|
||||
name: '@rush-temp/dev-server'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
@ -11730,7 +11842,7 @@ packages:
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
jwt-simple: 0.5.6
|
||||
prettier: 2.5.1
|
||||
ts-node: 10.5.0_5d12c2add188ff0e728b4ade3dacd39b
|
||||
ts-node: 10.5.0_typescript@4.5.4
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
@ -11815,9 +11927,8 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/elastic.tgz_@types+node@16.11.14:
|
||||
file:projects/elastic.tgz:
|
||||
resolution: {integrity: sha512-CF8tie/n08Slnvw40pFZnaS4j/2JPQzs2xAxakNqpokb5x3ci9e0z2gzXNB6otQElk1NxW69QDHqNme+jHqWPA==, tarball: file:projects/elastic.tgz}
|
||||
id: file:projects/elastic.tgz
|
||||
name: '@rush-temp/elastic'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
@ -11832,7 +11943,7 @@ packages:
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
ts-node: 10.5.0_5d12c2add188ff0e728b4ade3dacd39b
|
||||
ts-node: 10.5.0_typescript@4.5.4
|
||||
typescript: 4.5.4
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
@ -12305,7 +12416,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-all.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-Jll+Wp4p6/OjdvtbTqAGKbMUkOoAai5Se2+CSIOteRB6dDTgtlwy95fzQv2o5RHIBBiQXLQ2Csb8KgAluzTJ6w==, tarball: file:projects/model-all.tgz}
|
||||
resolution: {integrity: sha512-LprNHSPgySvlj/zl9bkeSZ7Uh1wWyPPkQBW6knjBBD3cizpFpxPGBrSQnhDe/RP0uj6azKRYWWUcAPFOYe4TvQ==, tarball: file:projects/model-all.tgz}
|
||||
id: file:projects/model-all.tgz
|
||||
name: '@rush-temp/model-all'
|
||||
version: 0.0.0
|
||||
@ -12350,6 +12461,27 @@ packages:
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/model-calendar.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-sI97CjbxdgK1qWGDrBViWm65NY+vwFzt1s94cGheRJP8CL/GqJNuaSyrJv0pqjfZgK6Z3IkcUq2ZUSSHwD+1gQ==, tarball: file:projects/model-calendar.tgz}
|
||||
id: file:projects/model-calendar.tgz
|
||||
name: '@rush-temp/model-calendar'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@rushstack/heft': 0.41.8
|
||||
'@types/heft-jest': 1.0.2
|
||||
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
|
||||
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
|
||||
eslint: 7.32.0
|
||||
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
|
||||
eslint-plugin-import: 2.25.3_eslint@7.32.0
|
||||
eslint-plugin-node: 11.1.0_eslint@7.32.0
|
||||
eslint-plugin-promise: 5.2.0_eslint@7.32.0
|
||||
prettier: 2.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
- typescript
|
||||
dev: false
|
||||
|
||||
file:projects/model-chunter.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-bbKuovYnIkpRkU0YhE2x6UEx2gvwKM/OkCj7SH4rQhVR3vjdWisBd0/P71NsNdfcdR7Hl4fhHSNVZfW6KNNPog==, tarball: file:projects/model-chunter.tgz}
|
||||
id: file:projects/model-chunter.tgz
|
||||
@ -12540,7 +12672,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-recruit.tgz_typescript@4.5.4:
|
||||
resolution: {integrity: sha512-t2mSCyFnB+YfsxFuAu0J8hNVhM+GP5SjiVevMe8tft+dCyyLeMpAJxTdEKkvRx6jV6yyxyPUmqZMAQCmm/pvuA==, tarball: file:projects/model-recruit.tgz}
|
||||
resolution: {integrity: sha512-TtzOJVyFh5KY3RmQUTUUqeemhDDo/14R1RRrbQ7FoYun9yl+lv5b00OUuIbZ4rtYSJQLhiJaXFbZbxHl6pr3mA==, tarball: file:projects/model-recruit.tgz}
|
||||
id: file:projects/model-recruit.tgz
|
||||
name: '@rush-temp/model-recruit'
|
||||
version: 0.0.0
|
||||
@ -13235,7 +13367,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/prod.tgz_a07ec81d4d975778878ca12202ea119e:
|
||||
resolution: {integrity: sha512-R0Y2btm9DPFvRRGYAGC6ilCIcE5t+p2trcdARVBxyi+tH4XwcXZSt0NJJe+57vpiwkCV8hYPa2fI+Eul1wdrpQ==, tarball: file:projects/prod.tgz}
|
||||
resolution: {integrity: sha512-mxkGGtPp108JHMkmnEgKKPNVrihu3xVv1wZqY/HTWhZ+v8Ct5RG92+Yg6NBhEsLmqCBBPTAHY/JapGi1oF9bWg==, tarball: file:projects/prod.tgz}
|
||||
id: file:projects/prod.tgz
|
||||
name: '@rush-temp/prod'
|
||||
version: 0.0.0
|
||||
@ -13329,7 +13461,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/recruit-resources.tgz_096c09b0b673a57c275d9767a12070b1:
|
||||
resolution: {integrity: sha512-EexKsB2ZRQ/VxlTABy5b5g3MLR51+549IMWW4g6+Xb/ZR6MZKCT6ocWPRgULW64EO3CTOJ37nIlXijj6Z/fPKw==, tarball: file:projects/recruit-resources.tgz}
|
||||
resolution: {integrity: sha512-nvxkMBBQ9fPzCtIIQbUOlLaV+4wulVAKLg2iBOR5RuEiKZK/kwItpbzv0u6mS5Vb7/yFRp0GsRM+G7rv1tiGfg==, tarball: file:projects/recruit-resources.tgz}
|
||||
id: file:projects/recruit-resources.tgz
|
||||
name: '@rush-temp/recruit-resources'
|
||||
version: 0.0.0
|
||||
@ -13366,7 +13498,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/recruit.tgz:
|
||||
resolution: {integrity: sha512-wAgHbMEy+KVBNhYTiPdcBnN0O7BAsfxLMxK/gcjM1pkqeLbCzJ/SpRNMFpC2K0/TU+qsPqCzK3zx0VSvFXH05A==, tarball: file:projects/recruit.tgz}
|
||||
resolution: {integrity: sha512-VAcfan3RLB0bq8DYryIS1waf0EiSSjbd1mdyq0IqMvlp9b8OBUGf0mOCfHDhkno9C4nf9fN8kCUDk9y82LfjZg==, tarball: file:projects/recruit.tgz}
|
||||
name: '@rush-temp/recruit'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
|
@ -82,7 +82,7 @@ services:
|
||||
- mongodb
|
||||
- elastic
|
||||
- minio
|
||||
- apm-server
|
||||
# - apm-server
|
||||
ports:
|
||||
- 3333:3333
|
||||
environment:
|
||||
@ -94,41 +94,41 @@ services:
|
||||
- MINIO_ENDPOINT=minio
|
||||
- MINIO_ACCESS_KEY=minioadmin
|
||||
- MINIO_SECRET_KEY=minioadmin
|
||||
- APM_SERVER_URL=http://apm-server:8200
|
||||
apm-server:
|
||||
image: docker.elastic.co/apm/apm-server:7.14.2
|
||||
depends_on:
|
||||
- "elastic"
|
||||
- "kibana"
|
||||
cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"]
|
||||
cap_drop: ["ALL"]
|
||||
ports:
|
||||
- 8200:8200
|
||||
command: |
|
||||
apm-server -e
|
||||
-E apm-server.rum.enabled=true
|
||||
-E setup.kibana.host=kibana:5601
|
||||
-E setup.template.settings.index.number_of_replicas=0
|
||||
-E apm-server.kibana.enabled=true
|
||||
-E apm-server.kibana.host=kibana:5601
|
||||
-E output.elasticsearch.hosts=["elastic:9200"]
|
||||
healthcheck:
|
||||
interval: 10s
|
||||
retries: 12
|
||||
test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:8200/
|
||||
kibana:
|
||||
image: docker.elastic.co/kibana/kibana:7.14.2
|
||||
depends_on:
|
||||
- "elastic"
|
||||
environment:
|
||||
ELASTICSEARCH_URL: http://elastic:9200
|
||||
ELASTICSEARCH_HOSTS: http://elastic:9200
|
||||
ports:
|
||||
- 5601:5601
|
||||
healthcheck:
|
||||
interval: 10s
|
||||
retries: 20
|
||||
test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:5601/api/status
|
||||
# - APM_SERVER_URL=http://apm-server:8200
|
||||
# apm-server:
|
||||
# image: docker.elastic.co/apm/apm-server:7.14.2
|
||||
# depends_on:
|
||||
# - "elastic"
|
||||
# - "kibana"
|
||||
# cap_add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"]
|
||||
# cap_drop: ["ALL"]
|
||||
# ports:
|
||||
# - 8200:8200
|
||||
# command: |
|
||||
# apm-server -e
|
||||
# -E apm-server.rum.enabled=true
|
||||
# -E setup.kibana.host=kibana:5601
|
||||
# -E setup.template.settings.index.number_of_replicas=0
|
||||
# -E apm-server.kibana.enabled=true
|
||||
# -E apm-server.kibana.host=kibana:5601
|
||||
# -E output.elasticsearch.hosts=["elastic:9200"]
|
||||
# healthcheck:
|
||||
# interval: 10s
|
||||
# retries: 12
|
||||
# test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:8200/
|
||||
# kibana:
|
||||
# image: docker.elastic.co/kibana/kibana:7.14.2
|
||||
# depends_on:
|
||||
# - "elastic"
|
||||
# environment:
|
||||
# ELASTICSEARCH_URL: http://elastic:9200
|
||||
# ELASTICSEARCH_HOSTS: http://elastic:9200
|
||||
# ports:
|
||||
# - 5601:5601
|
||||
# healthcheck:
|
||||
# interval: 10s
|
||||
# retries: 20
|
||||
# test: curl --write-out 'HTTP %{http_code}' --fail --silent --output /dev/null http://localhost:5601/api/status
|
||||
|
||||
volumes:
|
||||
db:
|
||||
|
@ -119,6 +119,9 @@
|
||||
"@anticrm/server-recruit": "~0.6.0",
|
||||
"@anticrm/server-recruit-resources": "~0.6.0",
|
||||
"@anticrm/server-task": "~0.6.0",
|
||||
"@anticrm/server-task-resources": "~0.6.0"
|
||||
"@anticrm/server-task-resources": "~0.6.0",
|
||||
"@anticrm/calendar": "~0.6.0",
|
||||
"@anticrm/calendar-assets": "~0.6.0",
|
||||
"@anticrm/calendar-resources": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import { inventoryId } from '@anticrm/inventory'
|
||||
import { templatesId } from '@anticrm/templates'
|
||||
import { notificationId } from '@anticrm/notification'
|
||||
import { tagsId } from '@anticrm/tags'
|
||||
import { calendarId } from '@anticrm/calendar'
|
||||
import rekoni from '@anticrm/rekoni'
|
||||
|
||||
import '@anticrm/login-assets'
|
||||
@ -54,6 +55,7 @@ import '@anticrm/inventory-assets'
|
||||
import '@anticrm/templates-assets'
|
||||
import '@anticrm/notification-assets'
|
||||
import '@anticrm/tags-assets'
|
||||
import '@anticrm/calendar-assets'
|
||||
|
||||
import { setMetadata } from '@anticrm/platform'
|
||||
export async function configurePlatform() {
|
||||
@ -95,4 +97,5 @@ export async function configurePlatform() {
|
||||
addLocation(templatesId, () => import(/* webpackChunkName: "templates" */ '@anticrm/templates-resources'))
|
||||
addLocation(notificationId, () => import(/* webpackChunkName: "notification" */ '@anticrm/notification-resources'))
|
||||
addLocation(tagsId, () => import(/* webpackChunkName: "tags" */ '@anticrm/tags-resources'))
|
||||
addLocation(calendarId, () => import(/* webpackChunkName: "calendar" */ '@anticrm/calendar-resources'))
|
||||
}
|
||||
|
@ -61,6 +61,7 @@
|
||||
"@anticrm/model-notification": "~0.6.0",
|
||||
"@anticrm/model-text-editor": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.16",
|
||||
"@anticrm/model-tags": "~0.6.0"
|
||||
"@anticrm/model-tags": "~0.6.0",
|
||||
"@anticrm/model-calendar": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ import { createModel as viewModel } from '@anticrm/model-view'
|
||||
import { createModel as workbenchModel } from '@anticrm/model-workbench'
|
||||
import { createModel as notificationModel } from '@anticrm/model-notification'
|
||||
import { createModel as tagsModel } from '@anticrm/model-tags'
|
||||
import { createModel as calendarModel } from '@anticrm/model-calendar'
|
||||
|
||||
export const version: Data<Version> = jsonVersion as Data<Version>
|
||||
|
||||
@ -77,6 +78,7 @@ const builders = [
|
||||
serverNotificationModel,
|
||||
serveSettingModel,
|
||||
tagsModel,
|
||||
calendarModel,
|
||||
serverChunterModel,
|
||||
serverInventoryModel,
|
||||
serverLeadModel,
|
||||
|
7
models/calendar/.eslintrc.js
Normal file
7
models/calendar/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
4
models/calendar/.npmignore
Normal file
4
models/calendar/.npmignore
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
18
models/calendar/config/rig.json
Normal file
18
models/calendar/config/rig.json
Normal file
@ -0,0 +1,18 @@
|
||||
// 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"
|
||||
}
|
46
models/calendar/package.json
Normal file
46
models/calendar/package.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "@anticrm/model-calendar",
|
||||
"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/ui": "~0.6.0",
|
||||
"@anticrm/view": "~0.6.0",
|
||||
"@anticrm/model-attachment": "~0.6.0",
|
||||
"@anticrm/model-task": "~0.6.0",
|
||||
"@anticrm/calendar": "~0.6.0",
|
||||
"@anticrm/calendar-resources": "~0.6.0",
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/model-core": "~0.6.0",
|
||||
"@anticrm/model-view": "~0.6.0",
|
||||
"@anticrm/model-workbench": "~0.6.1",
|
||||
"@anticrm/activity": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1",
|
||||
"@anticrm/model-chunter": "~0.6.0",
|
||||
"@anticrm/model-contact": "~0.6.1",
|
||||
"@anticrm/contact": "~0.6.5"
|
||||
}
|
||||
}
|
90
models/calendar/src/index.ts
Normal file
90
models/calendar/src/index.ts
Normal file
@ -0,0 +1,90 @@
|
||||
//
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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 { Calendar, Event } from '@anticrm/calendar'
|
||||
import { Employee } from '@anticrm/contact'
|
||||
import type { Domain, Markup, Ref, Timestamp } from '@anticrm/core'
|
||||
import { IndexKind } from '@anticrm/core'
|
||||
import { Builder, Collection, Index, Model, Prop, TypeDate, TypeMarkup, TypeString, UX } from '@anticrm/model'
|
||||
import attachment from '@anticrm/model-attachment'
|
||||
import chunter from '@anticrm/model-chunter'
|
||||
import contact from '@anticrm/model-contact'
|
||||
import core, { TAttachedDoc } from '@anticrm/model-core'
|
||||
import { TSpaceWithStates } from '@anticrm/model-task'
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
import calendar from './plugin'
|
||||
|
||||
export * from '@anticrm/calendar'
|
||||
|
||||
export const DOMAIN_CALENDAR = 'calendar' as Domain
|
||||
|
||||
@Model(calendar.class.Calendar, core.class.Space)
|
||||
@UX(calendar.string.Calendar, calendar.icon.Calendar)
|
||||
export class TCalendar extends TSpaceWithStates implements Calendar {}
|
||||
|
||||
@Model(calendar.class.Event, core.class.AttachedDoc, DOMAIN_CALENDAR)
|
||||
export class TEvent extends TAttachedDoc implements Event {
|
||||
@Prop(TypeString(), calendar.string.Title)
|
||||
@Index(IndexKind.FullText)
|
||||
title!: string
|
||||
|
||||
@Prop(TypeString(), calendar.string.EventNumber)
|
||||
number!: number
|
||||
|
||||
@Prop(TypeMarkup(), calendar.string.Description)
|
||||
@Index(IndexKind.FullText)
|
||||
description!: Markup
|
||||
|
||||
@Prop(TypeString(), calendar.string.Location, calendar.icon.Location)
|
||||
@Index(IndexKind.FullText)
|
||||
location?: string
|
||||
|
||||
@Prop(TypeDate(true), calendar.string.Date)
|
||||
date!: Timestamp
|
||||
|
||||
@Prop(TypeDate(true), calendar.string.DueTo)
|
||||
dueDate!: Timestamp
|
||||
|
||||
@Prop(Collection(attachment.class.Attachment), attachment.string.Attachments)
|
||||
attachments?: number
|
||||
|
||||
@Prop(Collection(chunter.class.Comment), chunter.string.Comments)
|
||||
comments?: number
|
||||
|
||||
@Prop(Collection(contact.class.Employee), calendar.string.Participants)
|
||||
participants!: Ref<Employee>[]
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createModel(TCalendar, TEvent)
|
||||
|
||||
builder.createDoc(workbench.class.Application, core.space.Model, {
|
||||
label: calendar.string.ApplicationLabelCalendar,
|
||||
icon: calendar.icon.Calendar,
|
||||
hidden: true,
|
||||
navigatorModel: {
|
||||
spaces: [
|
||||
{
|
||||
label: calendar.string.Calendars,
|
||||
spaceClass: calendar.class.Calendar,
|
||||
addSpaceLabel: calendar.string.CreateCalendar,
|
||||
createComponent: calendar.component.CreateCalendar
|
||||
}
|
||||
]
|
||||
}
|
||||
}, calendar.app.Calendar)
|
||||
}
|
||||
|
||||
export default calendar
|
31
models/calendar/src/plugin.ts
Normal file
31
models/calendar/src/plugin.ts
Normal file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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 { calendarId } from '@anticrm/calendar'
|
||||
import calendar from '@anticrm/calendar-resources/src/plugin'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
|
||||
export default mergeIds(calendarId, calendar, {
|
||||
component: {
|
||||
CreateCalendar: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
ApplicationLabelCalendar: '' as IntlString
|
||||
},
|
||||
space: {
|
||||
}
|
||||
})
|
8
models/calendar/tsconfig.json
Normal file
8
models/calendar/tsconfig.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ export default mergeIds(coreId, core, {
|
||||
Name: '' as IntlString,
|
||||
Description: '' as IntlString,
|
||||
Private: '' as IntlString,
|
||||
Archived: '' as IntlString
|
||||
Archived: '' as IntlString,
|
||||
ClassLabel: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
Timestamp,
|
||||
Type, Version
|
||||
} from '@anticrm/core'
|
||||
import { Index, Model, Prop, TypeRef, TypeString, TypeTimestamp } from '@anticrm/model'
|
||||
import { Index, Model, Prop, TypeIntlString, TypeRef, TypeString, TypeTimestamp } from '@anticrm/model'
|
||||
import type { IntlString } from '@anticrm/platform'
|
||||
import core from './component'
|
||||
|
||||
@ -70,7 +70,10 @@ export class TAttachedDoc extends TDoc implements AttachedDoc {
|
||||
@Model(core.class.Class, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TClass extends TDoc implements Class<Obj> {
|
||||
kind!: ClassifierKind
|
||||
|
||||
@Prop(TypeIntlString(), core.string.ClassLabel)
|
||||
label!: IntlString
|
||||
|
||||
extends!: Ref<Class<Obj>>
|
||||
domain!: Domain
|
||||
}
|
||||
@ -101,6 +104,9 @@ export class TType extends TObj implements Type<any> {
|
||||
@Model(core.class.TypeString, core.class.Type)
|
||||
export class TTypeString extends TType {}
|
||||
|
||||
@Model(core.class.TypeIntlString, core.class.Type)
|
||||
export class TTypeIntlString extends TType {}
|
||||
|
||||
@Model(core.class.TypeNumber, core.class.Type)
|
||||
export class TTypeNumber extends TType {}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import {
|
||||
TRefTo,
|
||||
TType,
|
||||
TTypeBoolean,
|
||||
TTypeDate, TTypeMarkup, TTypeNumber, TTypeString, TTypeTimestamp,
|
||||
TTypeDate, TTypeIntlString, TTypeMarkup, TTypeNumber, TTypeString, TTypeTimestamp,
|
||||
TVersion
|
||||
} from './core'
|
||||
import { TAccount, TSpace } from './security'
|
||||
@ -80,6 +80,7 @@ export function createModel (builder: Builder): void {
|
||||
TTypeDate,
|
||||
TArrOf,
|
||||
TVersion,
|
||||
TTypeNumber
|
||||
TTypeNumber,
|
||||
TTypeIntlString
|
||||
)
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
"@anticrm/model-task": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1",
|
||||
"@anticrm/model-presentation": "~0.6.0",
|
||||
"@anticrm/model-calendar": "~0.6.0",
|
||||
"@anticrm/model-tags": "~0.6.0",
|
||||
"@anticrm/skillset": "^0.6.0"
|
||||
}
|
||||
|
@ -303,6 +303,10 @@ export function createModel (builder: Builder): void {
|
||||
presenter: recruit.component.VacancyPresenter
|
||||
})
|
||||
|
||||
builder.mixin(recruit.class.ReviewCategory, core.class.Class, view.mixin.AttributePresenter, {
|
||||
presenter: recruit.component.ReviewCategoryPresenter
|
||||
})
|
||||
|
||||
builder.mixin(recruit.class.Applicant, core.class.Class, view.mixin.ObjectValidator, {
|
||||
validator: recruit.validator.ApplicantValidator
|
||||
})
|
||||
@ -366,6 +370,14 @@ export function createModel (builder: Builder): void {
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: recruit.class.ReviewCategory,
|
||||
action: task.action.UnarchiveSpace,
|
||||
query: {
|
||||
archived: true
|
||||
}
|
||||
})
|
||||
|
||||
builder.createDoc(
|
||||
view.class.Action,
|
||||
core.space.Model,
|
||||
|
@ -17,6 +17,7 @@ import { Person } from '@anticrm/contact'
|
||||
import core, { AttachedDoc, Class, Doc, DocumentQuery, DOMAIN_TX, MixinData, Ref, TxCollectionCUD, TxCreateDoc, TxMixin, TxOperations, TxUpdateDoc } from '@anticrm/core'
|
||||
import { createOrUpdate, MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model'
|
||||
import { DOMAIN_ATTACHMENT } from '@anticrm/model-attachment'
|
||||
import { DOMAIN_CALENDAR } from '@anticrm/model-calendar'
|
||||
import { DOMAIN_COMMENT } from '@anticrm/model-chunter'
|
||||
import contact, { DOMAIN_CONTACT } from '@anticrm/model-contact'
|
||||
import tags, { DOMAIN_TAGS, TagCategory, TagElement } from '@anticrm/model-tags'
|
||||
@ -157,6 +158,25 @@ export const recruitOperation: MigrateOperation = {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Migrate reviews
|
||||
|
||||
await client.update(DOMAIN_TASK, {
|
||||
_class: recruit.class.Review
|
||||
}, {
|
||||
$rename: {
|
||||
startDate: 'date'
|
||||
}
|
||||
})
|
||||
|
||||
await client.update(DOMAIN_TASK, {
|
||||
_class: recruit.class.Review,
|
||||
title: { $exists: false }
|
||||
}, {
|
||||
title: ''
|
||||
})
|
||||
|
||||
await client.move(DOMAIN_TASK, { _class: recruit.class.Review }, DOMAIN_CALENDAR)
|
||||
},
|
||||
async upgrade (client: MigrationUpgradeClient): Promise<void> {
|
||||
const tx = new TxOperations(client, core.account.System)
|
||||
|
@ -61,6 +61,7 @@ export default mergeIds(recruitId, recruit, {
|
||||
ApplicationPresenter: '' as AnyComponent,
|
||||
ApplicationsPresenter: '' as AnyComponent,
|
||||
VacancyPresenter: '' as AnyComponent,
|
||||
ReviewCategoryPresenter: '' as AnyComponent,
|
||||
EditApplication: '' as AnyComponent,
|
||||
TemplatesIcon: '' as AnyComponent,
|
||||
Applications: '' as AnyComponent,
|
||||
|
@ -1,67 +1,38 @@
|
||||
import { Employee, Organization } from '@anticrm/contact'
|
||||
import { Domain, IndexKind, Ref, Timestamp } from '@anticrm/core'
|
||||
import { Collection, Index, Model, Prop, TypeDate, TypeMarkup, TypeRef, TypeString, UX } from '@anticrm/model'
|
||||
import { Organization } from '@anticrm/contact'
|
||||
import { Domain, IndexKind, Ref } from '@anticrm/core'
|
||||
import { Collection, Index, Model, Prop, TypeMarkup, TypeRef, TypeString, UX } from '@anticrm/model'
|
||||
import attachment from '@anticrm/model-attachment'
|
||||
import calendar, { TEvent } from '@anticrm/model-calendar'
|
||||
import chunter from '@anticrm/model-chunter'
|
||||
import contact from '@anticrm/model-contact'
|
||||
import core, { TAttachedDoc } from '@anticrm/model-core'
|
||||
import task, { TSpaceWithStates, TTask } from '@anticrm/model-task'
|
||||
import core, { TAttachedDoc, TSpace } from '@anticrm/model-core'
|
||||
import task from '@anticrm/model-task'
|
||||
import { Candidate, Opinion, Review, ReviewCategory } from '@anticrm/recruit'
|
||||
import recruit from './plugin'
|
||||
|
||||
@Model(recruit.class.ReviewCategory, task.class.SpaceWithStates)
|
||||
@Model(recruit.class.ReviewCategory, core.class.Space)
|
||||
@UX(recruit.string.ReviewCategory, recruit.icon.Review)
|
||||
export class TReviewCategory extends TSpaceWithStates implements ReviewCategory {
|
||||
export class TReviewCategory extends TSpace implements ReviewCategory {
|
||||
@Prop(TypeString(), recruit.string.FullDescription)
|
||||
fullDescription?: string
|
||||
}
|
||||
|
||||
@Model(recruit.class.Review, calendar.class.Event)
|
||||
@UX(recruit.string.Review, recruit.icon.Review, recruit.string.ReviewShortLabel, 'number')
|
||||
export class TReview extends TEvent implements Review {
|
||||
// We need to declare, to provide property with label
|
||||
@Prop(TypeRef(recruit.mixin.Candidate), recruit.string.Candidate)
|
||||
declare attachedTo: Ref<Candidate>
|
||||
|
||||
@Prop(TypeString(), recruit.string.Verdict)
|
||||
@Index(IndexKind.FullText)
|
||||
verdict!: string
|
||||
|
||||
@Prop(TypeRef(contact.class.Organization), recruit.string.Company, contact.icon.Company)
|
||||
company?: Ref<Organization>
|
||||
}
|
||||
|
||||
@Model(recruit.class.Review, task.class.Task)
|
||||
@UX(recruit.string.Review, recruit.icon.Review, recruit.string.ReviewShortLabel, 'number')
|
||||
export class TReview extends TTask implements Review {
|
||||
// We need to declare, to provide property with label
|
||||
@Prop(TypeRef(recruit.class.Applicant), recruit.string.Candidate)
|
||||
declare attachedTo: Ref<Candidate>
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), recruit.string.AssignedRecruiter)
|
||||
declare assignee: Ref<Employee> | null
|
||||
|
||||
@Prop(TypeMarkup(), recruit.string.Description)
|
||||
@Index(IndexKind.FullText)
|
||||
description!: string
|
||||
|
||||
@Index(IndexKind.FullText)
|
||||
@Prop(TypeMarkup(), recruit.string.Verdict)
|
||||
verdict!: string
|
||||
|
||||
@Index(IndexKind.FullText)
|
||||
@Prop(TypeString(), recruit.string.Location, recruit.icon.Location)
|
||||
location?: string
|
||||
|
||||
@Index(IndexKind.FullText)
|
||||
@Prop(TypeString(), recruit.string.Company, contact.icon.Company)
|
||||
company?: string
|
||||
|
||||
@Prop(TypeDate(), recruit.string.StartDate)
|
||||
startDate!: Timestamp | null
|
||||
|
||||
@Prop(TypeDate(), recruit.string.DueDate)
|
||||
dueDate!: Timestamp | null
|
||||
|
||||
@Prop(Collection(recruit.class.Opinion), recruit.string.Opinions)
|
||||
opinions?: number
|
||||
|
||||
@Prop(Collection(attachment.class.Attachment), attachment.string.Attachments)
|
||||
attachments?: number
|
||||
|
||||
@Prop(Collection(chunter.class.Comment), chunter.string.Comments)
|
||||
comments?: number
|
||||
|
||||
@Prop(Collection(contact.class.Employee), recruit.string.Participants)
|
||||
participants!: Ref<Employee>[]
|
||||
}
|
||||
|
||||
@Model(recruit.class.Opinion, core.class.AttachedDoc, 'recruit' as Domain)
|
||||
|
@ -6,6 +6,7 @@ import task from '@anticrm/model-task'
|
||||
import view from '@anticrm/model-view'
|
||||
import workbench from '@anticrm/model-workbench'
|
||||
import recruit from './plugin'
|
||||
import calendar from '@anticrm/model-calendar'
|
||||
|
||||
export function createReviewModel (builder: Builder): void {
|
||||
builder.mixin(recruit.class.ReviewCategory, core.class.Class, workbench.mixin.SpaceView, {
|
||||
@ -21,11 +22,21 @@ export function createReviewModel (builder: Builder): void {
|
||||
})
|
||||
|
||||
createTableViewlet(builder)
|
||||
createKanbanViewlet(builder)
|
||||
createStatusTableViewlet(builder)
|
||||
|
||||
builder.mixin(recruit.class.Review, core.class.Class, task.mixin.KanbanCard, {
|
||||
card: recruit.component.KanbanReviewCard
|
||||
builder.createDoc(
|
||||
view.class.Action,
|
||||
core.space.Model,
|
||||
{
|
||||
label: recruit.string.CreateOpinion,
|
||||
icon: recruit.icon.Create,
|
||||
action: recruit.actionImpl.CreateOpinion
|
||||
},
|
||||
recruit.action.CreateOpinion
|
||||
)
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: recruit.class.Review,
|
||||
action: recruit.action.CreateOpinion
|
||||
})
|
||||
|
||||
builder.mixin(recruit.class.Review, core.class.Class, view.mixin.ObjectEditor, {
|
||||
@ -63,17 +74,6 @@ export function createReviewModel (builder: Builder): void {
|
||||
action: recruit.action.CreateReview
|
||||
})
|
||||
|
||||
builder.createDoc(
|
||||
task.class.KanbanTemplateSpace,
|
||||
core.space.Model,
|
||||
{
|
||||
name: recruit.string.ReviewCategory,
|
||||
description: task.string.ManageStatusesWithin,
|
||||
icon: recruit.component.TemplatesIcon
|
||||
},
|
||||
recruit.space.ReviewTemplates
|
||||
)
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: recruit.class.ReviewCategory,
|
||||
action: task.action.ArchiveSpace,
|
||||
@ -82,69 +82,6 @@ export function createReviewModel (builder: Builder): void {
|
||||
}
|
||||
})
|
||||
}
|
||||
function createStatusTableViewlet (builder: Builder): void {
|
||||
builder.createDoc(view.class.Viewlet, core.space.Model, {
|
||||
attachTo: recruit.class.Review,
|
||||
descriptor: task.viewlet.StatusTable,
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
options: {
|
||||
lookup: {
|
||||
attachedTo: recruit.mixin.Candidate,
|
||||
state: task.class.State,
|
||||
assignee: contact.class.Employee,
|
||||
doneState: task.class.DoneState,
|
||||
participants: contact.class.Employee
|
||||
}
|
||||
} as FindOptions<Doc>,
|
||||
config: [
|
||||
'',
|
||||
'$lookup.attachedTo',
|
||||
{ key: '$lookup.participants', presenter: recruit.component.PersonsPresenter, label: recruit.string.Participants, sortingKey: '$lookup.participants' },
|
||||
// 'location',
|
||||
'company',
|
||||
'dueDate',
|
||||
{ key: '', presenter: recruit.component.OpinionsPresenter, label: recruit.string.Opinions, sortingKey: 'opinions' },
|
||||
'$lookup.state',
|
||||
'$lookup.doneState',
|
||||
// { presenter: attachment.component.AttachmentsPresenter, label: attachment.string.Files, sortingKey: 'attachments' },
|
||||
// { presenter: chunter.component.CommentsPresenter, label: chunter.string.Comments, sortingKey: 'comments' },
|
||||
'modifiedOn'
|
||||
]
|
||||
})
|
||||
|
||||
builder.createDoc(
|
||||
view.class.Action,
|
||||
core.space.Model,
|
||||
{
|
||||
label: recruit.string.CreateOpinion,
|
||||
icon: recruit.icon.Create,
|
||||
action: recruit.actionImpl.CreateOpinion
|
||||
},
|
||||
recruit.action.CreateOpinion
|
||||
)
|
||||
|
||||
builder.createDoc(view.class.ActionTarget, core.space.Model, {
|
||||
target: recruit.class.Review,
|
||||
action: recruit.action.CreateOpinion
|
||||
})
|
||||
}
|
||||
|
||||
function createKanbanViewlet (builder: Builder): void {
|
||||
builder.createDoc(view.class.Viewlet, core.space.Model, {
|
||||
attachTo: recruit.class.Review,
|
||||
descriptor: task.viewlet.Kanban,
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
options: {
|
||||
lookup: {
|
||||
attachedTo: recruit.mixin.Candidate,
|
||||
state: task.class.State,
|
||||
assignee: contact.class.Employee,
|
||||
participants: contact.class.Employee
|
||||
}
|
||||
} as FindOptions<Doc>,
|
||||
config: ['$lookup.attachedTo', '$lookup.state', '$lookup.participants', '$lookup.assignee']
|
||||
})
|
||||
}
|
||||
|
||||
function createTableViewlet (builder: Builder): void {
|
||||
builder.createDoc(view.class.Viewlet, core.space.Model, {
|
||||
@ -154,22 +91,20 @@ function createTableViewlet (builder: Builder): void {
|
||||
options: {
|
||||
lookup: {
|
||||
attachedTo: recruit.mixin.Candidate,
|
||||
state: task.class.State,
|
||||
assignee: contact.class.Employee,
|
||||
doneState: task.class.DoneState,
|
||||
participants: contact.class.Employee
|
||||
participants: contact.class.Employee,
|
||||
company: contact.class.Organization
|
||||
}
|
||||
} as FindOptions<Doc>,
|
||||
config: [
|
||||
'',
|
||||
'title',
|
||||
'$lookup.attachedTo',
|
||||
{ key: '$lookup.participants', presenter: recruit.component.PersonsPresenter, label: recruit.string.Participants, sortingKey: '$lookup.participants' },
|
||||
// 'location',
|
||||
'company',
|
||||
'dueDate',
|
||||
'verdict',
|
||||
{ key: '', presenter: recruit.component.OpinionsPresenter, label: recruit.string.Opinions, sortingKey: 'opinions' },
|
||||
'$lookup.state',
|
||||
'$lookup.doneState',
|
||||
{ key: '$lookup.participants', presenter: calendar.component.PersonsPresenter, label: calendar.string.Participants, sortingKey: '$lookup.participants' },
|
||||
'$lookup.company',
|
||||
'date',
|
||||
'dueDate',
|
||||
// { presenter: attachment.component.AttachmentsPresenter, label: attachment.string.Files, sortingKey: 'attachments' },
|
||||
// { presenter: chunter.component.CommentsPresenter, label: chunter.string.Comments, sortingKey: 'comments' },
|
||||
'modifiedOn'
|
||||
|
@ -142,6 +142,10 @@ export function createModel (builder: Builder): void {
|
||||
presenter: view.component.StringPresenter
|
||||
})
|
||||
|
||||
builder.mixin(core.class.TypeIntlString, core.class.Class, view.mixin.AttributePresenter, {
|
||||
presenter: view.component.IntlStringPresenter
|
||||
})
|
||||
|
||||
builder.mixin(core.class.TypeNumber, core.class.Class, view.mixin.AttributeEditor, {
|
||||
editor: view.component.NumberEditor
|
||||
})
|
||||
|
@ -31,6 +31,7 @@ export default mergeIds(viewId, view, {
|
||||
component: {
|
||||
StringEditor: '' as AnyComponent,
|
||||
StringPresenter: '' as AnyComponent,
|
||||
IntlStringPresenter: '' as AnyComponent,
|
||||
NumberEditor: '' as AnyComponent,
|
||||
NumberPresenter: '' as AnyComponent,
|
||||
HTMLPresenter: '' as AnyComponent,
|
||||
|
@ -10,6 +10,7 @@
|
||||
"Name": "Name",
|
||||
"Description": "Description",
|
||||
"Private": "Private",
|
||||
"Archived": "Archived"
|
||||
"Archived": "Archived",
|
||||
"ClassLabel": "Label"
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
"Name": "Название",
|
||||
"Description": "Описание",
|
||||
"Private": "Личный",
|
||||
"Archived": "Архивный"
|
||||
"Archived": "Архивный",
|
||||
"ClassLabel": "Тип"
|
||||
}
|
||||
}
|
@ -31,6 +31,11 @@ export type PrimitiveType = number | string | boolean | undefined | Ref<Doc>
|
||||
*/
|
||||
export type Timestamp = number
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type Markup = string
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
@ -160,6 +165,15 @@ export type AttachedData<T extends AttachedDoc> = Omit<T, keyof AttachedDoc>
|
||||
|
||||
// T Y P E S
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
|
||||
export interface TypeDate extends Type<Date> {
|
||||
// If not set to true, will be false
|
||||
withTime?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
|
@ -44,6 +44,7 @@ export default plugin(coreId, {
|
||||
Space: '' as Ref<Class<Space>>,
|
||||
Account: '' as Ref<Class<Account>>,
|
||||
TypeString: '' as Ref<Class<Type<string>>>,
|
||||
TypeIntlString: '' as Ref<Class<Type<IntlString>>>,
|
||||
TypeNumber: '' as Ref<Class<Type<string>>>,
|
||||
TypeMarkup: '' as Ref<Class<Type<string>>>,
|
||||
TypeBoolean: '' as Ref<Class<Type<boolean>>>,
|
||||
|
@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import core, {
|
||||
Account, ArrOf as TypeArrOf, AttachedDoc, Attribute, Class, Classifier, ClassifierKind, Collection as TypeCollection, Data, Doc, Domain, generateId, IndexKind, Interface, Mixin as IMixin, MixinUpdate, Obj, PropertyType, Ref, RefTo, Space, Tx, TxCreateDoc, TxFactory, TxProcessor, Type
|
||||
Account, ArrOf as TypeArrOf, AttachedDoc, Attribute, Class, Classifier, ClassifierKind, Collection as TypeCollection, Data, Doc, Domain, generateId, IndexKind, Interface, Markup, Mixin as IMixin, MixinUpdate, Obj, PropertyType, Ref, RefTo, Space, Timestamp, Tx, TxCreateDoc, TxFactory, TxProcessor, Type, TypeDate as TypeDateType
|
||||
} from '@anticrm/core'
|
||||
import type { Asset, IntlString } from '@anticrm/platform'
|
||||
import toposort from 'toposort'
|
||||
@ -331,36 +331,43 @@ export function TypeString (): Type<string> {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function TypeNumber (): Type<string> {
|
||||
export function TypeNumber (): Type<number> {
|
||||
return { _class: core.class.TypeNumber, label: 'TypeNumber' as IntlString }
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function TypeMarkup (): Type<string> {
|
||||
export function TypeMarkup (): Type<Markup> {
|
||||
return { _class: core.class.TypeMarkup, label: 'TypeMarkup' as IntlString }
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function TypeBoolean (): Type<string> {
|
||||
export function TypeIntlString (): Type<IntlString> {
|
||||
return { _class: core.class.TypeIntlString, label: 'TypeIntlString' as IntlString }
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function TypeBoolean (): Type<boolean> {
|
||||
return { _class: core.class.TypeBoolean, label: 'TypeBoolean' as IntlString }
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function TypeTimestamp (): Type<string> {
|
||||
export function TypeTimestamp (): Type<Timestamp> {
|
||||
return { _class: core.class.TypeTimestamp, label: 'TypeTimestamp' as IntlString }
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function TypeDate (): Type<string> {
|
||||
return { _class: core.class.TypeDate, label: 'TypeDate' as IntlString }
|
||||
export function TypeDate (withTime?: boolean): TypeDateType {
|
||||
return { _class: core.class.TypeDate, label: 'TypeDate' as IntlString, withTime }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,6 +76,7 @@
|
||||
placeholder={attribute?.label}
|
||||
{maxWidth}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
attributeType={attribute.type}
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
@ -94,6 +95,7 @@
|
||||
placeholder={attribute?.label}
|
||||
{maxWidth}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
attributeType={attribute.type}
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
@ -105,6 +107,7 @@
|
||||
this={instance}
|
||||
{maxWidth}
|
||||
value={getAttribute(client, object, { key: attributeKey, attr: attribute })}
|
||||
attributeType={attribute.type}
|
||||
space={object.space}
|
||||
{onChange}
|
||||
{focus}
|
||||
|
@ -33,6 +33,7 @@
|
||||
export let labelProps: any | undefined = undefined
|
||||
export let okAction: () => void
|
||||
export let canSave: boolean = false
|
||||
export let size: 'small'| 'medium' = 'small'
|
||||
|
||||
export let okLabel: IntlString = presentation.string.Create
|
||||
export let cancelLabel: IntlString = presentation.string.Cancel
|
||||
@ -40,7 +41,7 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<form class="antiCard" on:submit|preventDefault={ () => {} }>
|
||||
<form class="antiCard" class:w-2125rem={size === 'small'} class:w-4125rem={size === 'medium'} on:submit|preventDefault={ () => {} }>
|
||||
<div class="antiCard-header">
|
||||
<div class="antiCard-header__title"><Label {label} params={labelProps ?? {}} /></div>
|
||||
{#if $$slots.error}
|
||||
|
@ -35,6 +35,7 @@
|
||||
export let show: boolean = false
|
||||
export let allowDeselect = false
|
||||
export let titleDeselect: IntlString | undefined = undefined
|
||||
export let readonly = false
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -69,7 +70,7 @@
|
||||
<div class="antiSelect" bind:this={container}
|
||||
on:click|preventDefault={() => {
|
||||
btn.focus()
|
||||
if (!opened) {
|
||||
if (!opened && !readonly) {
|
||||
opened = true
|
||||
showPopup(UsersPopup, { _class, title, caption, allowDeselect, selected: value, titleDeselect }, container, (result) => {
|
||||
if (result === null) {
|
||||
|
@ -78,7 +78,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
{#each persons as person}
|
||||
<div class="antiComponentBox flex-center">
|
||||
<div class="antiComponentBox flex-center margin_025 antiComponentBoxFocused">
|
||||
<UserInfo value={person} size={'medium'} />
|
||||
<div class="ml-1">
|
||||
<ActionIcon icon={IconClose} size={'small'} action={() => removePerson(person)} />
|
||||
@ -104,4 +104,7 @@
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.margin_025 {
|
||||
margin: 0.25rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,13 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import presentation, { MessageViewer } from '@anticrm/presentation'
|
||||
import { ActionIcon, IconCheck, IconClose, IconEdit } from '@anticrm/ui'
|
||||
import { ActionIcon, IconCheck, IconClose, IconEdit, Label } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import textEditorPlugin from '../plugin'
|
||||
import StyledTextEditor from './StyledTextEditor.svelte'
|
||||
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let content: string
|
||||
export let placeholder: IntlString = textEditorPlugin.string.EditorPlaceholder
|
||||
|
||||
export let emphasized = false
|
||||
export let alwaysEdit = false
|
||||
export let showButtons = true
|
||||
|
||||
let rawValue: string
|
||||
|
||||
const Mode = {
|
||||
@ -22,18 +28,41 @@
|
||||
textEditor.submit()
|
||||
}
|
||||
const dispatch = createEventDispatcher()
|
||||
let focused = false
|
||||
|
||||
let needFocus = false
|
||||
|
||||
$: if (textEditor && needFocus) {
|
||||
textEditor.focus()
|
||||
needFocus = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="antiComponent styled-box">
|
||||
{#if mode !== Mode.View}
|
||||
<div class="antiComponent styled-box" class:emphasized class:emphasized-focus={(mode === Mode.Edit || alwaysEdit) && focused} on:click={() => {
|
||||
if (alwaysEdit && focused) {
|
||||
textEditor?.focus()
|
||||
}
|
||||
}}>
|
||||
{#if label}
|
||||
<div class="label"><Label {label} /></div>
|
||||
{/if}
|
||||
{#if mode !== Mode.View || alwaysEdit}
|
||||
<StyledTextEditor
|
||||
{placeholder}
|
||||
{showButtons}
|
||||
bind:content={rawValue}
|
||||
bind:this={textEditor}
|
||||
on:focus={() => {
|
||||
focused = true
|
||||
}}
|
||||
on:blur={() => {
|
||||
focused = false
|
||||
}}
|
||||
on:value={(evt) => {
|
||||
rawValue = evt.detail
|
||||
}}
|
||||
>
|
||||
{#if !alwaysEdit}
|
||||
<div class="flex flex-reverse flex-grow">
|
||||
<div class="ml-2">
|
||||
<!-- disabled={rawValue.trim().length === 0} -->
|
||||
@ -59,6 +88,7 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</StyledTextEditor>
|
||||
{:else}
|
||||
<div class="text">
|
||||
@ -66,6 +96,7 @@
|
||||
<MessageViewer message={content} />
|
||||
{/if}
|
||||
</div>
|
||||
{#if !alwaysEdit}
|
||||
<div class="flex flex-reverse">
|
||||
<ActionIcon
|
||||
size={'medium'}
|
||||
@ -74,20 +105,49 @@
|
||||
label={textEditorPlugin.string.Edit}
|
||||
action={() => {
|
||||
rawValue = content ?? ''
|
||||
needFocus = true
|
||||
mode = Mode.Edit
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.styled-box {
|
||||
flex-grow: 1;
|
||||
|
||||
.label {
|
||||
padding-bottom: 0.25rem;
|
||||
font-size: 0.75rem;
|
||||
color: var(--theme-caption-color);
|
||||
opacity: 0.3;
|
||||
transition: top 200ms;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
.emphasized .emphasized-focus + .label {
|
||||
top: 0.5rem;
|
||||
}
|
||||
}
|
||||
.emphasized {
|
||||
padding: 1rem;
|
||||
background-color: var(--theme-bg-accent-color);
|
||||
border: 1px solid var(--theme-bg-accent-hover);
|
||||
border-radius: 0.75rem;
|
||||
&.emphasized-focus {
|
||||
background-color: var(--theme-bg-focused-color);
|
||||
border-color: var(--theme-bg-focused-border);
|
||||
}
|
||||
}
|
||||
.text {
|
||||
overflow: auto;
|
||||
flex-grow: 1;
|
||||
line-height: 150%;
|
||||
|
||||
.nolabel {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -27,12 +27,16 @@
|
||||
|
||||
export let content: string = ''
|
||||
export let placeholder: IntlString = textEditorPlugin.string.EditorPlaceholder
|
||||
export let showButtons = true
|
||||
|
||||
let textEditor: TextEditor
|
||||
|
||||
export function submit (): void {
|
||||
textEditor.submit()
|
||||
}
|
||||
export function focus (): void {
|
||||
textEditor.focus()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="ref-container">
|
||||
@ -50,12 +54,13 @@
|
||||
textEditor.clear()
|
||||
}}
|
||||
on:blur
|
||||
on:focus
|
||||
supportSubmit={false}
|
||||
/>
|
||||
</ScrollBox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<div class="buttons" class:shown={showButtons}>
|
||||
<div class="tool"><TextStyle size={'large'} /></div>
|
||||
<div class="tool"><Emoji size={'large'} /></div>
|
||||
<div class="tool"><GIF size={'large'} /></div>
|
||||
@ -72,6 +77,14 @@
|
||||
flex-direction: column;
|
||||
min-height: 4.5rem;
|
||||
|
||||
.buttons {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.shown {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.textInput {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
|
@ -53,6 +53,15 @@
|
||||
export function insertText (text: string): void {
|
||||
editor.commands.insertContent(text as HTMLContent)
|
||||
}
|
||||
let needFocus = false
|
||||
export function focus (): void {
|
||||
needFocus = true
|
||||
}
|
||||
|
||||
$: if (editor && needFocus) {
|
||||
editor.commands.focus()
|
||||
needFocus = false
|
||||
}
|
||||
|
||||
const Handle = Extension.create({
|
||||
addKeyboardShortcuts () {
|
||||
@ -98,6 +107,9 @@
|
||||
onBlur: () => {
|
||||
dispatch('blur', editor.getHTML())
|
||||
},
|
||||
onFocus: () => {
|
||||
dispatch('focus', editor.getHTML())
|
||||
},
|
||||
onUpdate: () => {
|
||||
content = editor.getHTML()
|
||||
dispatch('value', content)
|
||||
|
@ -417,12 +417,14 @@
|
||||
|
||||
// Basic component view.
|
||||
.antiComponentBox {
|
||||
margin: 0.25rem;
|
||||
padding: 0.5rem;
|
||||
background-color: var(--theme-button-bg-focused);
|
||||
background-color: var(--theme-bg-accent-color);
|
||||
border: 1px solid var(--theme-button-border-enabled);
|
||||
border-radius: .75rem;
|
||||
box-shadow: 0px 3px 3px rgba(0, 0, 0, .2);
|
||||
|
||||
&.antiComponentBoxFocused {
|
||||
background-color: var(--theme-button-bg-focused);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select */
|
||||
|
@ -70,13 +70,11 @@
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Cards */
|
||||
.antiCard {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 21.25rem;
|
||||
min-width: 21.25rem;
|
||||
max-width: 21.25rem;
|
||||
background-color: var(--theme-card-bg);
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: var(--theme-card-shadow);
|
||||
|
@ -28,10 +28,10 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const getNow = (): Date => {
|
||||
let tempDate = new Date(Date.now())
|
||||
const tempDate = new Date(Date.now())
|
||||
return new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())
|
||||
}
|
||||
let today: Date = getNow()
|
||||
const today: Date = getNow()
|
||||
let todayString: string
|
||||
async function todayStr () {
|
||||
todayString = await translate(ui.string.Today, {})
|
||||
|
@ -22,7 +22,7 @@
|
||||
export let withTime: boolean = false
|
||||
|
||||
const { currentLanguage } = getContext('lang')
|
||||
let inter: boolean = (currentLanguage === 'ru') ?? false
|
||||
const inter: boolean = (currentLanguage === 'ru') ?? false
|
||||
|
||||
const zeroLead = (n: number): string => {
|
||||
if (n < 10) return '0' + n.toString()
|
||||
|
7
plugins/calendar-assets/.eslintrc.js
Normal file
7
plugins/calendar-assets/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
9
plugins/calendar-assets/assets/icons.svg
Normal file
9
plugins/calendar-assets/assets/icons.svg
Normal file
@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="calendar" viewBox="0 0 24 24">
|
||||
<path d="M19.5,5h-2.1V4.5c0-0.3-0.2-0.5-0.5-0.5s-0.5,0.2-0.5,0.5V5H8.1V4.5C8.1,4.2,7.9,4,7.6,4S7.1,4.2,7.1,4.5V5H5 C4.2,5,3.5,5.7,3.5,6.5V19c0,0.8,0.7,1.5,1.5,1.5h14.5c0.8,0,1.5-0.7,1.5-1.5V6.5C21,5.7,20.3,5,19.5,5z M5,6h2.1v0.5 c0,0.3,0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5V6h8.3v0.5c0,0.3,0.2,0.5,0.5,0.5s0.5-0.2,0.5-0.5V6h2.1C19.7,6,20,6.3,20,6.5v3.1H4.5V6.5 C4.5,6.3,4.7,6,5,6z M19.5,19.5H5c-0.3,0-0.5-0.2-0.5-0.5v-8.3H20V19C20,19.2,19.7,19.5,19.5,19.5z" />
|
||||
</symbol>
|
||||
<symbol id="location" viewBox="0 0 16 16">
|
||||
<path d="M8,4.6c-1.5,0-2.6,1.2-2.6,2.6S6.5,9.9,8,9.9s2.6-1.2,2.6-2.6S9.5,4.6,8,4.6z M8,8.9c-0.9,0-1.6-0.7-1.6-1.6 c0-0.9,0.7-1.6,1.6-1.6s1.6,0.7,1.6,1.6C9.6,8.2,8.9,8.9,8,8.9z"/>
|
||||
<path d="M8,1.8c-3,0-5.5,2.5-5.5,5.5c0,1.9,0.9,3.4,2,4.5c1.1,1.1,2.3,1.8,2.9,2.1c0.4,0.2,0.9,0.2,1.3,0c0.6-0.3,1.8-1,2.9-2.1 c1.1-1.1,2-2.6,2-4.5C13.5,4.3,11,1.8,8,1.8z M10.8,11.1c-1,1-2.1,1.7-2.6,2c-0.1,0.1-0.2,0.1-0.3,0c-0.6-0.3-1.7-1-2.6-2 c-1-1-1.7-2.3-1.7-3.8c0-2.5,2-4.5,4.5-4.5s4.5,2,4.5,4.5C12.5,8.8,11.7,10.1,10.8,11.1z"/>
|
||||
</symbol>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
18
plugins/calendar-assets/config/rig.json
Normal file
18
plugins/calendar-assets/config/rig.json
Normal file
@ -0,0 +1,18 @@
|
||||
// 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"
|
||||
}
|
17
plugins/calendar-assets/lang/en.json
Normal file
17
plugins/calendar-assets/lang/en.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"string": {
|
||||
"ApplicationLabelCalendar": "Calendar",
|
||||
"Calendars": "Calendars",
|
||||
"Participants": "Participants",
|
||||
"NoParticipants": "No participants added",
|
||||
"PersonsLabel": "{name}",
|
||||
"AddDescription": "Add description",
|
||||
"Date": "Date",
|
||||
"DueTo": "Due date",
|
||||
"Description": "Description",
|
||||
"Title": "Title",
|
||||
"Location": "Location",
|
||||
"Company": "Company",
|
||||
"CreateCalendar": "Create Calendar"
|
||||
}
|
||||
}
|
17
plugins/calendar-assets/lang/ru.json
Normal file
17
plugins/calendar-assets/lang/ru.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"string": {
|
||||
"ApplicationLabelCalendar": "Календарь",
|
||||
"Calendars": "Календари",
|
||||
"Participants": "Участники",
|
||||
"NoParticipants": "Участники не добавлены",
|
||||
"PersonsLabel": "{name}",
|
||||
"AddDescription": "Добавить описание",
|
||||
"Date": "Дата",
|
||||
"DueTo": "Дата конца",
|
||||
"Description": "Описание",
|
||||
"Title": "Название",
|
||||
"Location": "Местоположение",
|
||||
"Company": "Компания",
|
||||
"CreateCalendar": "Новый Калеедарь"
|
||||
}
|
||||
}
|
33
plugins/calendar-assets/package.json
Normal file
33
plugins/calendar-assets/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@anticrm/calendar-assets",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "heft build",
|
||||
"build:docs": "",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"format": "prettier --write src && eslint --fix src",
|
||||
"build:watch": "tsc"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anticrm/platform-rig": "~0.6.0",
|
||||
"@types/heft-jest": "^1.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint": "^7.32.0",
|
||||
"prettier": "^2.4.1",
|
||||
"@rushstack/heft": "^0.41.1",
|
||||
"@types/node": "^16.4.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/calendar": "~0.6.0"
|
||||
}
|
||||
}
|
25
plugins/calendar-assets/src/index.ts
Normal file
25
plugins/calendar-assets/src/index.ts
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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 { addStringsLoader, loadMetadata } from '@anticrm/platform'
|
||||
import calendar, { calendarId } from '@anticrm/calendar'
|
||||
|
||||
const icons = require('../assets/icons.svg') as string // eslint-disable-line
|
||||
loadMetadata(calendar.icon, {
|
||||
Calendar: `${icons}#calendar`,
|
||||
Location: `${icons}#location`
|
||||
})
|
||||
|
||||
addStringsLoader(calendarId, async (lang: string) => await import(`../lang/${lang}.json`))
|
15
plugins/calendar-assets/tsconfig.json
Normal file
15
plugins/calendar-assets/tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"declaration": true,
|
||||
"outDir": "./lib",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
]
|
||||
}
|
||||
}
|
7
plugins/calendar-resources/.eslintrc.js
Normal file
7
plugins/calendar-resources/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/platform-rig/profiles/ui/config/eslint.config.json'],
|
||||
parserOptions: { tsconfigRootDir: __dirname },
|
||||
settings: {
|
||||
'svelte3/ignore-styles': () => true
|
||||
}
|
||||
}
|
BIN
plugins/calendar-resources/img/avatar.png
Normal file
BIN
plugins/calendar-resources/img/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
47
plugins/calendar-resources/package.json
Normal file
47
plugins/calendar-resources/package.json
Normal file
@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "@anticrm/calendar-resources",
|
||||
"version": "0.6.0",
|
||||
"main": "src/index.ts",
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "echo 'no build for ui'",
|
||||
"build:docs": "api-extractor run --local",
|
||||
"lint": "svelte-check && eslint",
|
||||
"lint:fix": "eslint --fix src",
|
||||
"format": "prettier --write --plugin-search-dir=. src && eslint --fix src",
|
||||
"svelte-check": "svelte-check"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte-loader": "^3.1.2",
|
||||
"sass": "^1.37.5",
|
||||
"svelte-preprocess": "^4.10.3",
|
||||
"@anticrm/platform-rig": "~0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"eslint-config-standard-with-typescript": "^21.0.1",
|
||||
"eslint-plugin-import": "^2.25.3",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^5.1.1",
|
||||
"eslint-plugin-svelte3": "~3.2.1",
|
||||
"prettier-plugin-svelte": "^2.2.0",
|
||||
"eslint": "^7.32.0",
|
||||
"prettier": "^2.4.1",
|
||||
"svelte-check": "^2.2.10",
|
||||
"typescript": "^4.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/platform": "~0.6.5",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/presentation": "~0.6.2",
|
||||
"@anticrm/calendar": "~0.6.0",
|
||||
"svelte": "^3.37.0",
|
||||
"@anticrm/text-editor": "~0.6.0",
|
||||
"@anticrm/contact": "~0.6.2",
|
||||
"@anticrm/contact-resources": "~0.6.0",
|
||||
"@anticrm/view-resources": "~0.6.0",
|
||||
"@anticrm/view": "~0.6.0",
|
||||
"@anticrm/workbench": "~0.6.1"
|
||||
}
|
||||
}
|
5
plugins/calendar-resources/postcss.config.js
Normal file
5
plugins/calendar-resources/postcss.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<!--
|
||||
// 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.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { formatName, Person } from '@anticrm/contact'
|
||||
import { Hierarchy } from '@anticrm/core'
|
||||
import { Avatar } from '@anticrm/presentation'
|
||||
import calendar from '../plugin'
|
||||
import { showPanel, Tooltip } from '@anticrm/ui'
|
||||
import view from '@anticrm/view'
|
||||
|
||||
export let value: Person | Person[]
|
||||
export let inline: boolean = false
|
||||
|
||||
let persons: Person[] = []
|
||||
$: persons = Array.isArray(value) ? value : [value]
|
||||
|
||||
async function onClick (p: Person) {
|
||||
showPanel(view.component.EditDoc, p._id, Hierarchy.mixinOrClass(p), 'full')
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class='flex persons'>
|
||||
{#each persons as p}
|
||||
<Tooltip label={calendar.string.PersonsLabel} props={{ name: formatName(p.name) }}>
|
||||
<div class="flex-presenter" class:inline-presenter={inline} on:click={() => onClick(p)}>
|
||||
<div class="icon">
|
||||
<Avatar size={'x-small'} avatar={p.avatar} />
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<style lang="scss">
|
||||
.persons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, min-content);
|
||||
.icon {
|
||||
margin: 0.25rem;
|
||||
}
|
||||
}
|
||||
</style>
|
24
plugins/calendar-resources/src/index.ts
Normal file
24
plugins/calendar-resources/src/index.ts
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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 { Resources } from '@anticrm/platform'
|
||||
|
||||
import PersonsPresenter from './components/PersonsPresenter.svelte'
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
PersonsPresenter
|
||||
}
|
||||
})
|
24
plugins/calendar-resources/src/plugin.ts
Normal file
24
plugins/calendar-resources/src/plugin.ts
Normal file
@ -0,0 +1,24 @@
|
||||
//
|
||||
// Copyright © 2020 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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 calendar, { calendarId } from '@anticrm/calendar'
|
||||
import { mergeIds } from '@anticrm/platform'
|
||||
|
||||
export default mergeIds(calendarId, calendar, {
|
||||
component: {
|
||||
},
|
||||
string: {
|
||||
}
|
||||
})
|
5
plugins/calendar-resources/svelte.config.js
Normal file
5
plugins/calendar-resources/svelte.config.js
Normal file
@ -0,0 +1,5 @@
|
||||
const sveltePreprocess = require('svelte-preprocess')
|
||||
|
||||
module.exports = {
|
||||
preprocess: sveltePreprocess()
|
||||
};
|
15
plugins/calendar-resources/tsconfig.json
Normal file
15
plugins/calendar-resources/tsconfig.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"declaration": true,
|
||||
"outDir": "./lib",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
]
|
||||
}
|
||||
}
|
7
plugins/calendar/.eslintrc.js
Normal file
7
plugins/calendar/.eslintrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
4
plugins/calendar/.npmignore
Normal file
4
plugins/calendar/.npmignore
Normal file
@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
18
plugins/calendar/config/rig.json
Normal file
18
plugins/calendar/config/rig.json
Normal file
@ -0,0 +1,18 @@
|
||||
// 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"
|
||||
}
|
34
plugins/calendar/package.json
Normal file
34
plugins/calendar/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "@anticrm/calendar",
|
||||
"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/platform": "~0.6.5",
|
||||
"@anticrm/ui": "~0.6.0",
|
||||
"@anticrm/core": "~0.6.11",
|
||||
"@anticrm/contact": "~0.6.5"
|
||||
}
|
||||
}
|
90
plugins/calendar/src/index.ts
Normal file
90
plugins/calendar/src/index.ts
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright © 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 { Employee } from '@anticrm/contact'
|
||||
import type { AttachedDoc, Class, Doc, Markup, Ref, Space, Timestamp } from '@anticrm/core'
|
||||
import type { Asset, IntlString, Plugin } from '@anticrm/platform'
|
||||
import { plugin } from '@anticrm/platform'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Calendar extends Space {}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Event extends AttachedDoc {
|
||||
title: string
|
||||
number: number
|
||||
description: Markup
|
||||
|
||||
location?: string
|
||||
|
||||
// Event scheduled date
|
||||
date: Timestamp
|
||||
|
||||
// Event due date for long events.
|
||||
dueDate?: Timestamp
|
||||
|
||||
attachments?: number
|
||||
comments?: number
|
||||
|
||||
participants?: Ref<Employee>[]
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const calendarId = 'calendar' as Plugin
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
const calendarPlugin = plugin(calendarId, {
|
||||
class: {
|
||||
Calendar: '' as Ref<Class<Calendar>>,
|
||||
Event: '' as Ref<Class<Event>>
|
||||
},
|
||||
icon: {
|
||||
Calendar: '' as Asset,
|
||||
Location: '' as Asset
|
||||
},
|
||||
space: {
|
||||
// Space for all personal events.
|
||||
PersonalEvents: '' as Ref<Space>
|
||||
},
|
||||
app: {
|
||||
Calendar: '' as Ref<Doc>
|
||||
},
|
||||
component: {
|
||||
PersonsPresenter: '' as AnyComponent
|
||||
},
|
||||
string: {
|
||||
Title: '' as IntlString,
|
||||
Calendar: '' as IntlString,
|
||||
Description: '' as IntlString,
|
||||
Date: '' as IntlString,
|
||||
DueTo: '' as IntlString,
|
||||
Calendars: '' as IntlString,
|
||||
CreateCalendar: '' as IntlString,
|
||||
Location: '' as IntlString,
|
||||
Participants: '' as IntlString,
|
||||
NoParticipants: '' as IntlString,
|
||||
PersonsLabel: '' as IntlString,
|
||||
EventNumber: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
||||
export default calendarPlugin
|
9
plugins/calendar/tsconfig.json
Normal file
9
plugins/calendar/tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"lib": ["esnext", "dom"]
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
import { createQuery } from '@anticrm/presentation'
|
||||
import { Dropdown } from '@anticrm/ui'
|
||||
import { ListItem } from '@anticrm/ui/src/types'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import contact from '../plugin'
|
||||
import Company from './icons/Company.svelte'
|
||||
|
||||
@ -27,6 +28,7 @@
|
||||
export let label: IntlString = contact.string.Organization
|
||||
|
||||
const query = createQuery()
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
query.query(contact.class.Organization, {}, (res) => {
|
||||
items = res.map((org) => {
|
||||
@ -52,6 +54,7 @@
|
||||
} else {
|
||||
value = selected._id as Ref<Organization>
|
||||
}
|
||||
dispatch('change', value)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
||||
"ReviewCategory": "Reviews",
|
||||
"ReviewCategoryDescription": "Description",
|
||||
"ThisReviewCategoryIsPrivate": "This category is private",
|
||||
"CreateReview": "Create review",
|
||||
"CreateReview": "Schedule {label}",
|
||||
"SelectReviewCategory": "select category",
|
||||
"Reviews": "Reviews",
|
||||
"Review": "Review",
|
||||
@ -84,7 +84,8 @@
|
||||
"OpinionValuePlaceholder": "10/10",
|
||||
"Participants": "Participants",
|
||||
"NoParticipants": "No participants added",
|
||||
"PersonsLabel": "{name}"
|
||||
"PersonsLabel": "{name}",
|
||||
"AddDescription": "Add description"
|
||||
},
|
||||
"status": {
|
||||
"CandidateRequired": "Please select candidate",
|
||||
|
@ -63,7 +63,7 @@
|
||||
"ReviewCategory": "Оценки",
|
||||
"ReviewCategoryDescription": "Описание",
|
||||
"ThisReviewCategoryIsPrivate": "Эта категория личная",
|
||||
"CreateReview": "Запланировать оценку",
|
||||
"CreateReview": "Запланировать {label}",
|
||||
"SelectReviewCategory": "выбрать категорию",
|
||||
"Reviews": "Оценки",
|
||||
"Review": "Оценка",
|
||||
@ -85,7 +85,8 @@
|
||||
"OpinionValuePlaceholder": "10/10",
|
||||
"Participants": "Участники",
|
||||
"NoParticipants": "Участники не добавлены",
|
||||
"PersonsLabel": "{name}"
|
||||
"PersonsLabel": "{name}",
|
||||
"AddDescription": "Add description"
|
||||
},
|
||||
"status": {
|
||||
"CandidateRequired": "Пожалуйста выберите кандидата",
|
||||
|
@ -55,6 +55,7 @@
|
||||
"@anticrm/contact-resources": "~0.6.0",
|
||||
"@anticrm/rekoni": "~0.6.0",
|
||||
"@anticrm/notification": "~0.6.0",
|
||||
"@anticrm/tags": "~0.6.0"
|
||||
"@anticrm/tags": "~0.6.0",
|
||||
"@anticrm/calendar": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -13,36 +13,36 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { Contact, Employee, Person } from '@anticrm/contact'
|
||||
import type { Contact, Organization, Person } from '@anticrm/contact'
|
||||
import contact from '@anticrm/contact'
|
||||
import { Account, Class, Client, Doc, generateId, Ref, SortingOrder } from '@anticrm/core'
|
||||
import { OrganizationSelector } from '@anticrm/contact-resources'
|
||||
import { Account, Class, Client, Doc, generateId, Ref } from '@anticrm/core'
|
||||
import { getResource, OK, Resource, Severity, Status } from '@anticrm/platform'
|
||||
import { Card, getClient, UserBox } from '@anticrm/presentation'
|
||||
import type { Candidate, Review } from '@anticrm/recruit'
|
||||
import task, { calcRank, SpaceWithStates, State } from '@anticrm/task'
|
||||
import { Grid, Status as StatusControl } from '@anticrm/ui'
|
||||
import {DatePicker} from '@anticrm/ui'
|
||||
import task, { SpaceWithStates } from '@anticrm/task'
|
||||
import { StyledTextBox } from '@anticrm/text-editor'
|
||||
import { DatePicker, Grid, Status as StatusControl, StylishEdit } from '@anticrm/ui'
|
||||
import view from '@anticrm/view'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import recruit from '../../plugin'
|
||||
|
||||
export let space: Ref<SpaceWithStates>
|
||||
export let candidate: Ref<Person>
|
||||
export let assignee: Ref<Employee>
|
||||
|
||||
export let preserveCandidate = false
|
||||
|
||||
let status: Status = OK
|
||||
|
||||
let title: string = ''
|
||||
let description: string = ''
|
||||
let startDate: Date = new Date()
|
||||
let dueDate: Date = new Date()
|
||||
let location: string = ''
|
||||
let company: Ref<Organization> | undefined = undefined
|
||||
|
||||
const doc: Review = {
|
||||
state: '' as Ref<State>,
|
||||
doneState: null,
|
||||
number: 0,
|
||||
assignee: assignee,
|
||||
rank: '',
|
||||
attachedTo: candidate,
|
||||
attachedToClass: recruit.mixin.Candidate,
|
||||
_class: recruit.class.Review,
|
||||
@ -51,10 +51,12 @@
|
||||
collection: 'reviews',
|
||||
modifiedOn: Date.now(),
|
||||
modifiedBy: '' as Ref<Account>,
|
||||
startDate: null,
|
||||
dueDate: null,
|
||||
description: '',
|
||||
verdict: ''
|
||||
date: 0,
|
||||
dueDate: undefined,
|
||||
description,
|
||||
company,
|
||||
verdict: '',
|
||||
title
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -62,9 +64,17 @@
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
export function canClose (): boolean {
|
||||
return candidate === undefined && assignee === undefined
|
||||
return candidate === undefined
|
||||
}
|
||||
|
||||
let spaceLabel: string = ''
|
||||
|
||||
$: client.findOne(recruit.class.ReviewCategory, { _id: doc.space }).then((res) => {
|
||||
if (res !== undefined) {
|
||||
spaceLabel = res.name
|
||||
}
|
||||
})
|
||||
|
||||
async function createReview () {
|
||||
const state = await client.findOne(task.class.State, { space: doc.space })
|
||||
if (state === undefined) {
|
||||
@ -75,11 +85,6 @@
|
||||
throw new Error('sequence object not found')
|
||||
}
|
||||
|
||||
const lastOne = await client.findOne(
|
||||
recruit.class.Review,
|
||||
{ state: state._id },
|
||||
{ sort: { rank: SortingOrder.Descending } }
|
||||
)
|
||||
const incResult = await client.update(sequence, { $inc: { sequence: 1 } }, true)
|
||||
|
||||
const candidateInstance = await client.findOne(contact.class.Person, { _id: doc.attachedTo as Ref<Person> })
|
||||
@ -87,24 +92,25 @@
|
||||
throw new Error('contact not found')
|
||||
}
|
||||
if (!client.getHierarchy().hasMixin(candidateInstance, recruit.mixin.Candidate)) {
|
||||
await client.createMixin<Contact, Candidate>(candidateInstance._id, candidateInstance._class, candidateInstance.space, recruit.mixin.Candidate, {})
|
||||
await client.createMixin<Contact, Candidate>(
|
||||
candidateInstance._id,
|
||||
candidateInstance._class,
|
||||
candidateInstance.space,
|
||||
recruit.mixin.Candidate,
|
||||
{}
|
||||
)
|
||||
}
|
||||
|
||||
await client.addCollection(
|
||||
recruit.class.Review,
|
||||
doc.space, doc.attachedTo, doc.attachedToClass, 'reviews',
|
||||
{
|
||||
state: state._id,
|
||||
doneState: null,
|
||||
await client.addCollection(recruit.class.Review, doc.space, doc.attachedTo, doc.attachedToClass, 'reviews', {
|
||||
number: (incResult as any).object.sequence,
|
||||
assignee: doc.assignee,
|
||||
rank: calcRank(lastOne, undefined),
|
||||
startDate: startDate?.getTime() ?? null,
|
||||
date: startDate?.getTime() ?? null,
|
||||
dueDate: dueDate?.getTime() ?? null,
|
||||
description: '',
|
||||
verdict: ''
|
||||
}
|
||||
)
|
||||
description,
|
||||
verdict: '',
|
||||
title,
|
||||
company,
|
||||
location
|
||||
})
|
||||
}
|
||||
|
||||
async function invokeValidate (
|
||||
@ -130,9 +136,11 @@
|
||||
</script>
|
||||
|
||||
<Card
|
||||
size={'medium'}
|
||||
label={recruit.string.CreateReview}
|
||||
labelProps={{ label: spaceLabel }}
|
||||
okAction={createReview}
|
||||
canSave={status.severity === Severity.OK}
|
||||
canSave={status.severity === Severity.OK && title.trim().length > 0}
|
||||
spaceClass={recruit.class.ReviewCategory}
|
||||
spaceQuery={{ archived: false }}
|
||||
spaceLabel={recruit.string.ReviewCategory}
|
||||
@ -143,19 +151,38 @@
|
||||
}}
|
||||
>
|
||||
<StatusControl slot="error" {status} />
|
||||
|
||||
<Grid column={1} rowGap={1.75}>
|
||||
<Grid column={!preserveCandidate ? 2 : 1}>
|
||||
<StylishEdit bind:value={title} label={recruit.string.Title} />
|
||||
{#if !preserveCandidate}
|
||||
<UserBox _class={contact.class.Person} title={recruit.string.Candidate} caption={recruit.string.Candidates} bind:value={doc.attachedTo} />
|
||||
{/if}
|
||||
<div class="antiComponentBox">
|
||||
<UserBox
|
||||
_class={contact.class.Employee}
|
||||
title={recruit.string.AssignRecruiter}
|
||||
caption={recruit.string.Recruiters}
|
||||
bind:value={doc.assignee}
|
||||
allowDeselect
|
||||
titleDeselect={recruit.string.UnAssignRecruiter}
|
||||
_class={contact.class.Person}
|
||||
title={recruit.string.Candidate}
|
||||
caption={recruit.string.Candidates}
|
||||
bind:value={doc.attachedTo}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</Grid>
|
||||
<StyledTextBox
|
||||
emphasized
|
||||
showButtons={false}
|
||||
bind:content={description}
|
||||
label={recruit.string.Description}
|
||||
alwaysEdit
|
||||
placeholder={recruit.string.AddDescription}
|
||||
/>
|
||||
<Grid column={2}>
|
||||
<StylishEdit bind:value={location} label={recruit.string.Location} />
|
||||
<OrganizationSelector bind:value={company} label={recruit.string.Company} />
|
||||
</Grid>
|
||||
<div class="antiComponentBox">
|
||||
<DatePicker title={recruit.string.StartDate} bind:value={startDate} withTime />
|
||||
</div>
|
||||
<div class="antiComponentBox">
|
||||
<DatePicker title={recruit.string.DueDate} bind:value={dueDate} withTime />
|
||||
</div>
|
||||
</Grid>
|
||||
</Card>
|
||||
|
@ -14,44 +14,32 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import core, { Ref } from '@anticrm/core'
|
||||
import core from '@anticrm/core'
|
||||
import { getClient, SpaceCreateCard } from '@anticrm/presentation'
|
||||
import task,{ createKanban,KanbanTemplate } from '@anticrm/task'
|
||||
import { Component,EditBox,Grid } from '@anticrm/ui'
|
||||
import { EditBox, Grid } from '@anticrm/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import recruit from '../../plugin'
|
||||
import Review from '../icons/Review.svelte'
|
||||
import { Organization } from '@anticrm/contact'
|
||||
import { OrganizationSelector } from '@anticrm/contact-resources'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let name: string = ''
|
||||
const description: string = ''
|
||||
let templateId: Ref<KanbanTemplate> | undefined
|
||||
let company: Ref<Organization> | undefined
|
||||
|
||||
export function canClose (): boolean {
|
||||
return name === '' && templateId !== undefined
|
||||
return name === ''
|
||||
}
|
||||
|
||||
const client = getClient()
|
||||
|
||||
async function createReviewCategory () {
|
||||
if (templateId !== undefined && await client.findOne(task.class.KanbanTemplate, { _id: templateId }) === undefined) {
|
||||
throw Error(`Failed to find target kanban template: ${templateId}`)
|
||||
}
|
||||
|
||||
const id = await client.createDoc(recruit.class.ReviewCategory, core.space.Space, {
|
||||
await client.createDoc(recruit.class.ReviewCategory, core.space.Space, {
|
||||
name,
|
||||
description,
|
||||
private: false,
|
||||
archived: false,
|
||||
company,
|
||||
members: []
|
||||
})
|
||||
|
||||
await createKanban(client, id, templateId)
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -63,13 +51,5 @@
|
||||
>
|
||||
<Grid column={1} rowGap={1.5}>
|
||||
<EditBox label={recruit.string.ReviewCategoryName} bind:value={name} icon={Review} placeholder={recruit.string.ReviewCategoryPlaceholder} maxWidth={'16rem'} focus/>
|
||||
<OrganizationSelector bind:value={company} label={recruit.string.Company} />
|
||||
|
||||
<Component is={task.component.KanbanTemplateSelector} props={{
|
||||
folders: [recruit.space.ReviewTemplates],
|
||||
template: templateId
|
||||
}} on:change={(evt) => {
|
||||
templateId = evt.detail
|
||||
}}/>
|
||||
</Grid>
|
||||
</SpaceCreateCard>
|
||||
|
@ -14,98 +14,65 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import contact from '@anticrm/contact'
|
||||
import { createQuery, getClient, UserBoxList } from '@anticrm/presentation'
|
||||
import type { Candidate, Review, ReviewCategory } from '@anticrm/recruit'
|
||||
import calendar from '@anticrm/calendar'
|
||||
import contact, { Contact } from '@anticrm/contact'
|
||||
import { OrganizationSelector } from '@anticrm/contact-resources'
|
||||
import { getClient, UserBox, UserBoxList, UserInfo } from '@anticrm/presentation'
|
||||
import type { Review } from '@anticrm/recruit'
|
||||
import { StyledTextBox } from '@anticrm/text-editor'
|
||||
import { EditBox, Grid, Label } from '@anticrm/ui'
|
||||
import { Grid, Label, showPanel, StylishEdit } from '@anticrm/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import recruit from '../../plugin'
|
||||
import CandidateCard from '../CandidateCard.svelte'
|
||||
import ExpandRightDouble from '../icons/ExpandRightDouble.svelte'
|
||||
import ReviewCategoryCard from './ReviewCategoryCard.svelte'
|
||||
import view from '@anticrm/view'
|
||||
|
||||
export let object: Review
|
||||
let candidate: Candidate
|
||||
|
||||
let reviewCategory: ReviewCategory
|
||||
|
||||
const candidateQuery = createQuery()
|
||||
$: if (object !== undefined) {
|
||||
candidateQuery.query(recruit.mixin.Candidate, { _id: object.attachedTo }, (result) => {
|
||||
candidate = result[0]
|
||||
})
|
||||
}
|
||||
|
||||
const reviewCategoryQuery = createQuery()
|
||||
$: if (candidate !== undefined) {
|
||||
reviewCategoryQuery.query(recruit.class.ReviewCategory, { _id: object.space }, (result) => {
|
||||
reviewCategory = result[0]
|
||||
})
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
onMount(() => {
|
||||
dispatch('open', {
|
||||
ignoreKeys: ['location', 'company', 'number', 'comments', 'startDate', 'description', 'verdict']
|
||||
ignoreKeys: ['number', 'comments', 'title', 'description', 'verdict']
|
||||
})
|
||||
})
|
||||
|
||||
let candidate: Contact | undefined = undefined
|
||||
|
||||
async function updateSelected (object: Review) {
|
||||
candidate = await client.findOne<Contact>(object.attachedToClass, { _id: object.attachedTo })
|
||||
}
|
||||
|
||||
$: updateSelected(object)
|
||||
</script>
|
||||
|
||||
{#if object !== undefined && candidate !== undefined}
|
||||
<div class="flex-between">
|
||||
<div class="card"><CandidateCard {candidate} /></div>
|
||||
<div class="arrows"><ExpandRightDouble /></div>
|
||||
<div class="card"><ReviewCategoryCard category={reviewCategory} /></div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 mb-2">
|
||||
{#if object !== undefined}
|
||||
<div class="mb-2">
|
||||
<div class="mb-2">
|
||||
<Grid column={2}>
|
||||
<EditBox
|
||||
label={recruit.string.Company}
|
||||
bind:value={object.company}
|
||||
icon={contact.icon.Company}
|
||||
placeholder={recruit.string.Company}
|
||||
maxWidth="39rem"
|
||||
focus
|
||||
on:change={() => client.update(object, { company: object.company })}
|
||||
<StylishEdit
|
||||
label={calendar.string.Title}
|
||||
bind:value={object.title}
|
||||
on:change={() => client.update(object, { title: object.title })}
|
||||
/>
|
||||
<EditBox
|
||||
label={recruit.string.Location}
|
||||
bind:value={object.location}
|
||||
icon={recruit.icon.Location}
|
||||
placeholder={recruit.string.Location}
|
||||
maxWidth="39rem"
|
||||
focus
|
||||
on:change={() => client.update(object, { location: object.location })}
|
||||
<div class="antiComponentBox over-underline" on:click={() => {
|
||||
if (candidate !== undefined) {
|
||||
showPanel(view.component.EditDoc, candidate._id, candidate._class, 'full')
|
||||
}
|
||||
}}>
|
||||
<UserBox
|
||||
readonly
|
||||
_class={contact.class.Person}
|
||||
title={recruit.string.Candidate}
|
||||
caption={recruit.string.Candidates}
|
||||
value={object.attachedTo}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
<div class="flex-row">
|
||||
<div class="mt-4 mb-2">
|
||||
<Label label={recruit.string.Participants} />
|
||||
</div>
|
||||
<UserBoxList
|
||||
_class={contact.class.Employee}
|
||||
items={object.participants}
|
||||
title={recruit.string.Participants}
|
||||
on:open={(evt) => {
|
||||
client.update(object, { $push: { participants: evt.detail._id } })
|
||||
}}
|
||||
on:delete={(evt) => {
|
||||
client.update(object, { $pull: { participants: evt.detail._id } })
|
||||
}}
|
||||
noItems={recruit.string.NoParticipants}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 mb-1">
|
||||
<Label label={recruit.string.Description} />
|
||||
</div>
|
||||
<div class="description flex">
|
||||
<div class="mt-2 mb-2">
|
||||
<StyledTextBox
|
||||
label={recruit.string.Description}
|
||||
emphasized
|
||||
content={object.description}
|
||||
on:value={(evt) => {
|
||||
console.log(evt.detail)
|
||||
@ -114,17 +81,44 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 mb-1">
|
||||
<Label label={recruit.string.Verdict} />
|
||||
</div>
|
||||
<div class="description flex">
|
||||
<StyledTextBox
|
||||
content={object.verdict}
|
||||
on:value={(evt) => {
|
||||
client.update(object, { verdict: evt.detail })
|
||||
}}
|
||||
<Grid column={2}>
|
||||
<StylishEdit
|
||||
label={calendar.string.Location}
|
||||
bind:value={object.location}
|
||||
on:change={() => client.update(object, { location: object.location })}
|
||||
/>
|
||||
<div class="antiComponentBox">
|
||||
<OrganizationSelector
|
||||
bind:value={object.company}
|
||||
label={recruit.string.Company}
|
||||
on:change={() => client.update(object, { company: object.company })}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
<div class="flex-row">
|
||||
<div class="mt-4 mb-2">
|
||||
<Label label={calendar.string.Participants} />
|
||||
</div>
|
||||
<UserBoxList
|
||||
_class={contact.class.Employee}
|
||||
items={object.participants}
|
||||
title={calendar.string.Participants}
|
||||
on:open={(evt) => {
|
||||
client.update(object, { $push: { participants: evt.detail._id } })
|
||||
}}
|
||||
on:delete={(evt) => {
|
||||
client.update(object, { $pull: { participants: evt.detail._id } })
|
||||
}}
|
||||
noItems={calendar.string.NoParticipants}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<StylishEdit
|
||||
label={recruit.string.Verdict}
|
||||
bind:value={object.verdict}
|
||||
on:change={() => client.update(object, { verdict: object.verdict })}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
@ -138,8 +132,6 @@
|
||||
|
||||
.description {
|
||||
height: 10rem;
|
||||
padding: 1rem;
|
||||
border: 1px solid var(--theme-menu-divider);
|
||||
border-radius: 8px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,90 +0,0 @@
|
||||
<!--
|
||||
// Copyright © 2020, 2021 Anticrm Platform Contributors.
|
||||
//
|
||||
// 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.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AttachmentsPresenter } from '@anticrm/attachment-resources'
|
||||
import { CommentsPresenter } from '@anticrm/chunter-resources'
|
||||
import { Employee, formatName, Person } from '@anticrm/contact'
|
||||
import type { WithLookup } from '@anticrm/core'
|
||||
import { Avatar } from '@anticrm/presentation'
|
||||
import type { Review } from '@anticrm/recruit'
|
||||
import { ActionIcon, IconMoreH, showPanel } from '@anticrm/ui'
|
||||
import view from '@anticrm/view'
|
||||
import PersonsPresenter from './PersonsPresenter.svelte'
|
||||
import ReviewPresenter from './ReviewPresenter.svelte'
|
||||
|
||||
export let object: WithLookup<Review>
|
||||
export let draggable: boolean
|
||||
|
||||
function showCandidate () {
|
||||
showPanel(view.component.EditDoc, object.attachedTo, object.attachedToClass, 'full')
|
||||
}
|
||||
function getPersons (object: WithLookup<Review>): Person[] {
|
||||
const r = (object.$lookup?.participants as unknown as Employee[] ?? [])
|
||||
const assignee = object.$lookup?.assignee as Employee
|
||||
if (assignee != null && r.findIndex(it => it._id === assignee._id) === -1) {
|
||||
return [...r, assignee]
|
||||
}
|
||||
return r
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="card-container" {draggable} class:draggable on:dragstart on:dragend>
|
||||
<div class="flex-between mb-3">
|
||||
<Avatar avatar={object.$lookup?.attachedTo?.avatar} size={'medium'} />
|
||||
<div class="flex-grow flex-col min-w-0 ml-2">
|
||||
<div class="fs-title over-underline lines-limit-2" on:click={showCandidate}>
|
||||
{#if object.$lookup?.attachedTo}
|
||||
{formatName(object.$lookup?.attachedTo?.name)}
|
||||
{/if}
|
||||
</div>
|
||||
<div class="small-text lines-limit-2">{object.$lookup?.attachedTo?.title ?? ''}</div>
|
||||
</div>
|
||||
<div class="tool"><ActionIcon label={undefined} icon={IconMoreH} size={'small'} /></div>
|
||||
</div>
|
||||
<div class="flex-between">
|
||||
<div class="flex-row-center">
|
||||
<div class="sm-tool-icon step-lr75">
|
||||
<ReviewPresenter value={object} />
|
||||
</div>
|
||||
{#if (object.attachments ?? 0) > 0}
|
||||
<div class="step-lr75"><AttachmentsPresenter value={object} /></div>
|
||||
{/if}
|
||||
{#if (object.comments ?? 0) > 0}
|
||||
<div class="step-lr75"><CommentsPresenter value={object} /></div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if object.$lookup?.participants || object.$lookup?.assignee}
|
||||
<PersonsPresenter value={getPersons(object)}></PersonsPresenter>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.card-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem 1.25rem;
|
||||
background-color: rgba(222, 222, 240, 0.06);
|
||||
border-radius: 0.75rem;
|
||||
user-select: none;
|
||||
|
||||
&.draggable {
|
||||
cursor: grab;
|
||||
}
|
||||
}
|
||||
.tool {
|
||||
align-self: start;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,37 @@
|
||||
<!--
|
||||
// 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.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { ReviewCategory } from '@anticrm/recruit'
|
||||
import { Icon } from '@anticrm/ui'
|
||||
import { showPanel } from '@anticrm/ui/src/panelup'
|
||||
import recruit from '../../plugin'
|
||||
|
||||
export let value: ReviewCategory
|
||||
export let inline: boolean = false
|
||||
|
||||
function show () {
|
||||
// showPanel(recruit.component.EditVacancy, value._id, value._class, 'right')
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class="flex-presenter" class:inline-presenter={inline} on:click={show}>
|
||||
<div class="icon">
|
||||
<Icon icon={recruit.icon.Vacancy} size={'small'} />
|
||||
</div>
|
||||
<span class="label">{value.name}</span>
|
||||
</div>
|
||||
{/if}
|
@ -37,7 +37,7 @@
|
||||
|
||||
function show () {
|
||||
closeTooltip()
|
||||
showPanel(view.component.EditDoc, value._id, value._class, 'full')
|
||||
showPanel(view.component.EditDoc, value._id, value._class, 'right')
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -43,21 +43,19 @@
|
||||
config={[
|
||||
'',
|
||||
{ key: '$lookup.space.name', label: recruit.string.ReviewCategoryTitle },
|
||||
'dueDate',
|
||||
'verdict',
|
||||
{
|
||||
key: '',
|
||||
presenter: recruit.component.OpinionsPresenter,
|
||||
label: recruit.string.Opinions,
|
||||
sortingKey: 'opinions'
|
||||
},
|
||||
'$lookup.state',
|
||||
'$lookup.doneState'
|
||||
'date',
|
||||
'dueDate'
|
||||
]}
|
||||
options={{
|
||||
lookup: {
|
||||
state: task.class.State,
|
||||
space: core.class.Space,
|
||||
doneState: task.class.DoneState
|
||||
space: core.class.Space
|
||||
}
|
||||
}}
|
||||
query={{ attachedTo: objectId }}
|
||||
|
@ -35,7 +35,6 @@ import CreateOpinion from './components/review/CreateOpinion.svelte'
|
||||
import CreateReviewCategory from './components/review/CreateReviewCategory.svelte'
|
||||
import EditReview from './components/review/EditReview.svelte'
|
||||
import EditReviewCategory from './components/review/EditReviewCategory.svelte'
|
||||
import KanbanReviewCard from './components/review/KanbanReviewCard.svelte'
|
||||
import OpinionPresenter from './components/review/OpinionPresenter.svelte'
|
||||
import OpinionsPresenter from './components/review/OpinionsPresenter.svelte'
|
||||
import Opinions from './components/review/Opinions.svelte'
|
||||
@ -48,8 +47,8 @@ import VacancyItemPresenter from './components/VacancyItemPresenter.svelte'
|
||||
import VacancyPresenter from './components/VacancyPresenter.svelte'
|
||||
import VacancyCountPresenter from './components/VacancyCountPresenter.svelte'
|
||||
import VacancyModifiedPresenter from './components/VacancyModifiedPresenter.svelte'
|
||||
import ReviewCategoryPresenter from './components/review/ReviewCategoryPresenter.svelte'
|
||||
import recruit from './plugin'
|
||||
import PersonsPresenter from './components/review/PersonsPresenter.svelte'
|
||||
|
||||
async function createApplication (object: Doc): Promise<void> {
|
||||
showPopup(CreateApplication, { candidate: object._id, preserveCandidate: true })
|
||||
@ -163,12 +162,11 @@ export default async (): Promise<Resources> => ({
|
||||
CreateReview,
|
||||
ReviewPresenter,
|
||||
EditReview,
|
||||
KanbanReviewCard,
|
||||
Reviews,
|
||||
Opinions,
|
||||
OpinionPresenter,
|
||||
OpinionsPresenter,
|
||||
PersonsPresenter
|
||||
ReviewCategoryPresenter
|
||||
},
|
||||
completion: {
|
||||
ApplicationQuery: async (client: Client, query: string) => await queryApplication(client, query)
|
||||
|
@ -101,9 +101,7 @@ export default mergeIds(recruitId, recruit, {
|
||||
StartDate: '' as IntlString,
|
||||
DueDate: '' as IntlString,
|
||||
CandidateReviews: '' as IntlString,
|
||||
Participants: '' as IntlString,
|
||||
NoParticipants: '' as IntlString,
|
||||
PersonsLabel: '' as IntlString
|
||||
AddDescription: '' as IntlString
|
||||
},
|
||||
space: {
|
||||
CandidatesPublic: '' as Ref<Space>
|
||||
@ -116,7 +114,6 @@ export default mergeIds(recruitId, recruit, {
|
||||
VacancyItemPresenter: '' as AnyComponent,
|
||||
VacancyCountPresenter: '' as AnyComponent,
|
||||
OpinionsPresenter: '' as AnyComponent,
|
||||
PersonsPresenter: '' as AnyComponent,
|
||||
VacancyModifiedPresenter: '' as AnyComponent
|
||||
}
|
||||
})
|
||||
|
@ -31,6 +31,7 @@
|
||||
"@anticrm/contact": "~0.6.5",
|
||||
"@anticrm/chunter": "~0.6.1",
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/calendar": "~0.6.0",
|
||||
"@anticrm/ui": "~0.6.0"
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Employee, Organization, Person } from '@anticrm/contact'
|
||||
import { Calendar, Event } from '@anticrm/calendar'
|
||||
import type { Organization, Person } from '@anticrm/contact'
|
||||
import type { AttachedDoc, Class, Doc, Mixin, Ref, Space, Timestamp } from '@anticrm/core'
|
||||
import type { Asset, Plugin } from '@anticrm/platform'
|
||||
import { plugin } from '@anticrm/platform'
|
||||
@ -34,10 +35,10 @@ export interface Vacancy extends SpaceWithStates {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ReviewCategory extends SpaceWithStates {
|
||||
export interface ReviewCategory extends Calendar {
|
||||
fullDescription?: string
|
||||
attachments?: number
|
||||
company?: Ref<Organization>
|
||||
comments?: number
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,22 +71,14 @@ export interface Applicant extends Task {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Review extends Task {
|
||||
export interface Review extends Event {
|
||||
attachedTo: Ref<Candidate>
|
||||
attachments?: number
|
||||
comments?: number
|
||||
description: string
|
||||
|
||||
verdict: string
|
||||
|
||||
location?: string
|
||||
company?: string
|
||||
|
||||
startDate: Timestamp | null
|
||||
dueDate: Timestamp | null
|
||||
company?: Ref<Organization>
|
||||
|
||||
opinions?: number
|
||||
|
||||
participants?: Ref<Employee>[]
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -15,6 +15,7 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { TypeDate } from '@anticrm/core'
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import { DatePopup, showPopup } from '@anticrm/ui'
|
||||
import DatePresenter from './DatePresenter.svelte'
|
||||
@ -22,6 +23,9 @@
|
||||
export let value: number | Date | undefined
|
||||
export let label: IntlString
|
||||
export let onChange: (value: any) => void
|
||||
|
||||
export let attributeType: TypeDate | undefined
|
||||
|
||||
$: date = value ? new Date(value) : new Date()
|
||||
let container: HTMLElement
|
||||
let opened: boolean = false
|
||||
@ -31,7 +35,7 @@
|
||||
on:click|preventDefault={() => {
|
||||
if (!opened) {
|
||||
opened = true
|
||||
showPopup(DatePopup, { selected: date, title: label }, container, (result) => {
|
||||
showPopup(DatePopup, { value: date, title: label, withTime: attributeType?.withTime ?? false }, container, (result) => {
|
||||
if (result) {
|
||||
value = result.getTime()
|
||||
onChange(value)
|
||||
@ -40,5 +44,5 @@
|
||||
})
|
||||
}
|
||||
}} >
|
||||
<DatePresenter {value} />
|
||||
<DatePresenter {value} {attributeType} />
|
||||
</div>
|
@ -15,16 +15,18 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { TypeDate } from '@anticrm/core'
|
||||
import { DatePresenter } from '@anticrm/ui'
|
||||
|
||||
export let value: number | Date | undefined
|
||||
export let attributeType: TypeDate | undefined
|
||||
|
||||
$: date = value ? new Date(value) : undefined
|
||||
</script>
|
||||
|
||||
<div class="antiSelect">
|
||||
{#if date}
|
||||
<DatePresenter value={date} />
|
||||
<DatePresenter value={date} withTime={attributeType?.withTime ?? false} />
|
||||
{:else}
|
||||
No date
|
||||
{/if}
|
||||
|
@ -0,0 +1,26 @@
|
||||
<!--
|
||||
// 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.
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { IntlString } from '@anticrm/platform'
|
||||
import { Label } from '@anticrm/ui'
|
||||
|
||||
export let value: IntlString
|
||||
</script>
|
||||
|
||||
<span class="lines-limit-2">
|
||||
<Label label={value}/>
|
||||
</span>
|
@ -23,6 +23,7 @@ import DateEditor from './components/DateEditor.svelte'
|
||||
import DatePresenter from './components/DatePresenter.svelte'
|
||||
import StringEditor from './components/StringEditor.svelte'
|
||||
import StringPresenter from './components/StringPresenter.svelte'
|
||||
import IntlStringPresenter from './components/IntlStringPresenter.svelte'
|
||||
import NumberEditor from './components/NumberEditor.svelte'
|
||||
import NumberPresenter from './components/NumberPresenter.svelte'
|
||||
import Table from './components/Table.svelte'
|
||||
@ -80,6 +81,7 @@ export default async (): Promise<Resources> => ({
|
||||
RolePresenter,
|
||||
ObjectPresenter,
|
||||
EditDoc,
|
||||
HTMLPresenter
|
||||
HTMLPresenter,
|
||||
IntlStringPresenter
|
||||
}
|
||||
})
|
||||
|
@ -98,12 +98,14 @@ async function getAttributePresenter (
|
||||
const resultKey = preserveKey.sortingKey ?? preserveKey.key
|
||||
const sortingKey = attribute.type._class === core.class.ArrOf ? resultKey + '.length' : resultKey
|
||||
const presenter = await getResource(presenterMixin.presenter)
|
||||
|
||||
return {
|
||||
key: preserveKey.key,
|
||||
sortingKey,
|
||||
_class: attrClass,
|
||||
label: preserveKey.label ?? attribute.label,
|
||||
presenter,
|
||||
props: { attributeType: attribute.type },
|
||||
icon: presenterMixin.icon,
|
||||
attribute
|
||||
}
|
||||
@ -215,7 +217,7 @@ export async function getActions (
|
||||
|
||||
export async function deleteObject (client: TxOperations, object: Doc): Promise<void> {
|
||||
const hierarchy = client.getHierarchy()
|
||||
const promises: Promise<any>[] = []
|
||||
const promises: Array<Promise<any>> = []
|
||||
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
|
||||
const adoc = object as AttachedDoc
|
||||
promises.push(client.removeCollection(object._class, object.space, adoc._id, adoc.attachedTo, adoc.attachedToClass, adoc.collection).catch(err => console.error(err)))
|
||||
@ -261,7 +263,7 @@ function getParentClass (hierarchy: Hierarchy, _class: Ref<Class<Doc>>): Ref<Cla
|
||||
return result
|
||||
}
|
||||
|
||||
function getMixins (hierarchy: Hierarchy, _class: Ref<Class<Doc>>, object: Doc): Ref<Mixin<Doc>>[] {
|
||||
function getMixins (hierarchy: Hierarchy, _class: Ref<Class<Doc>>, object: Doc): Array<Ref<Mixin<Doc>>> {
|
||||
const parentClass = getParentClass(hierarchy, _class)
|
||||
const descendants = hierarchy.getDescendants(parentClass)
|
||||
return descendants.filter(
|
||||
|
@ -65,8 +65,12 @@
|
||||
{#if spaceSample !== undefined && model}
|
||||
<Table
|
||||
_class={spaceSample._class}
|
||||
config={['', 'company', 'location', 'modifiedOn']}
|
||||
options={{}}
|
||||
config={['', '$lookup._class.label', 'modifiedOn']}
|
||||
options={{
|
||||
lookup: {
|
||||
_class: core.class.Class
|
||||
}
|
||||
}}
|
||||
showNotification
|
||||
baseMenuClass={core.class.Space}
|
||||
query={{
|
||||
|
20
rush.json
20
rush.json
@ -1131,5 +1131,25 @@
|
||||
"projectFolder": "server-plugins/setting-resources",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/calendar",
|
||||
"projectFolder": "plugins/calendar",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/calendar-assets",
|
||||
"projectFolder": "plugins/calendar-assets",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/calendar-resources",
|
||||
"projectFolder": "plugins/calendar-resources",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@anticrm/model-calendar",
|
||||
"projectFolder": "models/calendar",
|
||||
"shouldPublish": true
|
||||
},
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user