mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
UBERF-4946 Drive application (#5616)
This commit is contained in:
Generated
+228
-4
@@ -146,6 +146,15 @@ dependencies:
|
||||
'@rush-temp/document-resources':
|
||||
specifier: file:./projects/document-resources.tgz
|
||||
version: file:projects/document-resources.tgz(@tiptap/pm@2.2.4)(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2)
|
||||
'@rush-temp/drive':
|
||||
specifier: file:./projects/drive.tgz
|
||||
version: file:projects/drive.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2)
|
||||
'@rush-temp/drive-assets':
|
||||
specifier: file:./projects/drive-assets.tgz
|
||||
version: file:projects/drive-assets.tgz(esbuild@0.20.1)(ts-node@10.9.2)
|
||||
'@rush-temp/drive-resources':
|
||||
specifier: file:./projects/drive-resources.tgz
|
||||
version: file:projects/drive-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2)
|
||||
'@rush-temp/elastic':
|
||||
specifier: file:./projects/elastic.tgz
|
||||
version: file:projects/elastic.tgz(@types/node@20.11.19)(esbuild@0.20.1)
|
||||
@@ -254,6 +263,9 @@ dependencies:
|
||||
'@rush-temp/model-document':
|
||||
specifier: file:./projects/model-document.tgz
|
||||
version: file:projects/model-document.tgz
|
||||
'@rush-temp/model-drive':
|
||||
specifier: file:./projects/model-drive.tgz
|
||||
version: file:projects/model-drive.tgz
|
||||
'@rush-temp/model-gmail':
|
||||
specifier: file:./projects/model-gmail.tgz
|
||||
version: file:projects/model-gmail.tgz
|
||||
@@ -308,6 +320,9 @@ dependencies:
|
||||
'@rush-temp/model-server-document':
|
||||
specifier: file:./projects/model-server-document.tgz
|
||||
version: file:projects/model-server-document.tgz
|
||||
'@rush-temp/model-server-drive':
|
||||
specifier: file:./projects/model-server-drive.tgz
|
||||
version: file:projects/model-server-drive.tgz
|
||||
'@rush-temp/model-server-gmail':
|
||||
specifier: file:./projects/model-server-gmail.tgz
|
||||
version: file:projects/model-server-gmail.tgz
|
||||
@@ -530,6 +545,12 @@ dependencies:
|
||||
'@rush-temp/server-document-resources':
|
||||
specifier: file:./projects/server-document-resources.tgz
|
||||
version: file:projects/server-document-resources.tgz(esbuild@0.20.1)(ts-node@10.9.2)
|
||||
'@rush-temp/server-drive':
|
||||
specifier: file:./projects/server-drive.tgz
|
||||
version: file:projects/server-drive.tgz(esbuild@0.20.1)(ts-node@10.9.2)
|
||||
'@rush-temp/server-drive-resources':
|
||||
specifier: file:./projects/server-drive-resources.tgz
|
||||
version: file:projects/server-drive-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2)
|
||||
'@rush-temp/server-gmail':
|
||||
specifier: file:./projects/server-gmail.tgz
|
||||
version: file:projects/server-gmail.tgz(esbuild@0.20.1)(ts-node@10.9.2)
|
||||
@@ -19610,6 +19631,113 @@ packages:
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/drive-assets.tgz(esbuild@0.20.1)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-nSFnPSUpwp1cjsI5P3PnJmba3E3A9Cz4c2ZuiL51QjbtuAY7ctFZsveQrV6sfbfS/c+vvoBfw+WXcBXcPrlnXA==, tarball: file:projects/drive-assets.tgz}
|
||||
id: file:projects/drive-assets.tgz
|
||||
name: '@rush-temp/drive-assets'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@types/jest': 29.5.12
|
||||
'@types/node': 20.11.19
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@jest/types'
|
||||
- babel-jest
|
||||
- babel-plugin-macros
|
||||
- esbuild
|
||||
- node-notifier
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/drive-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-E2zO+OiX83Ig7B8ZJHiKJZydZf0RqPxXrHBnGl99l3biAcxNId4UJryMUM8KC7PQQw16ue/bERRU1dOBIs9Hng==, tarball: file:projects/drive-resources.tgz}
|
||||
id: file:projects/drive-resources.tgz
|
||||
name: '@rush-temp/drive-resources'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@types/jest': 29.5.12
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
eslint-plugin-svelte: 2.35.1(eslint@8.56.0)(svelte@4.2.12)(ts-node@10.9.2)
|
||||
fast-equals: 5.0.1
|
||||
filesize: 8.0.7
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
prettier-plugin-svelte: 3.2.2(prettier@3.2.5)(svelte@4.2.12)
|
||||
sass: 1.71.1
|
||||
svelte: 4.2.12
|
||||
svelte-check: 3.6.9(postcss-load-config@4.0.2)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12)
|
||||
svelte-eslint-parser: 0.33.1(svelte@4.2.12)
|
||||
svelte-loader: 3.2.0(svelte@4.2.12)
|
||||
svelte-preprocess: 5.1.3(postcss-load-config@4.0.2)(postcss@8.4.35)(sass@1.71.1)(svelte@4.2.12)(typescript@5.3.3)
|
||||
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@jest/types'
|
||||
- '@types/node'
|
||||
- babel-jest
|
||||
- babel-plugin-macros
|
||||
- coffeescript
|
||||
- esbuild
|
||||
- less
|
||||
- node-notifier
|
||||
- postcss
|
||||
- postcss-load-config
|
||||
- pug
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/drive.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-Av+Kk9dyNTpd9XtrMgx5Sf9+GUNDMcLDpVT+dlCdJqgcmweVQXGC81AGXDapuzoruVN0x5JdAwGL127Z3kOfxA==, tarball: file:projects/drive.tgz}
|
||||
id: file:projects/drive.tgz
|
||||
name: '@rush-temp/drive'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@types/jest': 29.5.12
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@jest/types'
|
||||
- '@types/node'
|
||||
- babel-jest
|
||||
- babel-plugin-macros
|
||||
- esbuild
|
||||
- node-notifier
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/elastic.tgz(@types/node@20.11.19)(esbuild@0.20.1):
|
||||
resolution: {integrity: sha512-iUKt8+1LhjnXTCYZv0DssFNwm1pHB+ioIePMutpYZrtO7HvwaZN4kHVneHjk5hA0EeE96JOkCwgYcPka35UvuA==, tarball: file:projects/elastic.tgz}
|
||||
id: file:projects/elastic.tgz
|
||||
@@ -20553,7 +20681,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/model-all.tgz:
|
||||
resolution: {integrity: sha512-2OrA8LVIJi2SmLHH/eIPGz3aWSD38swpk1SGyko75AbEoyJAXU6NHR8eFLbCGJIEOhF889Z9aJmXtAkuI7zpbw==, tarball: file:projects/model-all.tgz}
|
||||
resolution: {integrity: sha512-eT/WXN3UKeAlTfImDOcLVfmHGhZo/yinjhkqvpVSSCGWJhiCJBNX5vJLn9HkEem6Xh9/YCMxp2MN49n50bV7+Q==, tarball: file:projects/model-all.tgz}
|
||||
name: '@rush-temp/model-all'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
@@ -20729,6 +20857,24 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/model-drive.tgz:
|
||||
resolution: {integrity: sha512-6asmZyk0a+N8c+cmsmRDk1pq0IuMGpo3cDJefSYGyXdljeEbPyQVgidO2vbUXVLJ8NYZiZZDzWrWCww7t+tHaQ==, tarball: file:projects/model-drive.tgz}
|
||||
name: '@rush-temp/model-drive'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
prettier: 3.2.5
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/model-gmail.tgz:
|
||||
resolution: {integrity: sha512-Bmsl1/2h/DX6G5njEjb0hpKefll9pkcWV+4DyMW3KrQyz1lcFswWRSCK9fg6u3XrGe3QkMZrmikmdqR06WOV+Q==, tarball: file:projects/model-gmail.tgz}
|
||||
name: '@rush-temp/model-gmail'
|
||||
@@ -21073,6 +21219,24 @@ packages:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/model-server-drive.tgz:
|
||||
resolution: {integrity: sha512-8VZ/UCnjAiS9ZDi6oSVh1G+u6dXtO+xrWknFs2J8KUTiNcfqE98s3ok84QiR6LsMtS0Jn+JYgLppYSqL73P3/A==, tarball: file:projects/model-server-drive.tgz}
|
||||
name: '@rush-temp/model-server-drive'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
prettier: 3.2.5
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
file:projects/model-server-gmail.tgz:
|
||||
resolution: {integrity: sha512-wBrT0XWhQWs1JvlfOedP/YfmKxLdG5Ik3sv94faSTkM0JCbDielAHEzcYqDZ/W5D1nblBrDnr/rtwJ+BZ6P+UQ==, tarball: file:projects/model-server-gmail.tgz}
|
||||
name: '@rush-temp/model-server-gmail'
|
||||
@@ -22107,7 +22271,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/pod-server.tgz:
|
||||
resolution: {integrity: sha512-XHR0YptOBL1XIE0gR5RfXn8BQ+LXdWdB0t8C5S3czVnBjQccPTlsYBN1IrG9jWzUFGxPq9vGUy9Kd+dgr2KvbQ==, tarball: file:projects/pod-server.tgz}
|
||||
resolution: {integrity: sha512-On9iUbvTRMtKD+Eqe4/LgKjk4y8MwXP/VaqQ+5nnmOra1nXnMQHwkaNnT7eYhWLoH4rM88JN9RyifT8UmF7dQQ==, tarball: file:projects/pod-server.tgz}
|
||||
name: '@rush-temp/pod-server'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
@@ -22252,7 +22416,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/prod.tgz(bufferutil@4.0.8)(sass@1.71.1)(ts-node@10.9.2)(utf-8-validate@6.0.3):
|
||||
resolution: {integrity: sha512-ApNm3LLGsu8aU/ySQbpHVWR+td2eUUeCzgjnkwdw83E4QZ9mFj8I9hTN0z4gC32PAOFdxRt6P0J8vA78WBNfGw==, tarball: file:projects/prod.tgz}
|
||||
resolution: {integrity: sha512-PgH0PbsoN0q+n48ghZJrY6pRprrEUTaGK7z1o+5XMmxRKgbT3OCFTn9xhEJxIylL4o96vr1r5WLiQupebAU//w==, tarball: file:projects/prod.tgz}
|
||||
id: file:projects/prod.tgz
|
||||
name: '@rush-temp/prod'
|
||||
version: 0.0.0
|
||||
@@ -23189,6 +23353,66 @@ packages:
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/server-drive-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-KIf7tcrSge1i02B2Mfr7Nczi85c8mloCuuydcoui/uBREzyQDMvp5alcagh7qxxi+tdcuyxRxu6VBnRnM5Nm4w==, tarball: file:projects/server-drive-resources.tgz}
|
||||
id: file:projects/server-drive-resources.tgz
|
||||
name: '@rush-temp/server-drive-resources'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@types/jest': 29.5.12
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@jest/types'
|
||||
- '@types/node'
|
||||
- babel-jest
|
||||
- babel-plugin-macros
|
||||
- esbuild
|
||||
- node-notifier
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/server-drive.tgz(esbuild@0.20.1)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-PmYaAL/QMvNdU7M+vPzdVNOS5oZcpRUKS/qFFHEFN3U1RyROsFxmJ0802+KC1t+H6yRRBsZbB8bBtyj7u/mPLw==, tarball: file:projects/server-drive.tgz}
|
||||
id: file:projects/server-drive.tgz
|
||||
name: '@rush-temp/server-drive'
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@types/jest': 29.5.12
|
||||
'@types/node': 20.11.19
|
||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint: 8.56.0
|
||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||
eslint-plugin-import: 2.29.1(eslint@8.56.0)
|
||||
eslint-plugin-n: 15.7.0(eslint@8.56.0)
|
||||
eslint-plugin-promise: 6.1.1(eslint@8.56.0)
|
||||
jest: 29.7.0(@types/node@20.11.19)(ts-node@10.9.2)
|
||||
prettier: 3.2.5
|
||||
ts-jest: 29.1.2(esbuild@0.20.1)(jest@29.7.0)(typescript@5.3.3)
|
||||
typescript: 5.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@babel/core'
|
||||
- '@jest/types'
|
||||
- babel-jest
|
||||
- babel-plugin-macros
|
||||
- esbuild
|
||||
- node-notifier
|
||||
- supports-color
|
||||
- ts-node
|
||||
dev: false
|
||||
|
||||
file:projects/server-gmail-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2):
|
||||
resolution: {integrity: sha512-70qdzXaq0DidVubkXv7DmuuLqdBy+rWVOLnJASmTKKYKcmZualQI2SxmDM2wGwuGGmHNup0stFpMswL+pV5u+A==, tarball: file:projects/server-gmail-resources.tgz}
|
||||
id: file:projects/server-gmail-resources.tgz
|
||||
@@ -25432,7 +25656,7 @@ packages:
|
||||
dev: false
|
||||
|
||||
file:projects/tool.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.3):
|
||||
resolution: {integrity: sha512-Hvo30pcgIBmHUOHsuLDFZLI77rv4hq/MsyZ3xAcIJFFuQc/reUgbW3LX5wlRI0lsbMhyxf9uw5jWjWoDPZKa8A==, tarball: file:projects/tool.tgz}
|
||||
resolution: {integrity: sha512-iVwH4zmc67aEXW4wiOyvZpR05m8vmI11z7r/l/Ze+0inUoteke9f3iP4EeXQqPjw/tSlJnFUUPmW7/PUyTY1Xg==, tarball: file:projects/tool.tgz}
|
||||
id: file:projects/tool.tgz
|
||||
name: '@rush-temp/tool'
|
||||
version: 0.0.0
|
||||
|
||||
@@ -167,6 +167,11 @@
|
||||
"@hcengineering/bitrix": "^0.6.44",
|
||||
"@hcengineering/bitrix-assets": "^0.6.0",
|
||||
"@hcengineering/bitrix-resources": "^0.6.0",
|
||||
"@hcengineering/drive": "^0.6.0",
|
||||
"@hcengineering/drive-assets": "^0.6.0",
|
||||
"@hcengineering/drive-resources": "^0.6.0",
|
||||
"@hcengineering/server-drive": "^0.6.0",
|
||||
"@hcengineering/server-drive-resources": "^0.6.0",
|
||||
"@hcengineering/support": "^0.6.1",
|
||||
"@hcengineering/support-assets": "^0.6.1",
|
||||
"@hcengineering/support-resources": "^0.6.0",
|
||||
|
||||
@@ -23,6 +23,7 @@ import { chunterId } from '@hcengineering/chunter'
|
||||
import client, { clientId } from '@hcengineering/client'
|
||||
import contactPlugin, { contactId } from '@hcengineering/contact'
|
||||
import { documentId } from '@hcengineering/document'
|
||||
import { driveId } from '@hcengineering/drive'
|
||||
import gmail, { gmailId } from '@hcengineering/gmail'
|
||||
import guest, { guestId } from '@hcengineering/guest'
|
||||
import { hrId } from '@hcengineering/hr'
|
||||
@@ -56,6 +57,7 @@ import '@hcengineering/calendar-assets'
|
||||
import '@hcengineering/chunter-assets'
|
||||
import '@hcengineering/contact-assets'
|
||||
import '@hcengineering/document-assets'
|
||||
import '@hcengineering/drive-assets'
|
||||
import '@hcengineering/gmail-assets'
|
||||
import '@hcengineering/guest-assets'
|
||||
import '@hcengineering/hr-assets'
|
||||
@@ -121,6 +123,7 @@ function configureI18n(): void {
|
||||
addStringsLoader(calendarId, async (lang: string) => await import(`@hcengineering/calendar-assets/lang/${lang}.json`))
|
||||
addStringsLoader(chunterId, async (lang: string) => await import(`@hcengineering/chunter-assets/lang/${lang}.json`))
|
||||
addStringsLoader(contactId, async (lang: string) => await import(`@hcengineering/contact-assets/lang/${lang}.json`))
|
||||
addStringsLoader(driveId, async (lang: string) => await import(`@hcengineering/drive-assets/lang/${lang}.json`))
|
||||
addStringsLoader(gmailId, async (lang: string) => await import(`@hcengineering/gmail-assets/lang/${lang}.json`))
|
||||
addStringsLoader(hrId, async (lang: string) => await import(`@hcengineering/hr-assets/lang/${lang}.json`))
|
||||
addStringsLoader(inventoryId, async (lang: string) => await import(`@hcengineering/inventory-assets/lang/${lang}.json`))
|
||||
@@ -232,6 +235,7 @@ export async function configurePlatform() {
|
||||
addLocation(documentId, () => import(/* webpackChunkName: "document" */ '@hcengineering/document-resources'))
|
||||
addLocation(guestId, () => import(/* webpackChunkName: "guest" */ '@hcengineering/guest-resources'))
|
||||
addLocation(timeId, () => import(/* webpackChunkName: "time" */ '@hcengineering/time-resources'))
|
||||
addLocation(driveId, () => import(/* webpackChunkName: "drive" */ '@hcengineering/drive-resources'))
|
||||
|
||||
setMetadata(client.metadata.FilterModel, true)
|
||||
setMetadata(client.metadata.ExtraPlugins, ['preference' as Plugin])
|
||||
|
||||
@@ -95,6 +95,8 @@
|
||||
"@hcengineering/server-core": "^0.6.1",
|
||||
"@hcengineering/server-document": "^0.6.0",
|
||||
"@hcengineering/server-document-resources": "^0.6.0",
|
||||
"@hcengineering/server-drive": "^0.6.0",
|
||||
"@hcengineering/server-drive-resources": "^0.6.0",
|
||||
"@hcengineering/server-gmail": "^0.6.0",
|
||||
"@hcengineering/server-gmail-resources": "^0.6.0",
|
||||
"@hcengineering/server-hr": "^0.6.0",
|
||||
|
||||
@@ -27,6 +27,7 @@ import { serverCalendarId } from '@hcengineering/server-calendar'
|
||||
import { serverChunterId } from '@hcengineering/server-chunter'
|
||||
import { serverCollaborationId } from '@hcengineering/server-collaboration'
|
||||
import { serverContactId } from '@hcengineering/server-contact'
|
||||
import { serverDriveId } from '@hcengineering/server-drive'
|
||||
import { serverDocumentId } from '@hcengineering/server-document'
|
||||
import { serverGmailId } from '@hcengineering/server-gmail'
|
||||
import { serverGuestId } from '@hcengineering/server-guest'
|
||||
@@ -66,6 +67,7 @@ addLocation(serverViewId, () => import('@hcengineering/server-view-resources'))
|
||||
addLocation(serverDocumentId, () => import('@hcengineering/server-document-resources'))
|
||||
addLocation(serverTimeId, () => import('@hcengineering/server-time-resources'))
|
||||
addLocation(serverGuestId, () => import('@hcengineering/server-guest-resources'))
|
||||
addLocation(serverDriveId, () => import('@hcengineering/server-drive-resources'))
|
||||
|
||||
function prepareTools (): {
|
||||
mongodbUri: string
|
||||
|
||||
@@ -88,6 +88,8 @@
|
||||
"@hcengineering/model-document": "^0.6.0",
|
||||
"@hcengineering/model-server-document": "^0.6.0",
|
||||
"@hcengineering/model-time": "^0.6.0",
|
||||
"@hcengineering/model-server-time": "^0.6.0"
|
||||
"@hcengineering/model-server-time": "^0.6.0",
|
||||
"@hcengineering/model-drive": "^0.6.0",
|
||||
"@hcengineering/model-server-drive": "^0.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import {
|
||||
import { serverContactId, createModel as serverContactModel } from '@hcengineering/model-server-contact'
|
||||
import { serverCoreId, createModel as serverCoreModel } from '@hcengineering/model-server-core'
|
||||
import { serverDocumentId, createModel as serverDocumentModel } from '@hcengineering/model-server-document'
|
||||
import { serverDriveId, createModel as serverDriveModel } from '@hcengineering/model-server-drive'
|
||||
import { serverGmailId, createModel as serverGmailModel } from '@hcengineering/model-server-gmail'
|
||||
import { serverGuestId, createModel as serverGuestModel } from '@hcengineering/model-server-guest'
|
||||
import { serverHrId, createModel as serverHrModel } from '@hcengineering/model-server-hr'
|
||||
@@ -63,6 +64,7 @@ import { serverTimeId, createModel as serverTimeModel } from '@hcengineering/mod
|
||||
import { serverTrackerId, createModel as serverTrackerModel } from '@hcengineering/model-server-tracker'
|
||||
import { serverViewId, createModel as serverViewModel } from '@hcengineering/model-server-view'
|
||||
import setting, { settingId, createModel as settingModel } from '@hcengineering/model-setting'
|
||||
import { driveId, createModel as driveModel } from '@hcengineering/model-drive'
|
||||
import { supportId, createModel as supportModel } from '@hcengineering/model-support'
|
||||
import { tagsId, createModel as tagsModel } from '@hcengineering/model-tags'
|
||||
import { taskId, createModel as taskModel } from '@hcengineering/model-task'
|
||||
@@ -296,6 +298,7 @@ export default function buildModel (enabled: string[] = ['*'], disabled: string[
|
||||
}
|
||||
],
|
||||
[timeModel, timeId],
|
||||
[driveModel, driveId],
|
||||
[supportModel, supportId],
|
||||
|
||||
[serverCoreModel, serverCoreId],
|
||||
@@ -323,7 +326,8 @@ export default function buildModel (enabled: string[] = ['*'], disabled: string[
|
||||
[serverOpenAI, openAIId],
|
||||
[serverDocumentModel, serverDocumentId],
|
||||
[serverTimeModel, serverTimeId],
|
||||
[serverGuestModel, serverGuestId]
|
||||
[serverGuestModel, serverGuestId],
|
||||
[serverDriveModel, serverDriveId]
|
||||
]
|
||||
|
||||
for (const [b, id, config] of builders) {
|
||||
|
||||
@@ -21,7 +21,6 @@ export default mergeIds(coreId, core, {
|
||||
Archived: '' as IntlString,
|
||||
ClassLabel: '' as IntlString,
|
||||
ClassPropertyLabel: '' as IntlString,
|
||||
Members: '' as IntlString,
|
||||
Blob: '' as IntlString,
|
||||
BlobContentType: '' as IntlString,
|
||||
BlobEtag: '' as IntlString,
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/model/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig",
|
||||
"rigProfile": "model"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@hcengineering/model-drive",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"template": "@hcengineering/model-package",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"format": "format src",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/model": "^0.6.7",
|
||||
"@hcengineering/model-core": "^0.6.0",
|
||||
"@hcengineering/model-preference": "^0.6.0",
|
||||
"@hcengineering/model-tracker": "^0.6.0",
|
||||
"@hcengineering/model-view": "^0.6.0",
|
||||
"@hcengineering/model-workbench": "^0.6.1",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/drive": "^0.6.0",
|
||||
"@hcengineering/drive-resources": "^0.6.0",
|
||||
"@hcengineering/ui": "^0.6.11",
|
||||
"@hcengineering/view": "^0.6.9"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
//
|
||||
// Copyright © 2024 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 core, {
|
||||
type Domain,
|
||||
type Role,
|
||||
type RolesAssignment,
|
||||
type Type,
|
||||
Account,
|
||||
AccountRole,
|
||||
Ref,
|
||||
IndexKind,
|
||||
DOMAIN_MODEL,
|
||||
type Blob
|
||||
} from '@hcengineering/core'
|
||||
import { type Drive, type File, type Folder, type Resource, driveId } from '@hcengineering/drive'
|
||||
import { type Builder, Model, UX, Mixin, Prop, TypeString, Index, TypeRef, ReadOnly } from '@hcengineering/model'
|
||||
import { TDoc, TType, TTypedSpace } from '@hcengineering/model-core'
|
||||
import tracker from '@hcengineering/model-tracker'
|
||||
import view, { type Viewlet, classPresenter, createAction } from '@hcengineering/model-view'
|
||||
import workbench from '@hcengineering/model-workbench'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
|
||||
import drive from './plugin'
|
||||
|
||||
export { driveId } from '@hcengineering/drive'
|
||||
export { drive as default }
|
||||
|
||||
export const DOMAIN_DRIVE = 'drive' as Domain
|
||||
|
||||
/** @public */
|
||||
export function TypeFilesize (): Type<number> {
|
||||
return { _class: drive.class.TypeFileSize, label: drive.string.Size }
|
||||
}
|
||||
|
||||
@Model(drive.class.TypeFileSize, core.class.Type, DOMAIN_MODEL)
|
||||
export class TTypeFileSize extends TType {}
|
||||
|
||||
@Model(drive.class.Drive, core.class.TypedSpace)
|
||||
@UX(drive.string.Drive)
|
||||
export class TDrive extends TTypedSpace implements Drive {}
|
||||
|
||||
@Mixin(drive.mixin.DefaultDriveTypeData, drive.class.Drive)
|
||||
@UX(getEmbeddedLabel('Default drive type'))
|
||||
export class TDefaultDriveTypeData extends TDrive implements RolesAssignment {
|
||||
[key: Ref<Role>]: Ref<Account>[]
|
||||
}
|
||||
|
||||
@Model(drive.class.Resource, core.class.Doc, DOMAIN_DRIVE)
|
||||
@UX(drive.string.Resource)
|
||||
export class TResource extends TDoc implements Resource {
|
||||
declare space: Ref<Drive>
|
||||
|
||||
@Prop(TypeString(), drive.string.Name)
|
||||
@Index(IndexKind.FullText)
|
||||
name!: string
|
||||
|
||||
@Prop(TypeRef(core.class.Blob), drive.string.File)
|
||||
@ReadOnly()
|
||||
file?: Ref<Blob>
|
||||
|
||||
@Prop(TypeRef(drive.class.Resource), drive.string.Parent)
|
||||
@Index(IndexKind.Indexed)
|
||||
@ReadOnly()
|
||||
parent!: Ref<Resource>
|
||||
|
||||
@Prop(TypeRef(drive.class.Resource), drive.string.Path)
|
||||
@ReadOnly()
|
||||
path!: Ref<Resource>[]
|
||||
}
|
||||
|
||||
@Model(drive.class.Folder, drive.class.Resource, DOMAIN_DRIVE)
|
||||
@UX(drive.string.Folder)
|
||||
export class TFolder extends TResource implements Folder {
|
||||
@Prop(TypeRef(drive.class.Folder), drive.string.Parent)
|
||||
@Index(IndexKind.Indexed)
|
||||
@ReadOnly()
|
||||
declare parent: Ref<Folder>
|
||||
|
||||
@Prop(TypeRef(drive.class.Folder), drive.string.Path)
|
||||
@ReadOnly()
|
||||
declare path: Ref<Folder>[]
|
||||
|
||||
declare file: undefined
|
||||
}
|
||||
|
||||
@Model(drive.class.File, drive.class.Resource, DOMAIN_DRIVE)
|
||||
@UX(drive.string.File)
|
||||
export class TFile extends TResource implements File {
|
||||
@Prop(TypeRef(core.class.Blob), drive.string.File)
|
||||
@ReadOnly()
|
||||
declare file: Ref<Blob>
|
||||
|
||||
@Prop(TypeRef(drive.class.Folder), drive.string.Parent)
|
||||
@Index(IndexKind.Indexed)
|
||||
@ReadOnly()
|
||||
declare parent: Ref<Folder>
|
||||
|
||||
@Prop(TypeRef(drive.class.Folder), drive.string.Path)
|
||||
@ReadOnly()
|
||||
declare path: Ref<Folder>[]
|
||||
}
|
||||
|
||||
function defineDrive (builder: Builder): void {
|
||||
builder.createModel(TDrive, TDefaultDriveTypeData)
|
||||
|
||||
builder.mixin(drive.class.Drive, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: drive.component.DrivePresenter
|
||||
})
|
||||
|
||||
builder.mixin(drive.class.Drive, core.class.Class, view.mixin.ObjectPanel, {
|
||||
component: drive.component.DrivePanel
|
||||
})
|
||||
|
||||
builder.mixin(drive.class.Drive, core.class.Class, view.mixin.LinkProvider, {
|
||||
encode: drive.function.DriveLinkProvider
|
||||
})
|
||||
|
||||
// Space type
|
||||
|
||||
builder.createDoc(
|
||||
core.class.SpaceTypeDescriptor,
|
||||
core.space.Model,
|
||||
{
|
||||
name: drive.string.Drive,
|
||||
description: drive.string.Description,
|
||||
icon: drive.icon.Drive,
|
||||
baseClass: drive.class.Drive,
|
||||
availablePermissions: [
|
||||
core.permission.UpdateSpace,
|
||||
core.permission.ArchiveSpace,
|
||||
core.permission.ForbidDeleteObject
|
||||
]
|
||||
},
|
||||
drive.descriptor.DriveType
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.SpaceType,
|
||||
core.space.Model,
|
||||
{
|
||||
name: 'Default drive type',
|
||||
descriptor: drive.descriptor.DriveType,
|
||||
roles: 0,
|
||||
targetClass: drive.mixin.DefaultDriveTypeData
|
||||
},
|
||||
drive.spaceType.DefaultDrive
|
||||
)
|
||||
|
||||
// Navigator
|
||||
|
||||
builder.mixin(drive.class.Drive, core.class.Class, view.mixin.SpacePresenter, {
|
||||
presenter: drive.component.DriveSpacePresenter
|
||||
})
|
||||
|
||||
builder.createDoc(
|
||||
view.class.Viewlet,
|
||||
core.space.Model,
|
||||
{
|
||||
attachTo: drive.class.Drive,
|
||||
descriptor: view.viewlet.Table,
|
||||
configOptions: {
|
||||
hiddenKeys: ['name', 'description']
|
||||
},
|
||||
config: ['', 'members', 'owners', 'private', 'archived']
|
||||
},
|
||||
drive.viewlet.DriveTable
|
||||
)
|
||||
|
||||
// Actions
|
||||
|
||||
builder.mixin(drive.class.Drive, core.class.Class, view.mixin.IgnoreActions, {
|
||||
actions: [tracker.action.EditRelatedTargets, tracker.action.NewRelatedIssue]
|
||||
})
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: drive.actionImpl.EditDrive,
|
||||
label: drive.string.EditDrive,
|
||||
icon: view.icon.Edit,
|
||||
input: 'focus',
|
||||
category: drive.category.Drive,
|
||||
target: drive.class.Drive,
|
||||
visibilityTester: view.function.CanEditSpace,
|
||||
query: {},
|
||||
context: {
|
||||
mode: ['context', 'browser'],
|
||||
group: 'edit'
|
||||
}
|
||||
},
|
||||
drive.action.EditDrive
|
||||
)
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: drive.actionImpl.CreateRootFolder,
|
||||
label: drive.string.CreateFolder,
|
||||
icon: drive.icon.Folder,
|
||||
category: drive.category.Drive,
|
||||
input: 'none',
|
||||
target: drive.class.Drive,
|
||||
context: {
|
||||
mode: ['context', 'browser'],
|
||||
application: drive.app.Drive,
|
||||
group: 'create'
|
||||
}
|
||||
},
|
||||
drive.action.CreateRootFolder
|
||||
)
|
||||
}
|
||||
|
||||
function defineResource (builder: Builder): void {
|
||||
builder.createModel(TTypeFileSize, TResource)
|
||||
|
||||
classPresenter(builder, drive.class.TypeFileSize, drive.component.FileSizePresenter)
|
||||
|
||||
builder.mixin(drive.class.Resource, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: drive.component.ResourcePresenter
|
||||
})
|
||||
|
||||
builder.createDoc<Viewlet>(
|
||||
view.class.Viewlet,
|
||||
core.space.Model,
|
||||
{
|
||||
attachTo: drive.class.Resource,
|
||||
descriptor: view.viewlet.Table,
|
||||
config: [
|
||||
{
|
||||
key: '',
|
||||
presenter: drive.component.ResourcePresenter,
|
||||
label: drive.string.Name
|
||||
},
|
||||
{
|
||||
key: '$lookup.file.size',
|
||||
presenter: drive.component.FileSizePresenter,
|
||||
label: drive.string.Size
|
||||
},
|
||||
{
|
||||
key: '$lookup.file.modifiedOn'
|
||||
},
|
||||
'createdBy'
|
||||
],
|
||||
configOptions: {
|
||||
hiddenKeys: ['name', 'file', 'parent', 'path'],
|
||||
sortable: true
|
||||
}
|
||||
},
|
||||
drive.viewlet.FileTable
|
||||
)
|
||||
|
||||
// builder.createDoc<Viewlet>(
|
||||
// view.class.Viewlet,
|
||||
// core.space.Model,
|
||||
// {
|
||||
// attachTo: drive.class.Resource,
|
||||
// descriptor: drive.viewlet.Grid,
|
||||
// config: ['', 'type', 'size', 'lastModified', 'createdBy'],
|
||||
// configOptions: {
|
||||
// hiddenKeys: ['name', 'file', 'parent', 'path'],
|
||||
// sortable: true
|
||||
// }
|
||||
// },
|
||||
// drive.viewlet.FileGrid
|
||||
// )
|
||||
}
|
||||
|
||||
function defineFolder (builder: Builder): void {
|
||||
builder.createModel(TFolder)
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: drive.component.FolderPresenter
|
||||
})
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, view.mixin.ObjectEditor, {
|
||||
editor: drive.component.EditFolder
|
||||
})
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, view.mixin.ObjectPanel, {
|
||||
component: drive.component.FolderPanel
|
||||
})
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, view.mixin.LinkProvider, {
|
||||
encode: drive.function.FolderLinkProvider
|
||||
})
|
||||
|
||||
// Actions
|
||||
|
||||
builder.mixin(drive.class.Folder, core.class.Class, view.mixin.IgnoreActions, {
|
||||
actions: [
|
||||
view.action.Open,
|
||||
view.action.OpenInNewTab,
|
||||
tracker.action.EditRelatedTargets,
|
||||
tracker.action.NewRelatedIssue
|
||||
]
|
||||
})
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: drive.actionImpl.CreateChildFolder,
|
||||
label: drive.string.CreateFolder,
|
||||
icon: drive.icon.Folder,
|
||||
category: drive.category.Drive,
|
||||
input: 'none',
|
||||
target: drive.class.Folder,
|
||||
context: {
|
||||
mode: ['context', 'browser'],
|
||||
application: drive.app.Drive,
|
||||
group: 'create'
|
||||
}
|
||||
},
|
||||
drive.action.CreateChildFolder
|
||||
)
|
||||
}
|
||||
|
||||
function defineFile (builder: Builder): void {
|
||||
builder.createModel(TFile)
|
||||
|
||||
builder.mixin(drive.class.File, core.class.Class, view.mixin.ObjectPresenter, {
|
||||
presenter: drive.component.FilePresenter
|
||||
})
|
||||
|
||||
// Actions
|
||||
|
||||
builder.mixin(drive.class.File, core.class.Class, view.mixin.IgnoreActions, {
|
||||
actions: [view.action.OpenInNewTab, tracker.action.EditRelatedTargets, tracker.action.NewRelatedIssue]
|
||||
})
|
||||
|
||||
createAction(
|
||||
builder,
|
||||
{
|
||||
action: drive.actionImpl.DownloadFile,
|
||||
label: drive.string.Download,
|
||||
icon: drive.icon.Download,
|
||||
category: drive.category.Drive,
|
||||
input: 'none',
|
||||
target: drive.class.File,
|
||||
context: {
|
||||
mode: ['context', 'browser'],
|
||||
application: drive.app.Drive,
|
||||
group: 'tools'
|
||||
}
|
||||
},
|
||||
drive.action.DownloadFile
|
||||
)
|
||||
}
|
||||
|
||||
function defineApplication (builder: Builder): void {
|
||||
builder.createDoc(
|
||||
workbench.class.Application,
|
||||
core.space.Model,
|
||||
{
|
||||
label: drive.string.Drive,
|
||||
icon: drive.icon.Drive,
|
||||
alias: driveId,
|
||||
hidden: false,
|
||||
locationResolver: drive.resolver.Location,
|
||||
navigatorModel: {
|
||||
specials: [
|
||||
{
|
||||
id: 'browser',
|
||||
accessLevel: AccountRole.User,
|
||||
label: drive.string.Drives,
|
||||
icon: view.icon.List,
|
||||
component: workbench.component.SpecialView,
|
||||
componentProps: {
|
||||
_class: drive.class.Drive,
|
||||
label: drive.string.Drives
|
||||
},
|
||||
position: 'top'
|
||||
}
|
||||
],
|
||||
spaces: [
|
||||
{
|
||||
id: 'drives',
|
||||
label: drive.string.Drive,
|
||||
spaceClass: drive.class.Drive,
|
||||
addSpaceLabel: drive.string.CreateDrive,
|
||||
createComponent: drive.component.CreateDrive,
|
||||
icon: drive.icon.Drive,
|
||||
// intentionally left empty in order to make space presenter working
|
||||
specials: []
|
||||
}
|
||||
]
|
||||
},
|
||||
navHeaderComponent: drive.component.DriveSpaceHeader
|
||||
},
|
||||
drive.app.Drive
|
||||
)
|
||||
}
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createDoc(
|
||||
view.class.ViewletDescriptor,
|
||||
core.space.Model,
|
||||
{
|
||||
label: view.string.Grid,
|
||||
icon: view.icon.Table,
|
||||
component: drive.component.GridView
|
||||
},
|
||||
drive.viewlet.Grid
|
||||
)
|
||||
|
||||
defineDrive(builder)
|
||||
defineResource(builder)
|
||||
defineFolder(builder)
|
||||
defineFile(builder)
|
||||
defineApplication(builder)
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Doc, Ref } from '@hcengineering/core'
|
||||
import {} from '@hcengineering/core'
|
||||
import { driveId } from '@hcengineering/drive'
|
||||
import drive from '@hcengineering/drive-resources/src/plugin'
|
||||
import { type IntlString, type Resource, mergeIds } from '@hcengineering/platform'
|
||||
import { type AnyComponent, type Location } from '@hcengineering/ui'
|
||||
import {
|
||||
type Action,
|
||||
type ActionCategory,
|
||||
type ViewAction,
|
||||
type Viewlet,
|
||||
type ViewletDescriptor
|
||||
} from '@hcengineering/view'
|
||||
|
||||
export default mergeIds(driveId, drive, {
|
||||
component: {
|
||||
GridView: '' as AnyComponent,
|
||||
CreateDrive: '' as AnyComponent,
|
||||
DriveSpaceHeader: '' as AnyComponent,
|
||||
DriveSpacePresenter: '' as AnyComponent,
|
||||
DrivePanel: '' as AnyComponent,
|
||||
DrivePresenter: '' as AnyComponent,
|
||||
EditFolder: '' as AnyComponent,
|
||||
FolderPanel: '' as AnyComponent,
|
||||
FolderPresenter: '' as AnyComponent,
|
||||
FilePresenter: '' as AnyComponent,
|
||||
FileSizePresenter: '' as AnyComponent,
|
||||
ResourcePresenter: '' as AnyComponent
|
||||
},
|
||||
function: {
|
||||
DriveLinkProvider: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>,
|
||||
FolderLinkProvider: '' as Resource<(doc: Doc, props: Record<string, any>) => Promise<Location>>
|
||||
},
|
||||
viewlet: {
|
||||
Grid: '' as Ref<ViewletDescriptor>,
|
||||
DriveTable: '' as Ref<Viewlet>,
|
||||
FileTable: '' as Ref<Viewlet>,
|
||||
FileGrid: '' as Ref<Viewlet>
|
||||
},
|
||||
category: {
|
||||
Drive: '' as Ref<ActionCategory>
|
||||
},
|
||||
action: {
|
||||
CreateChildFolder: '' as Ref<Action>,
|
||||
CreateRootFolder: '' as Ref<Action>,
|
||||
EditDrive: '' as Ref<Action>,
|
||||
DownloadFile: '' as Ref<Action>
|
||||
},
|
||||
actionImpl: {
|
||||
CreateChildFolder: '' as ViewAction,
|
||||
CreateRootFolder: '' as ViewAction,
|
||||
EditDrive: '' as ViewAction,
|
||||
DownloadFile: '' as ViewAction
|
||||
},
|
||||
string: {
|
||||
Name: '' as IntlString,
|
||||
Description: '' as IntlString,
|
||||
Size: '' as IntlString,
|
||||
Type: '' as IntlString,
|
||||
LastModified: '' as IntlString,
|
||||
Parent: '' as IntlString,
|
||||
Path: '' as IntlString,
|
||||
Drives: '' as IntlString,
|
||||
Download: '' as IntlString
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/model/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/model/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig",
|
||||
"rigProfile": "model"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@hcengineering/model-server-drive",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"template": "@hcengineering/model-package",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"format": "format src",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/model": "^0.6.7",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/drive": "^0.6.0",
|
||||
"@hcengineering/server-core": "^0.6.1",
|
||||
"@hcengineering/server-drive": "^0.6.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type Builder } from '@hcengineering/model'
|
||||
|
||||
import core, { type Class, type Doc } from '@hcengineering/core'
|
||||
import drive from '@hcengineering/drive'
|
||||
import serverCore, { type ObjectDDParticipant } from '@hcengineering/server-core'
|
||||
import serverDrive from '@hcengineering/server-drive'
|
||||
|
||||
export { serverDriveId } from '@hcengineering/server-drive'
|
||||
|
||||
export function createModel (builder: Builder): void {
|
||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||
trigger: serverDrive.trigger.OnFileDelete,
|
||||
txMatch: {
|
||||
_class: core.class.TxRemoveDoc,
|
||||
objectClass: drive.class.File
|
||||
}
|
||||
})
|
||||
|
||||
builder.mixin<Class<Doc>, ObjectDDParticipant>(
|
||||
drive.class.Folder,
|
||||
core.class.Class,
|
||||
serverCore.mixin.ObjectDDParticipant,
|
||||
{
|
||||
collectDocs: serverDrive.function.FindFolderResources
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/model/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
}
|
||||
}
|
||||
@@ -217,6 +217,7 @@ export default plugin(coreId, {
|
||||
Account: '' as IntlString,
|
||||
StatusCategory: '' as IntlString,
|
||||
Rank: '' as IntlString,
|
||||
Members: '' as IntlString,
|
||||
Owners: '' as IntlString,
|
||||
Permission: '' as IntlString,
|
||||
CreateObject: '' as IntlString,
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
$: isNew = teamspace === undefined
|
||||
|
||||
let typeId: Ref<SpaceType> | undefined = teamspace?.type || document.spaceType.DefaultTeamspaceType
|
||||
let typeId: Ref<SpaceType> | undefined = teamspace?.type ?? document.spaceType.DefaultTeamspaceType
|
||||
let spaceType: WithLookup<SpaceType> | undefined
|
||||
|
||||
$: void loadSpaceType(typeId)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Class, Doc, Mixin, Ref, Space, SpaceType, SpaceTypeDescriptor } from '@hcengineering/core'
|
||||
import type { Class, Doc, Mixin, Ref, SpaceType, SpaceTypeDescriptor } from '@hcengineering/core'
|
||||
import { NotificationGroup, NotificationType } from '@hcengineering/notification'
|
||||
import type { Asset, Plugin, Resource } from '@hcengineering/platform'
|
||||
import { IntlString, plugin } from '@hcengineering/platform'
|
||||
@@ -60,9 +60,6 @@ export const documentPlugin = plugin(documentId, {
|
||||
Star: '' as Asset,
|
||||
Starred: '' as Asset
|
||||
},
|
||||
space: {
|
||||
Documents: '' as Ref<Space>
|
||||
},
|
||||
app: {
|
||||
Documents: '' as Ref<Doc>
|
||||
},
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/assets/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="drive" viewBox="0 0 32 32">
|
||||
<path d="M16 3C10.7021 3 5 4.252 5 7V25C5 27.748 10.7021 29 16 29C21.2979 29 27 27.748 27 25V7C27 4.252 21.2979 3 16 3ZM16 5C21.7976 5 24.7949 6.4341 24.9968 7C24.7949 7.5659 21.7976 9 16 9C10.1587 9 7.1606 7.5444 7 7.0176V7.0127C7.1606 6.4556 10.1587 5 16 5ZM7 9.4277C9.1279 10.4951 12.6426 11 16 11C19.3574 11 22.8721 10.4951 25 9.4277V12.9873C24.8394 13.5444 21.8413 15 16 15C10.1499 15 7.1509 13.54 7 13V9.4277ZM7 15.4277C9.1279 16.4951 12.6426 17 16 17C19.3574 17 22.8721 16.4951 25 15.4277V18.9873C24.8394 19.5444 21.8413 21 16 21C10.1499 21 7.1509 19.54 7 19V15.4277ZM16 27C10.1499 27 7.1509 25.54 7 25V21.4277C9.1279 22.4951 12.6426 23 16 23C19.3574 23 22.8721 22.4951 25 21.4277V24.9873C24.8394 25.5444 21.8413 27 16 27Z" fill="currentColor"/>
|
||||
</symbol>
|
||||
<symbol id="file" viewBox="0 0 32 32">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9 4C7.89543 4 7 4.89543 7 6V26C7 27.1046 7.89543 28 9 28H23C24.1046 28 25 27.1046 25 26V12H21C18.7909 12 17 10.2091 17 8V4H9ZM19 4.41421V8C19 9.10457 19.8954 10 21 10H24.5858L19 4.41421ZM5 6C5 3.79086 6.79086 2 9 2H18.5858C19.1162 2 19.6249 2.21071 20 2.58579L26.4142 9C26.7893 9.37507 27 9.88378 27 10.4142V26C27 28.2091 25.2091 30 23 30H9C6.79086 30 5 28.2091 5 26V6Z" fill="currentColor"/>
|
||||
</symbol>
|
||||
<symbol id="folder" viewBox="0 0 32 32">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9C2 6.23858 4.23858 4 7 4H10.6716C11.4672 4 12.2303 4.31607 12.7929 4.87868L15.6213 7.70711C15.8089 7.89464 16.0632 8 16.3284 8H25C27.7614 8 30 10.2386 30 13V23C30 25.7614 27.7614 28 25 28H7C4.23858 28 2 25.7614 2 23V9ZM7 6C5.34315 6 4 7.34315 4 9V23C4 24.6569 5.34315 26 7 26H25C26.6569 26 28 24.6569 28 23V13C28 11.3431 26.6569 10 25 10H16.3284C15.5328 10 14.7697 9.68393 14.2071 9.12132L11.3787 6.29289C11.1911 6.10536 10.9368 6 10.6716 6H7Z" fill="currentColor"/>
|
||||
</symbol>
|
||||
<symbol id="folder-open" viewBox="0 0 33 32">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M28 14V13C28 11.3431 26.6569 10 25 10H16.3284C15.5328 10 14.7697 9.68393 14.2071 9.12132L11.3787 6.29289C11.1911 6.10536 10.9368 6 10.6716 6H7C5.34315 6 4 7.34315 4 9V21L5.17111 16.9011C5.66174 15.1839 7.23128 14 9.01721 14H28Z" fill="currentColor" fill-opacity="0.1"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 4C4.23858 4 2 6.23858 2 9V23C2 25.7614 4.23858 28 7 28H26.9828C28.7687 28 30.3383 26.8161 30.8289 25.0989L32.5432 19.0989C33.147 16.9856 31.9391 14.8804 30 14.2152V13C30 10.2386 27.7614 8 25 8H16.3284C16.0632 8 15.8089 7.89464 15.6213 7.70711L12.7929 4.87868C12.2303 4.31607 11.4672 4 10.6716 4H7ZM28 14V13C28 11.3431 26.6569 10 25 10H16.3284C15.5328 10 14.7697 9.68393 14.2071 9.12132L11.3787 6.29289C11.1911 6.10536 10.9368 6 10.6716 6H7C5.34315 6 4 7.34315 4 9V21L5.17111 16.9011C5.66174 15.1839 7.23128 14 9.01721 14H28Z" fill="currentColor"/>
|
||||
</symbol>
|
||||
<symbol id="folder-closed" viewBox="0 0 32 32">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 9C2 6.23858 4.23858 4 7 4H10.6716C11.4672 4 12.2303 4.31607 12.7929 4.87868L15.6213 7.70711C15.8089 7.89464 16.0632 8 16.3284 8H25C27.7614 8 30 10.2386 30 13V23C30 25.7614 27.7614 28 25 28H7C4.23858 28 2 25.7614 2 23V9ZM7 6C5.34315 6 4 7.34315 4 9V23C4 24.6569 5.34315 26 7 26H25C26.6569 26 28 24.6569 28 23V13C28 11.3431 26.6569 10 25 10H16.3284C15.5328 10 14.7697 9.68393 14.2071 9.12132L11.3787 6.29289C11.1911 6.10536 10.9368 6 10.6716 6H7Z" fill="currentColor"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 6C5.34315 6 4 7.34315 4 9V23C4 24.6569 5.34315 26 7 26H25C26.6569 26 28 24.6569 28 23V13C28 11.3431 26.6569 10 25 10H16.3284C15.5328 10 14.7697 9.68393 14.2071 9.12132L11.3787 6.29289C11.1911 6.10536 10.9368 6 10.6716 6H7Z" fill="currentColor" fill-opacity="0.1"/>
|
||||
</symbol>
|
||||
<symbol id="download" viewBox="0 0 24 24">
|
||||
<path d="M18.7,9.6C18.5,6,15.6,3.2,12,3.2C8.4,3.2,5.5,6,5.3,9.5c-2.3,0.7-4,2.9-4,5.5c0,3.2,2.6,5.8,5.8,5.8 c0.5,0,1.1-0.1,1.6-0.2C9,20.4,9.2,20,9.1,19.6S8.6,19,8.2,19.1c-0.4,0.1-0.8,0.2-1.2,0.2c-2.3,0-4.2-1.9-4.2-4.2 c0-2,1.4-3.7,3.3-4.1c0.2,0,0.3-0.1,0.4-0.2c0.2-0.1,0.4-0.4,0.4-0.6c0-2.9,2.4-5.2,5.2-5.2s5.2,2.4,5.2,5.2c0,0.1,0,0.1,0,0.2 c0,0.3,0.2,0.6,0.6,0.7c1.9,0.4,3.3,2.1,3.3,4.1c0,2.3-1.9,4.2-4.2,4.2c-0.4,0-0.8-0.1-1.2-0.2c-0.4-0.1-0.8,0.1-0.9,0.5 c-0.1,0.4,0.1,0.8,0.5,0.9c0.5,0.1,1,0.2,1.6,0.2c3.2,0,5.8-2.6,5.8-5.8C22.6,12.5,21,10.4,18.7,9.6z" />
|
||||
<path d="M16.1,14.5c-0.3-0.3-0.8-0.3-1.1,0l-2.3,2.3V10c0-0.4-0.3-0.8-0.8-0.8s-0.8,0.3-0.8,0.8v6.7l-2.2-2.2 c-0.3-0.3-0.8-0.3-1.1,0c-0.3,0.3-0.3,0.8,0,1.1l3.5,3.5c0.3,0.3,0.8,0.3,1.1,0l3.6-3.5C16.4,15.2,16.4,14.8,16.1,14.5z" />
|
||||
</symbol>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig",
|
||||
"rigProfile": "assets"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"string": {
|
||||
"Drive": "Drive",
|
||||
"Drives": "Drives",
|
||||
"File": "File",
|
||||
"Folder": "Folder",
|
||||
"Resource": "Resource",
|
||||
"Name": "Name",
|
||||
"Description": "Description",
|
||||
"Size": "Size",
|
||||
"Type": "Type",
|
||||
"LastModified": "Last modified",
|
||||
"Parent": "Parent",
|
||||
"Path": "Path",
|
||||
"Download": "Download",
|
||||
"CreateDrive": "Create Drive",
|
||||
"CreateFolder": "Create Folder",
|
||||
"UploadFile": "Upload File",
|
||||
"UploadFolder": "Upload Folder",
|
||||
"EditDrive": "Edit Drive",
|
||||
"RoleLabel": "Role",
|
||||
"Root": "/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"string": {
|
||||
"Storage": "Depósito"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"string": {
|
||||
"Storage": "Armazenagem"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"string": {
|
||||
"Drive": "Диск",
|
||||
"Drives": "Диски",
|
||||
"File": "Файл",
|
||||
"Folder": "Папка",
|
||||
"Resource": "Ресурс",
|
||||
"Name": "Название",
|
||||
"Description": "Описание",
|
||||
"Size": "Размер",
|
||||
"Type": "Тип",
|
||||
"LastModified": "Последнее изменение",
|
||||
"Parent": "Родительская папка",
|
||||
"Path": "Путь",
|
||||
"Download": "Скачать",
|
||||
"CreateDrive": "Создать диск",
|
||||
"CreateFolder": "Создать папку",
|
||||
"UploadFile": "Загрузить файл",
|
||||
"UploadFolder": "Загрузить папку",
|
||||
"EditDrive": "Редактировать",
|
||||
"RoleLabel": "Роль",
|
||||
"Root": "/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "@hcengineering/drive-assets",
|
||||
"version": "0.6.0",
|
||||
"main": "src/index.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"template": "@hcengineering/assets-package",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"test": "jest --passWithNoTests --silent",
|
||||
"build:docs": "",
|
||||
"format": "format src",
|
||||
"build:watch": "compile",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:test": "jest --passWithNoTests --silent",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint": "^8.54.0",
|
||||
"prettier": "^3.1.0",
|
||||
"@types/node": "~20.11.16",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5",
|
||||
"typescript": "^5.3.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/drive": "^0.6.0"
|
||||
},
|
||||
"repository": "https://github.com/hcenginneing/anticrm",
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { makeLocalesTest } from '@hcengineering/platform'
|
||||
|
||||
it(
|
||||
'Locales are equale',
|
||||
makeLocalesTest((lang) => import(`../../lang/${lang}.json`))
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
//
|
||||
// Copyright © 2024 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 { loadMetadata } from '@hcengineering/platform'
|
||||
import drive from '@hcengineering/drive'
|
||||
|
||||
const icons = require('../assets/icons.svg') as string // eslint-disable-line
|
||||
loadMetadata(drive.icon, {
|
||||
Drive: `${icons}#drive`,
|
||||
File: `${icons}#file`,
|
||||
Folder: `${icons}#folder`,
|
||||
FolderOpen: `${icons}#folder-open`,
|
||||
FolderClosed: `${icons}#folder-closed`,
|
||||
Download: `${icons}#download`
|
||||
})
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/assets/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"types": ["node", "jest"],
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/ui/eslint.config.json'],
|
||||
parserOptions: { tsconfigRootDir: __dirname }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"printWidth": 120,
|
||||
"useTabs": false,
|
||||
"bracketSpacing": true,
|
||||
"proseWrap": "preserve",
|
||||
"plugins": [
|
||||
"prettier-plugin-svelte"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.svelte",
|
||||
"options": {
|
||||
"parser": "svelte"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig",
|
||||
"rigProfile": "ui"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)']
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "@hcengineering/drive-resources",
|
||||
"version": "0.6.0",
|
||||
"main": "src/index.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile ui",
|
||||
"build:docs": "api-extractor run --local",
|
||||
"format": "format src",
|
||||
"svelte-check": "do-svelte-check",
|
||||
"_phase:svelte-check": "do-svelte-check",
|
||||
"build:watch": "compile ui",
|
||||
"_phase:build": "compile ui",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte-loader": "^3.2.0",
|
||||
"sass": "^1.53.0",
|
||||
"svelte-preprocess": "^5.1.3",
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-svelte": "^2.35.1",
|
||||
"prettier-plugin-svelte": "^3.2.2",
|
||||
"eslint": "^8.54.0",
|
||||
"prettier": "^3.1.0",
|
||||
"svelte-check": "^3.6.9",
|
||||
"typescript": "^5.3.3",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5",
|
||||
"svelte-eslint-parser": "^0.33.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/analytics": "^0.6.0",
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/attachment": "^0.6.9",
|
||||
"@hcengineering/drive": "^0.6.0",
|
||||
"@hcengineering/contact-resources": "^0.6.0",
|
||||
"@hcengineering/panel": "^0.6.15",
|
||||
"@hcengineering/presentation": "^0.6.2",
|
||||
"@hcengineering/ui": "^0.6.11",
|
||||
"@hcengineering/view": "^0.6.9",
|
||||
"@hcengineering/view-resources": "^0.6.0",
|
||||
"svelte": "^4.2.12",
|
||||
"fast-equals": "^5.0.1",
|
||||
"filesize": "^8.0.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { deepEqual } from 'fast-equals'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { AccountArrayEditor } from '@hcengineering/contact-resources'
|
||||
import core, {
|
||||
Account,
|
||||
Data,
|
||||
DocumentUpdate,
|
||||
RolesAssignment,
|
||||
Ref,
|
||||
Role,
|
||||
SpaceType,
|
||||
generateId,
|
||||
getCurrentAccount,
|
||||
WithLookup
|
||||
} from '@hcengineering/core'
|
||||
import { Drive } from '@hcengineering/drive'
|
||||
import presentation, { Card, getClient, reduceCalls } from '@hcengineering/presentation'
|
||||
import { EditBox, Label, Toggle } from '@hcengineering/ui'
|
||||
import { SpaceTypeSelector } from '@hcengineering/view-resources'
|
||||
|
||||
import driveRes from '../plugin'
|
||||
|
||||
export let drive: Drive | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
let name: string = drive?.name ?? ''
|
||||
let description: string = drive?.description ?? ''
|
||||
let isPrivate: boolean = drive?.private ?? false
|
||||
|
||||
let members: Ref<Account>[] =
|
||||
drive?.members !== undefined ? hierarchy.clone(drive.members) : [getCurrentAccount()._id]
|
||||
let owners: Ref<Account>[] = drive?.owners !== undefined ? hierarchy.clone(drive.owners) : [getCurrentAccount()._id]
|
||||
let rolesAssignment: RolesAssignment = {}
|
||||
|
||||
let typeId: Ref<SpaceType> | undefined = drive?.type ?? driveRes.spaceType.DefaultDrive
|
||||
let spaceType: WithLookup<SpaceType> | undefined
|
||||
|
||||
$: void loadSpaceType(typeId)
|
||||
const loadSpaceType = reduceCalls(async (id: typeof typeId): Promise<void> => {
|
||||
spaceType =
|
||||
id !== undefined
|
||||
? await client
|
||||
.getModel()
|
||||
.findOne(core.class.SpaceType, { _id: id }, { lookup: { _id: { roles: core.class.Role } } })
|
||||
: undefined
|
||||
|
||||
if (drive === undefined || spaceType?.targetClass === undefined || spaceType?.$lookup?.roles === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
rolesAssignment = getRolesAssignment()
|
||||
})
|
||||
|
||||
function getRolesAssignment (): RolesAssignment {
|
||||
if (drive === undefined || spaceType?.targetClass === undefined || spaceType?.$lookup?.roles === undefined) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const asMixin = hierarchy.as(drive, spaceType?.targetClass)
|
||||
|
||||
return spaceType.$lookup.roles.reduce<RolesAssignment>((prev, { _id }) => {
|
||||
prev[_id as Ref<Role>] = (asMixin as any)[_id] ?? []
|
||||
|
||||
return prev
|
||||
}, {})
|
||||
}
|
||||
|
||||
async function handleSave (): Promise<void> {
|
||||
if (drive === undefined) {
|
||||
await createDrive()
|
||||
} else {
|
||||
await updateDrive()
|
||||
}
|
||||
}
|
||||
|
||||
function getDriveData (): Omit<Data<Drive>, 'type'> {
|
||||
return {
|
||||
name,
|
||||
description,
|
||||
private: isPrivate,
|
||||
members,
|
||||
owners,
|
||||
archived: false
|
||||
}
|
||||
}
|
||||
|
||||
async function updateDrive (): Promise<void> {
|
||||
if (drive === undefined || spaceType?.targetClass === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const data = getDriveData()
|
||||
const update: DocumentUpdate<Drive> = {}
|
||||
if (data.name !== drive?.name) {
|
||||
update.name = data.name
|
||||
}
|
||||
if (data.description !== drive?.description) {
|
||||
update.description = data.description
|
||||
}
|
||||
if (data.private !== drive?.private) {
|
||||
update.private = data.private
|
||||
}
|
||||
if (data.members.length !== drive?.members.length) {
|
||||
update.members = data.members
|
||||
} else {
|
||||
for (const member of data.members) {
|
||||
if (drive.members.findIndex((p) => p === member) === -1) {
|
||||
update.members = data.members
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (data.owners?.length !== drive?.owners?.length) {
|
||||
update.owners = data.owners
|
||||
} else {
|
||||
for (const owner of data.owners ?? []) {
|
||||
if (drive.owners?.findIndex((p) => p === owner) === -1) {
|
||||
update.owners = data.owners
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(update).length > 0) {
|
||||
await client.update(drive, update)
|
||||
}
|
||||
|
||||
if (!deepEqual(rolesAssignment, getRolesAssignment())) {
|
||||
await client.updateMixin(
|
||||
drive._id,
|
||||
driveRes.class.Drive,
|
||||
core.space.Space,
|
||||
spaceType.targetClass,
|
||||
rolesAssignment
|
||||
)
|
||||
}
|
||||
|
||||
close()
|
||||
}
|
||||
|
||||
async function createDrive (): Promise<void> {
|
||||
if (typeId === undefined || spaceType?.targetClass === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const driveId = generateId<Drive>()
|
||||
const driveData = getDriveData()
|
||||
|
||||
await client.createDoc(driveRes.class.Drive, core.space.Space, { ...driveData, type: typeId }, driveId)
|
||||
|
||||
// Create space type's mixin with roles assignments
|
||||
await client.createMixin(driveId, driveRes.class.Drive, core.space.Space, spaceType.targetClass, rolesAssignment)
|
||||
|
||||
close(driveId)
|
||||
}
|
||||
|
||||
function close (id?: Ref<Drive>): void {
|
||||
dispatch('close', id)
|
||||
}
|
||||
|
||||
function handleTypeChange (evt: CustomEvent<Ref<SpaceType>>): void {
|
||||
typeId = evt.detail
|
||||
}
|
||||
|
||||
$: roles = (spaceType?.$lookup?.roles ?? []) as Role[]
|
||||
|
||||
function handleOwnersChanged (newOwners: Ref<Account>[]): void {
|
||||
owners = newOwners
|
||||
|
||||
const newMembersSet = new Set([...members, ...newOwners])
|
||||
members = Array.from(newMembersSet)
|
||||
}
|
||||
|
||||
function handleMembersChanged (newMembers: Ref<Account>[]): void {
|
||||
// If a member was removed we need to remove it from any roles assignments as well
|
||||
const newMembersSet = new Set(newMembers)
|
||||
const removedMembersSet = new Set(members.filter((m) => !newMembersSet.has(m)))
|
||||
|
||||
if (removedMembersSet.size > 0 && rolesAssignment !== undefined) {
|
||||
for (const [key, value] of Object.entries(rolesAssignment)) {
|
||||
rolesAssignment[key as Ref<Role>] = value != null ? value.filter((m) => !removedMembersSet.has(m)) : undefined
|
||||
}
|
||||
}
|
||||
|
||||
members = newMembers
|
||||
}
|
||||
|
||||
function handleRoleAssignmentChanged (roleId: Ref<Role>, newMembers: Ref<Account>[]): void {
|
||||
if (rolesAssignment === undefined) {
|
||||
rolesAssignment = {}
|
||||
}
|
||||
|
||||
rolesAssignment[roleId] = newMembers
|
||||
}
|
||||
|
||||
$: canSave =
|
||||
name.trim().length > 0 &&
|
||||
!(members.length === 0 && isPrivate) &&
|
||||
typeId !== undefined &&
|
||||
spaceType?.targetClass !== undefined &&
|
||||
owners.length > 0 &&
|
||||
(!isPrivate || owners.some((o) => members.includes(o)))
|
||||
</script>
|
||||
|
||||
<Card
|
||||
label={drive ? driveRes.string.EditDrive : driveRes.string.CreateDrive}
|
||||
okLabel={drive ? presentation.string.Create : presentation.string.Save}
|
||||
okAction={handleSave}
|
||||
{canSave}
|
||||
accentHeader
|
||||
width={'medium'}
|
||||
gap={'gapV-6'}
|
||||
onCancel={close}
|
||||
on:changeContent
|
||||
>
|
||||
<div class="antiGrid">
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header">
|
||||
<Label label={core.string.SpaceType} />
|
||||
</div>
|
||||
|
||||
<SpaceTypeSelector
|
||||
disabled={drive !== undefined}
|
||||
descriptors={[driveRes.descriptor.DriveType]}
|
||||
type={typeId}
|
||||
focusIndex={4}
|
||||
kind="regular"
|
||||
size="large"
|
||||
on:change={handleTypeChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header">
|
||||
<Label label={core.string.Name} />
|
||||
</div>
|
||||
<div class="padding">
|
||||
<EditBox id="teamspace-title" bind:value={name} placeholder={core.string.Name} kind={'large-style'} autoFocus />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header topAlign">
|
||||
<Label label={core.string.Description} />
|
||||
</div>
|
||||
<div class="padding">
|
||||
<EditBox id="teamspace-description" bind:value={description} placeholder={core.string.Description} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="antiGrid">
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header">
|
||||
<Label label={core.string.Owners} />
|
||||
</div>
|
||||
<AccountArrayEditor
|
||||
value={owners}
|
||||
label={core.string.Owners}
|
||||
onChange={handleOwnersChanged}
|
||||
kind={'regular'}
|
||||
size={'large'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header withDesciption">
|
||||
<Label label={presentation.string.MakePrivate} />
|
||||
<span><Label label={presentation.string.MakePrivateDescription} /></span>
|
||||
</div>
|
||||
<Toggle bind:on={isPrivate} disabled={!isPrivate && members.length === 0} />
|
||||
</div>
|
||||
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header">
|
||||
<Label label={core.string.Members} />
|
||||
</div>
|
||||
<AccountArrayEditor
|
||||
value={members}
|
||||
label={core.string.Members}
|
||||
onChange={handleMembersChanged}
|
||||
kind={'regular'}
|
||||
size={'large'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{#each roles as role}
|
||||
<div class="antiGrid-row">
|
||||
<div class="antiGrid-row__header">
|
||||
<Label label={driveRes.string.RoleLabel} params={{ role: role.name }} />
|
||||
</div>
|
||||
<AccountArrayEditor
|
||||
value={rolesAssignment?.[role._id] ?? []}
|
||||
label={core.string.Members}
|
||||
includeItems={members}
|
||||
readonly={members.length === 0}
|
||||
onChange={(refs) => {
|
||||
handleRoleAssignmentChanged(role._id, refs)
|
||||
}}
|
||||
kind={'regular'}
|
||||
size={'large'}
|
||||
/>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</Card>
|
||||
@@ -0,0 +1,121 @@
|
||||
<!--
|
||||
//
|
||||
// Copyright © 2024 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 core, { Ref, generateId } from '@hcengineering/core'
|
||||
import { Drive, Folder } from '@hcengineering/drive'
|
||||
import { Card, SpaceSelector, getClient } from '@hcengineering/presentation'
|
||||
import { EditBox, FocusHandler, createFocusManager } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { ObjectBox } from '@hcengineering/view-resources'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import drive from '../plugin'
|
||||
|
||||
export function canClose (): boolean {
|
||||
return name === ''
|
||||
}
|
||||
|
||||
export let space: Ref<Drive>
|
||||
export let parent: Ref<Folder>
|
||||
|
||||
const id: Ref<Folder> = generateId()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
const client = getClient()
|
||||
|
||||
let _space = space
|
||||
let _parent = parent !== drive.ids.Root ? parent : undefined
|
||||
let name = ''
|
||||
|
||||
$: if (_space !== space) _parent = undefined
|
||||
$: canSave = getTitle(name).length > 0 && _space !== undefined
|
||||
|
||||
function getTitle (value: string): string {
|
||||
return value.trim()
|
||||
}
|
||||
|
||||
async function create (): Promise<void> {
|
||||
let path: Ref<Folder>[] = []
|
||||
|
||||
if (_parent != null && _parent !== drive.ids.Root) {
|
||||
const parent = await client.findOne(drive.class.Folder, { _id: _parent })
|
||||
if (parent === undefined) {
|
||||
throw new Error('parent not found')
|
||||
}
|
||||
path = [parent._id, ...parent.path]
|
||||
}
|
||||
|
||||
await client.createDoc(
|
||||
drive.class.Folder,
|
||||
space,
|
||||
{
|
||||
name: getTitle(name),
|
||||
parent: _parent ?? drive.ids.Root,
|
||||
path
|
||||
},
|
||||
id
|
||||
)
|
||||
|
||||
dispatch('close', id)
|
||||
}
|
||||
|
||||
const manager = createFocusManager()
|
||||
</script>
|
||||
|
||||
<FocusHandler {manager} />
|
||||
|
||||
<Card
|
||||
label={drive.string.CreateFolder}
|
||||
okAction={create}
|
||||
{canSave}
|
||||
on:close={() => {
|
||||
dispatch('close')
|
||||
}}
|
||||
on:changeContent
|
||||
>
|
||||
<svelte:fragment slot="header">
|
||||
<SpaceSelector
|
||||
_class={drive.class.Drive}
|
||||
label={drive.string.Drive}
|
||||
bind:space={_space}
|
||||
kind={'regular'}
|
||||
size={'small'}
|
||||
iconWithEmoji={view.ids.IconWithEmoji}
|
||||
defaultIcon={drive.icon.Drive}
|
||||
/>
|
||||
<ObjectBox
|
||||
_class={drive.class.Folder}
|
||||
bind:value={_parent}
|
||||
docQuery={{
|
||||
space: _space
|
||||
}}
|
||||
kind={'regular'}
|
||||
size={'small'}
|
||||
label={drive.string.Root}
|
||||
searchField={'name'}
|
||||
allowDeselect
|
||||
showNavigate={false}
|
||||
docProps={{ disabled: true, noUnderline: true }}
|
||||
on:object={(evt) => {
|
||||
console.log('selected', evt)
|
||||
}}
|
||||
/>
|
||||
</svelte:fragment>
|
||||
|
||||
<div class="flex-row-center clear-mins">
|
||||
<EditBox placeholder={core.string.Name} bind:value={name} kind={'large-style'} autoFocus focusIndex={1} />
|
||||
</div>
|
||||
</Card>
|
||||
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 Drive } from '@hcengineering/drive'
|
||||
import { Button, IconDetails, IconMoreH } from '@hcengineering/ui'
|
||||
import { showMenu } from '@hcengineering/view-resources'
|
||||
|
||||
import DrivePresenter from './DrivePresenter.svelte'
|
||||
|
||||
export let object: Drive
|
||||
export let asideShown: boolean = false
|
||||
</script>
|
||||
|
||||
<div class="popupPanel-title">
|
||||
<div class="popupPanel-title__content">
|
||||
<div class="title">
|
||||
<DrivePresenter value={object} shouldShowAvatar={false} disabled noUnderline />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row-center ml-3 no-print">
|
||||
<Button
|
||||
icon={IconMoreH}
|
||||
iconProps={{ size: 'medium' }}
|
||||
kind={'icon'}
|
||||
on:click={(ev) => {
|
||||
showMenu(ev, { object })
|
||||
}}
|
||||
/>
|
||||
<div class="buttons-divider max-h-7 h-7 mx-2 no-print" />
|
||||
<Button
|
||||
focusIndex={10008}
|
||||
icon={IconDetails}
|
||||
iconProps={{ size: 'medium', filled: asideShown }}
|
||||
kind={'icon'}
|
||||
selected={asideShown}
|
||||
on:click={() => {
|
||||
asideShown = !asideShown
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,63 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 Ref } from '@hcengineering/core'
|
||||
import drive, { type Drive } from '@hcengineering/drive'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Separator } from '@hcengineering/ui'
|
||||
import { DocAttributeBar } from '@hcengineering/view-resources'
|
||||
|
||||
import DriveHeader from './DriveHeader.svelte'
|
||||
import FolderBrowser from './FolderBrowser.svelte'
|
||||
|
||||
export let _id: Ref<Drive>
|
||||
export let readonly: boolean = false
|
||||
export let embedded: boolean = false
|
||||
export let kind: 'default' | 'modern' = 'default'
|
||||
|
||||
export function canClose (): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
let object: Drive | undefined = undefined
|
||||
let asideShown = false
|
||||
|
||||
const query = createQuery()
|
||||
$: query.query(drive.class.Drive, { _id }, (res) => {
|
||||
;[object] = res
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if object}
|
||||
<div class="popupPanel panel {kind}" class:embedded>
|
||||
<DriveHeader {object} bind:asideShown />
|
||||
|
||||
<div class="popupPanel-body">
|
||||
<div class="popupPanel-body__main">
|
||||
<FolderBrowser space={object._id} parent={drive.ids.Root} />
|
||||
</div>
|
||||
|
||||
{#if asideShown}
|
||||
<Separator name="aside" float={false} index={0} />
|
||||
<div class="popupPanel-body__aside no-print" class:shown={asideShown}>
|
||||
<Separator name={'panel-aside'} float={true} index={0} />
|
||||
<div class="antiPanel-wrap__content">
|
||||
<DocAttributeBar {object} {readonly} ignoreKeys={[]} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
//
|
||||
// Copyright © 2024 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 { Drive } from '@hcengineering/drive'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { Icon, tooltip } from '@hcengineering/ui'
|
||||
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
|
||||
import { ObjectPresenterType } from '@hcengineering/view'
|
||||
|
||||
import drive from '../plugin'
|
||||
|
||||
export let value: Drive
|
||||
export let inline: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let noUnderline: boolean = false
|
||||
export let shouldShowAvatar = true
|
||||
export let type: ObjectPresenterType = 'link'
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{#if inline}
|
||||
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
||||
{:else if type === 'link'}
|
||||
<DocNavLink {disabled} object={value} {accent} {noUnderline}>
|
||||
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{#if shouldShowAvatar}
|
||||
<div class="icon">
|
||||
<Icon icon={drive.icon.Drive} size={'small'} />
|
||||
</div>
|
||||
{/if}
|
||||
<span class="label no-underline nowrap" class:fs-bold={accent}>
|
||||
{value.name}
|
||||
</span>
|
||||
</div>
|
||||
</DocNavLink>
|
||||
{:else if type === 'text'}
|
||||
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{value.name}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -0,0 +1,147 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { AccountRole, Ref, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
|
||||
import { type Drive } from '@hcengineering/drive'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Button, ButtonWithDropdown, IconAdd, IconDropdown, Loading, SelectPopupValueType } from '@hcengineering/ui'
|
||||
|
||||
import drive from '../plugin'
|
||||
import { getFolderIdFromFragment } from '../navigation'
|
||||
import { createDrive, createFolder, createFiles } from '../utils'
|
||||
|
||||
export let currentSpace: Ref<Drive> | undefined
|
||||
export let currentFragment: string | undefined
|
||||
|
||||
const query = createQuery()
|
||||
|
||||
let loading = true
|
||||
let hasDrive = false
|
||||
query.query(
|
||||
drive.class.Drive,
|
||||
{ archived: false },
|
||||
(res) => {
|
||||
hasDrive = res.length > 0
|
||||
loading = false
|
||||
},
|
||||
{ limit: 1, projection: { _id: 1 } }
|
||||
)
|
||||
|
||||
$: parent = getFolderIdFromFragment(currentFragment ?? '') ?? drive.ids.Root
|
||||
|
||||
async function handleDropdownItemSelected (res?: SelectPopupValueType['id']): Promise<void> {
|
||||
if (res === drive.string.CreateDrive) {
|
||||
await handleCreateDrive()
|
||||
} else if (res === drive.string.CreateFolder) {
|
||||
await handleCreateFolder()
|
||||
} else if (res === drive.string.UploadFile) {
|
||||
await handleUploadFile()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCreateDrive (): Promise<void> {
|
||||
await createDrive()
|
||||
}
|
||||
|
||||
async function handleCreateFolder (): Promise<void> {
|
||||
if (currentSpace !== undefined) {
|
||||
await createFolder(currentSpace, parent, true)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleUploadFile (): Promise<void> {
|
||||
if (currentSpace !== undefined) {
|
||||
inputFile.click()
|
||||
}
|
||||
}
|
||||
|
||||
const dropdownItems = hasAccountRole(getCurrentAccount(), AccountRole.User)
|
||||
? [
|
||||
{ id: drive.string.CreateDrive, label: drive.string.CreateDrive, icon: drive.icon.Drive },
|
||||
{ id: drive.string.CreateFolder, label: drive.string.CreateFolder, icon: drive.icon.Folder },
|
||||
{ id: drive.string.UploadFile, label: drive.string.UploadFile, icon: drive.icon.File }
|
||||
// { id: drive.string.UploadFolder, label: drive.string.UploadFolder }
|
||||
]
|
||||
: [
|
||||
{ id: drive.string.CreateFolder, label: drive.string.CreateFolder, icon: drive.icon.Folder },
|
||||
{ id: drive.string.UploadFile, label: drive.string.UploadFile, icon: drive.icon.File }
|
||||
// { id: drive.string.UploadFolder, label: drive.string.UploadFolder }
|
||||
]
|
||||
|
||||
let progress = false
|
||||
let inputFile: HTMLInputElement
|
||||
|
||||
async function fileSelected (): Promise<void> {
|
||||
if (currentSpace === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
const list = inputFile.files
|
||||
if (list === null || list.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
progress = true
|
||||
|
||||
await createFiles(list, currentSpace, parent)
|
||||
|
||||
inputFile.value = ''
|
||||
progress = false
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if loading}
|
||||
<Loading shrink />
|
||||
{:else}
|
||||
<input
|
||||
bind:this={inputFile}
|
||||
multiple
|
||||
type="file"
|
||||
name="file"
|
||||
id="file"
|
||||
style="display: none"
|
||||
on:change={fileSelected}
|
||||
/>
|
||||
|
||||
<div class="antiNav-subheader">
|
||||
{#if hasDrive}
|
||||
<ButtonWithDropdown
|
||||
icon={IconAdd}
|
||||
justify={'left'}
|
||||
kind={'primary'}
|
||||
label={drive.string.UploadFile}
|
||||
mainButtonId={'new-document'}
|
||||
dropdownIcon={IconDropdown}
|
||||
{dropdownItems}
|
||||
disabled={currentSpace === undefined || progress}
|
||||
on:click={handleUploadFile}
|
||||
on:dropdown-selected={(ev) => {
|
||||
void handleDropdownItemSelected(ev.detail)
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
<Button
|
||||
icon={IconAdd}
|
||||
label={drive.string.CreateDrive}
|
||||
justify={'left'}
|
||||
width={'100%'}
|
||||
kind={'primary'}
|
||||
gap={'large'}
|
||||
disabled={progress}
|
||||
on:click={handleCreateDrive}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,119 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { Doc, Ref, SortingOrder, Space } from '@hcengineering/core'
|
||||
import { Drive, Folder } from '@hcengineering/drive'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Action, navigate } from '@hcengineering/ui'
|
||||
|
||||
import drive from '../plugin'
|
||||
import { getDriveLink, getFolderIdFromFragment, getFolderLink } from '../navigation'
|
||||
import FolderTreeLevel from './FolderTreeLevel.svelte'
|
||||
import FolderTreeElement from './FolderTreeElement.svelte'
|
||||
|
||||
export let space: Drive
|
||||
export let currentSpace: Ref<Space> | undefined
|
||||
export let currentSpecial: string | undefined
|
||||
export let currentFragment: string | undefined
|
||||
export let getActions: (space: Space) => Promise<Action[]> = async () => []
|
||||
|
||||
let folders: Ref<Folder>[] = []
|
||||
let folderById: Map<Ref<Folder>, Folder> = new Map<Ref<Folder>, Folder>()
|
||||
let descendants: Map<Ref<Folder>, Folder[]> = new Map<Ref<Folder>, Folder[]>()
|
||||
|
||||
function getDescendants (obj: Ref<Folder>): Ref<Folder>[] {
|
||||
return (descendants.get(obj) ?? []).sort((a, b) => a.name.localeCompare(b.name)).map((p) => p._id)
|
||||
}
|
||||
|
||||
let selected: Ref<Doc> | undefined
|
||||
$: selected = getFolderIdFromFragment(currentFragment ?? '')
|
||||
|
||||
const query = createQuery()
|
||||
query.query(
|
||||
drive.class.Folder,
|
||||
{
|
||||
space: space._id
|
||||
},
|
||||
(result) => {
|
||||
folderById.clear()
|
||||
descendants.clear()
|
||||
|
||||
for (const doc of result) {
|
||||
const current = descendants.get(doc.parent) ?? []
|
||||
current.push(doc)
|
||||
descendants.set(doc.parent, current)
|
||||
folderById.set(doc._id, doc)
|
||||
}
|
||||
|
||||
folderById = folderById
|
||||
descendants = descendants
|
||||
folders = getDescendants(drive.ids.Root)
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
name: SortingOrder.Ascending
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function handleDriveSelected (_id: Ref<Drive>): void {
|
||||
navigate(getDriveLink(_id))
|
||||
}
|
||||
|
||||
function handleFolderSelected (_id: Ref<Folder>): void {
|
||||
navigate(getFolderLink(_id))
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if space}
|
||||
<FolderTreeElement
|
||||
_id={space._id}
|
||||
icon={drive.icon.Drive}
|
||||
title={space.name}
|
||||
selected={currentSpace === space._id && selected === space._id}
|
||||
parent={descendants.size > 0}
|
||||
actions={() => getActions(space)}
|
||||
on:click={() => {
|
||||
handleDriveSelected(space._id)
|
||||
}}
|
||||
>
|
||||
<!-- <TreeNode
|
||||
{collapsed}
|
||||
_id={space._id}
|
||||
icon={drive.icon.Drive}
|
||||
title={space.name}
|
||||
folder
|
||||
parent={descendants.size > 0}
|
||||
actions={() => getActions(space)}
|
||||
on:click={() => {
|
||||
if (selected === space?._id) {
|
||||
collapsed = !collapsed
|
||||
} else {
|
||||
handleDriveSelected(space._id)
|
||||
}
|
||||
}}
|
||||
> -->
|
||||
<FolderTreeLevel
|
||||
{folders}
|
||||
{descendants}
|
||||
{folderById}
|
||||
{selected}
|
||||
on:selected={(ev) => {
|
||||
handleFolderSelected(ev.detail)
|
||||
}}
|
||||
/>
|
||||
<!-- </TreeNode> -->
|
||||
</FolderTreeElement>
|
||||
{/if}
|
||||
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 Folder } from '@hcengineering/drive'
|
||||
|
||||
import FolderBrowser from './FolderBrowser.svelte'
|
||||
|
||||
export let object: Folder
|
||||
export let readonly: boolean = false
|
||||
</script>
|
||||
|
||||
{#if object}
|
||||
<FolderBrowser space={object.space} parent={object._id} {readonly} />
|
||||
{/if}
|
||||
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
//
|
||||
// Copyright © 2024 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 { File } from '@hcengineering/drive'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { Icon, tooltip } from '@hcengineering/ui'
|
||||
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
|
||||
import { ObjectPresenterType } from '@hcengineering/view'
|
||||
|
||||
import drive from '../plugin'
|
||||
|
||||
export let value: File
|
||||
export let inline: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let noUnderline: boolean = false
|
||||
export let shouldShowAvatar = true
|
||||
export let type: ObjectPresenterType = 'link'
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{#if inline}
|
||||
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
||||
{:else if type === 'link'}
|
||||
<DocNavLink {disabled} object={value} {accent} {noUnderline}>
|
||||
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{#if shouldShowAvatar}
|
||||
<div class="icon">
|
||||
<Icon icon={drive.icon.File} size={'small'} />
|
||||
</div>
|
||||
{/if}
|
||||
<span class="label nowrap" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
||||
{value.name}
|
||||
</span>
|
||||
</div>
|
||||
</DocNavLink>
|
||||
{:else if type === 'text'}
|
||||
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{value.name}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 filesize from 'filesize'
|
||||
|
||||
export let value: number | undefined
|
||||
export let accent: boolean = false
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<span class="overflow-label select-text" class:fs-bold={accent}>
|
||||
{value !== undefined ? filesize(value) : '-'}
|
||||
</span>
|
||||
{/if}
|
||||
@@ -0,0 +1,105 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 Doc, type DocumentQuery, type Ref, type WithLookup } from '@hcengineering/core'
|
||||
import drive, { type Drive, type Folder } from '@hcengineering/drive'
|
||||
import { Viewlet, ViewOptions } from '@hcengineering/view'
|
||||
import { Scroller, SearchEdit } from '@hcengineering/ui'
|
||||
import {
|
||||
FilterBar,
|
||||
FilterButton,
|
||||
ViewletContentView,
|
||||
ViewletSelector,
|
||||
ViewletSettingButton
|
||||
} from '@hcengineering/view-resources'
|
||||
|
||||
import { createFiles } from '../utils'
|
||||
|
||||
export let space: Ref<Drive>
|
||||
export let parent: Ref<Folder>
|
||||
export let readonly: boolean = false
|
||||
|
||||
const _class = drive.class.Resource
|
||||
|
||||
$: query = { space, parent }
|
||||
|
||||
let dragover = false
|
||||
|
||||
let viewlet: WithLookup<Viewlet> | undefined = undefined
|
||||
let viewOptions: ViewOptions | undefined
|
||||
|
||||
let search = ''
|
||||
let searchQuery: DocumentQuery<Doc> = { ...query }
|
||||
let resultQuery: DocumentQuery<Doc> = { ...searchQuery }
|
||||
|
||||
$: if (query !== undefined) updateSearchQuery(search)
|
||||
$: resultQuery = { ...searchQuery }
|
||||
|
||||
function updateSearchQuery (search: string): void {
|
||||
searchQuery = search === '' ? { ...query } : { ...query, $search: search }
|
||||
}
|
||||
|
||||
async function handleDrop (e: DragEvent): Promise<void> {
|
||||
if (readonly) {
|
||||
return
|
||||
}
|
||||
// progress = true
|
||||
const list = e.dataTransfer?.files
|
||||
if (list !== undefined && list.length !== 0) {
|
||||
await createFiles(list, space, parent)
|
||||
}
|
||||
// progress = false
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if space !== undefined}
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="antiComponent"
|
||||
class:solid={dragover}
|
||||
on:dragover|preventDefault={() => {
|
||||
dragover = true
|
||||
}}
|
||||
on:dragleave={() => {
|
||||
dragover = false
|
||||
}}
|
||||
on:drop|preventDefault|stopPropagation={(ev) => {
|
||||
void handleDrop(ev)
|
||||
}}
|
||||
>
|
||||
<div class="ac-header full divide caption-height">
|
||||
<div class="ac-header-full small-gap">
|
||||
<SearchEdit bind:value={search} on:change={() => {}} />
|
||||
<div class="buttons-divider" />
|
||||
<FilterButton {_class} {space} />
|
||||
</div>
|
||||
<div class="ac-header-full medium-gap">
|
||||
<ViewletSettingButton bind:viewOptions bind:viewlet />
|
||||
<ViewletSelector bind:viewlet viewletQuery={{ attachTo: _class }} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if viewlet !== undefined && viewOptions}
|
||||
<FilterBar {_class} {space} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} />
|
||||
<div class="popupPanel rowContent">
|
||||
{#if viewlet}
|
||||
<Scroller horizontal={true}>
|
||||
<ViewletContentView {_class} {viewlet} query={resultQuery} {space} {viewOptions} />
|
||||
</Scroller>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,81 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { toIdMap, type Doc, type Ref } from '@hcengineering/core'
|
||||
import drive, { type Folder } from '@hcengineering/drive'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Button, IconDetails, IconMoreH } from '@hcengineering/ui'
|
||||
import { DocsNavigator, showMenu } from '@hcengineering/view-resources'
|
||||
|
||||
import FolderPresenter from './FolderPresenter.svelte'
|
||||
|
||||
export let object: Folder
|
||||
export let asideShown: boolean = false
|
||||
|
||||
const client = getClient()
|
||||
|
||||
let parents: Doc[] = []
|
||||
$: void updateParents(object.path)
|
||||
|
||||
async function updateParents (path: Ref<Folder>[]): Promise<void> {
|
||||
const docs: Array<Doc> = []
|
||||
|
||||
const folders = await client.findAll(drive.class.Folder, { _id: { $in: path } })
|
||||
const byId = toIdMap(folders)
|
||||
for (const p of path) {
|
||||
const parent = byId.get(p)
|
||||
if (parent !== undefined) {
|
||||
docs.push(parent)
|
||||
}
|
||||
}
|
||||
|
||||
const root = await client.findOne(drive.class.Drive, { _id: object.space })
|
||||
if (root !== undefined) {
|
||||
docs.push(root)
|
||||
}
|
||||
|
||||
parents = docs.reverse()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="popupPanel-title">
|
||||
<div class="popupPanel-title__content">
|
||||
<DocsNavigator elements={parents} />
|
||||
<div class="title">
|
||||
<FolderPresenter value={object} shouldShowAvatar={false} disabled noUnderline />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-row-center ml-3 no-print">
|
||||
<Button
|
||||
icon={IconMoreH}
|
||||
iconProps={{ size: 'medium' }}
|
||||
kind={'icon'}
|
||||
on:click={(ev) => {
|
||||
showMenu(ev, { object })
|
||||
}}
|
||||
/>
|
||||
<div class="buttons-divider max-h-7 h-7 mx-2 no-print" />
|
||||
<Button
|
||||
focusIndex={10008}
|
||||
icon={IconDetails}
|
||||
iconProps={{ size: 'medium', filled: asideShown }}
|
||||
kind={'icon'}
|
||||
selected={asideShown}
|
||||
on:click={() => {
|
||||
asideShown = !asideShown
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,63 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 Ref } from '@hcengineering/core'
|
||||
import drive, { type Folder } from '@hcengineering/drive'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { Separator } from '@hcengineering/ui'
|
||||
import { DocAttributeBar } from '@hcengineering/view-resources'
|
||||
|
||||
import FolderHeader from './FolderHeader.svelte'
|
||||
import FolderBrowser from './FolderBrowser.svelte'
|
||||
|
||||
export let _id: Ref<Folder>
|
||||
export let readonly: boolean = false
|
||||
export let embedded: boolean = false
|
||||
export let kind: 'default' | 'modern' = 'default'
|
||||
|
||||
export function canClose (): boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
let object: Folder | undefined = undefined
|
||||
let asideShown = false
|
||||
|
||||
const query = createQuery()
|
||||
$: query.query(drive.class.Folder, { _id }, (res) => {
|
||||
;[object] = res
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if object}
|
||||
<div class="popupPanel panel {kind}" class:embedded>
|
||||
<FolderHeader {object} bind:asideShown />
|
||||
|
||||
<div class="popupPanel-body">
|
||||
<div class="popupPanel-body__main">
|
||||
<FolderBrowser space={object.space} parent={object._id} {readonly} />
|
||||
</div>
|
||||
|
||||
{#if asideShown}
|
||||
<Separator name="aside" float={false} index={0} />
|
||||
<div class="popupPanel-body__aside no-print" class:shown={asideShown}>
|
||||
<Separator name={'panel-aside'} float={true} index={0} />
|
||||
<div class="antiPanel-wrap__content">
|
||||
<DocAttributeBar {object} {readonly} ignoreKeys={[]} />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
//
|
||||
// Copyright © 2024 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 { Folder } from '@hcengineering/drive'
|
||||
import { getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { Icon, tooltip } from '@hcengineering/ui'
|
||||
import { DocNavLink, ObjectMention } from '@hcengineering/view-resources'
|
||||
import { ObjectPresenterType } from '@hcengineering/view'
|
||||
|
||||
import drive from '../plugin'
|
||||
|
||||
export let value: Folder
|
||||
export let inline: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let noUnderline: boolean = false
|
||||
export let shouldShowAvatar = true
|
||||
export let type: ObjectPresenterType = 'link'
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{#if inline}
|
||||
<ObjectMention object={value} {disabled} {accent} {noUnderline} />
|
||||
{:else if type === 'link'}
|
||||
<DocNavLink {disabled} object={value} {accent} {noUnderline}>
|
||||
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{#if shouldShowAvatar}
|
||||
<div class="icon">
|
||||
<Icon icon={drive.icon.Folder} size={'small'} />
|
||||
</div>
|
||||
{/if}
|
||||
<span class="label nowrap" class:no-underline={noUnderline || disabled} class:fs-bold={accent}>
|
||||
{value.name}
|
||||
</span>
|
||||
</div>
|
||||
</DocNavLink>
|
||||
{:else if type === 'text'}
|
||||
<span class="overflow-label" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
|
||||
{value.name}
|
||||
</span>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -0,0 +1,101 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { createEventDispatcher } from 'svelte'
|
||||
import type { Doc, Ref } from '@hcengineering/core'
|
||||
import { type Asset, type IntlString, getEmbeddedLabel } from '@hcengineering/platform'
|
||||
import { type Action, type AnySvelteComponent, tooltip } from '@hcengineering/ui'
|
||||
import {
|
||||
Icon,
|
||||
IconChevronDown,
|
||||
IconMoreH,
|
||||
Label,
|
||||
Menu,
|
||||
getTreeCollapsed,
|
||||
setTreeCollapsed,
|
||||
showPopup
|
||||
} from '@hcengineering/ui'
|
||||
|
||||
export let _id: Ref<Doc>
|
||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||
export let iconProps: Record<string, any> | undefined = undefined
|
||||
export let label: IntlString | undefined = undefined
|
||||
export let title: string | undefined = undefined
|
||||
export let parent: boolean = false
|
||||
export let collapsed: boolean = getTreeCollapsed(_id)
|
||||
export let selected: boolean = false
|
||||
export let level: number = 0
|
||||
export let actions: (originalEvent?: MouseEvent) => Promise<Action[]> = async () => []
|
||||
|
||||
let hovered = false
|
||||
async function onMenuClick (ev: MouseEvent): Promise<void> {
|
||||
showPopup(Menu, { actions: await actions(ev), ctx: _id }, ev.target as HTMLElement, () => {
|
||||
hovered = false
|
||||
})
|
||||
hovered = true
|
||||
}
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
$: collapsed = getTreeCollapsed(_id)
|
||||
$: setTreeCollapsed(_id, collapsed)
|
||||
$: folder = level === 0
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
class="antiNav-element tree"
|
||||
class:selected
|
||||
class:hovered
|
||||
class:parent
|
||||
class:collapsed
|
||||
style:padding-left={`${level > 0 ? level * 1.25 + 0.125 : 0.75}rem`}
|
||||
on:click={() => {
|
||||
if (selected) {
|
||||
collapsed = !collapsed
|
||||
}
|
||||
dispatch('click')
|
||||
}}
|
||||
>
|
||||
{#if !folder}
|
||||
<div
|
||||
class="an-element__tool arrow"
|
||||
class:empty={!parent}
|
||||
on:click|preventDefault|stopPropagation={() => {
|
||||
if (parent) collapsed = !collapsed
|
||||
}}
|
||||
>
|
||||
{#if parent}<IconChevronDown size={'small'} filled />{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if icon}
|
||||
<div class="an-element__icon" class:folder>
|
||||
<Icon {icon} {iconProps} size={'small'} />
|
||||
</div>
|
||||
{/if}
|
||||
<span class="an-element__label" use:tooltip={{ label: label ?? getEmbeddedLabel(title ?? '') }}>
|
||||
{#if label}<Label {label} />{:else}{title}{/if}
|
||||
</span>
|
||||
<div class="an-element__grow" />
|
||||
|
||||
<div class="an-element__tool" class:pressed={hovered} on:click|preventDefault|stopPropagation={onMenuClick}>
|
||||
<IconMoreH size={'small'} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if parent && !collapsed}
|
||||
<div class="antiNav-element__dropbox"><slot /></div>
|
||||
{/if}
|
||||
@@ -0,0 +1,87 @@
|
||||
<!--
|
||||
// Copyright © 2024 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 { createEventDispatcher } from 'svelte'
|
||||
import { Doc, Ref } from '@hcengineering/core'
|
||||
import { Folder } from '@hcengineering/drive'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Action, IconEdit } from '@hcengineering/ui'
|
||||
import { getActions as getContributedActions } from '@hcengineering/view-resources'
|
||||
|
||||
import FolderTreeElement from './FolderTreeElement.svelte'
|
||||
|
||||
import drive from '../plugin'
|
||||
|
||||
export let folders: Ref<Folder>[]
|
||||
export let folderById: Map<Ref<Folder>, Folder>
|
||||
export let descendants: Map<Ref<Folder>, Folder[]>
|
||||
|
||||
export let selected: Ref<Doc> | undefined
|
||||
export let level = 1
|
||||
|
||||
const client = getClient()
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function getDescendants (obj: Ref<Folder>): Ref<Folder>[] {
|
||||
return (descendants.get(obj) ?? []).sort((a, b) => a.name.localeCompare(b.name)).map((p) => p._id)
|
||||
}
|
||||
|
||||
async function getActions (obj: Folder): Promise<Action[]> {
|
||||
const result: Action[] = []
|
||||
const extraActions = await getContributedActions(client, obj)
|
||||
for (const act of extraActions) {
|
||||
result.push({
|
||||
icon: act.icon ?? IconEdit,
|
||||
label: act.label,
|
||||
action: async (ctx: any, evt: Event) => {
|
||||
const impl = await getResource(act.action)
|
||||
await impl(obj, evt, act.actionProps)
|
||||
}
|
||||
})
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function handleSelected (obj: Ref<Folder>): void {
|
||||
dispatch('selected', obj)
|
||||
}
|
||||
|
||||
$: _folders = folders.map((it) => folderById.get(it)).filter((it) => it !== undefined) as Folder[]
|
||||
$: _descendants = new Map(_folders.map((it) => [it._id, getDescendants(it._id)]))
|
||||
</script>
|
||||
|
||||
{#each _folders as doc}
|
||||
{@const desc = _descendants.get(doc._id) ?? []}
|
||||
|
||||
{#if doc}
|
||||
<FolderTreeElement
|
||||
_id={doc._id}
|
||||
icon={drive.icon.Folder}
|
||||
title={doc.name}
|
||||
selected={selected === doc._id}
|
||||
parent={desc.length > 0}
|
||||
actions={async () => await getActions(doc)}
|
||||
{level}
|
||||
on:click={() => {
|
||||
handleSelected(doc._id)
|
||||
}}
|
||||
>
|
||||
{#if desc.length}
|
||||
<svelte:self folders={desc} {descendants} {folderById} {selected} level={level + 1} on:selected />
|
||||
{/if}
|
||||
</FolderTreeElement>
|
||||
{/if}
|
||||
{/each}
|
||||
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
// Copyright © 2024 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">
|
||||
</script>
|
||||
|
||||
<div>Here will be grid view</div>
|
||||
@@ -0,0 +1,53 @@
|
||||
<!--
|
||||
//
|
||||
// Copyright © 2024 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 File, type Folder, type Resource } from '@hcengineering/drive'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { ObjectPresenterType } from '@hcengineering/view'
|
||||
|
||||
import drive from '../plugin'
|
||||
|
||||
import FilePresenter from './FilePresenter.svelte'
|
||||
import FolderPresenter from './FolderPresenter.svelte'
|
||||
|
||||
export let value: Resource
|
||||
export let inline: boolean = false
|
||||
export let disabled: boolean = false
|
||||
export let accent: boolean = false
|
||||
export let noUnderline: boolean = false
|
||||
export let shouldShowAvatar = true
|
||||
export let type: ObjectPresenterType = 'link'
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
|
||||
function isFile (value: Resource): value is File {
|
||||
return hierarchy.isDerived(value._class, drive.class.File)
|
||||
}
|
||||
|
||||
function isFolder (value: Resource): value is Folder {
|
||||
return hierarchy.isDerived(value._class, drive.class.Folder)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{#if isFile(value)}
|
||||
<FilePresenter {value} {inline} {disabled} {accent} {noUnderline} {shouldShowAvatar} {type} />
|
||||
{:else if isFolder(value)}
|
||||
<FolderPresenter {value} {inline} {disabled} {accent} {noUnderline} {shouldShowAvatar} {type} />
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type Doc, type Ref } from '@hcengineering/core'
|
||||
import drive, { type Drive, type File, type Folder } from '@hcengineering/drive'
|
||||
import { type Resources } from '@hcengineering/platform'
|
||||
import { getFileUrl } from '@hcengineering/presentation'
|
||||
import { type Location, showPopup } from '@hcengineering/ui'
|
||||
|
||||
import CreateDrive from './components/CreateDrive.svelte'
|
||||
import DrivePanel from './components/DrivePanel.svelte'
|
||||
import DriveSpaceHeader from './components/DriveSpaceHeader.svelte'
|
||||
import DriveSpacePresenter from './components/DriveSpacePresenter.svelte'
|
||||
import DrivePresenter from './components/DrivePresenter.svelte'
|
||||
import EditFolder from './components/EditFolder.svelte'
|
||||
import FilePresenter from './components/FilePresenter.svelte'
|
||||
import FileSizePresenter from './components/FileSizePresenter.svelte'
|
||||
import FolderPanel from './components/FolderPanel.svelte'
|
||||
import FolderPresenter from './components/FolderPresenter.svelte'
|
||||
import GridView from './components/GridView.svelte'
|
||||
import ResourcePresenter from './components/ResourcePresenter.svelte'
|
||||
|
||||
import { getDriveLink, getFolderLink, resolveLocation } from './navigation'
|
||||
import { createFolder } from './utils'
|
||||
|
||||
async function CreateRootFolder (doc: Drive): Promise<void> {
|
||||
await createFolder(doc._id, drive.ids.Root)
|
||||
}
|
||||
|
||||
async function CreateChildFolder (doc: Folder): Promise<void> {
|
||||
await createFolder(doc.space, doc._id)
|
||||
}
|
||||
|
||||
async function EditDrive (drive: Drive): Promise<void> {
|
||||
showPopup(CreateDrive, { drive })
|
||||
}
|
||||
|
||||
async function DownloadFile (doc: File | File[]): Promise<void> {
|
||||
const files = Array.isArray(doc) ? doc : [doc]
|
||||
for (const file of files) {
|
||||
const url = getFileUrl(file.file, 'full', file.name)
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
async function DriveLinkProvider (doc: Doc): Promise<Location> {
|
||||
return getDriveLink(doc._id as Ref<Drive>)
|
||||
}
|
||||
|
||||
async function FolderLinkProvider (doc: Doc): Promise<Location> {
|
||||
return getFolderLink(doc._id as Ref<Folder>)
|
||||
}
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
CreateDrive,
|
||||
DrivePanel,
|
||||
DriveSpaceHeader,
|
||||
DriveSpacePresenter,
|
||||
DrivePresenter,
|
||||
EditFolder,
|
||||
FilePresenter,
|
||||
FileSizePresenter,
|
||||
FolderPanel,
|
||||
FolderPresenter,
|
||||
GridView,
|
||||
ResourcePresenter
|
||||
},
|
||||
actionImpl: {
|
||||
CreateChildFolder,
|
||||
CreateRootFolder,
|
||||
EditDrive,
|
||||
DownloadFile
|
||||
},
|
||||
function: {
|
||||
DriveLinkProvider,
|
||||
FolderLinkProvider
|
||||
},
|
||||
resolver: {
|
||||
Location: resolveLocation
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Doc, Ref } from '@hcengineering/core'
|
||||
import drive, { type Drive, type Folder, driveId } from '@hcengineering/drive'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { type Location, type ResolvedLocation, getCurrentResolvedLocation, getPanelURI } from '@hcengineering/ui'
|
||||
import view, { type ObjectPanel } from '@hcengineering/view'
|
||||
|
||||
export function getPanelFragment<T extends Doc> (object: Pick<T, '_class' | '_id'>): string {
|
||||
const hierarchy = getClient().getHierarchy()
|
||||
const objectPanelMixin = hierarchy.classHierarchyMixin<Doc, ObjectPanel>(object._class, view.mixin.ObjectPanel)
|
||||
const component = objectPanelMixin?.component ?? view.component.EditDoc
|
||||
return getPanelURI(component, object._id, object._class, 'content')
|
||||
}
|
||||
|
||||
export function getFolderIdFromFragment (fragment: string): Ref<Folder> | undefined {
|
||||
const [, _id] = decodeURIComponent(fragment).split('|')
|
||||
return _id as Ref<Folder>
|
||||
}
|
||||
|
||||
export function getDriveLink (_id: Ref<Drive>): Location {
|
||||
const loc = getCurrentResolvedLocation()
|
||||
loc.path.length = 2
|
||||
loc.fragment = undefined
|
||||
loc.query = undefined
|
||||
loc.path[2] = driveId
|
||||
loc.path[3] = _id
|
||||
|
||||
return loc
|
||||
}
|
||||
|
||||
export function getFolderLink (_id: Ref<Folder>): Location {
|
||||
const loc = getCurrentResolvedLocation()
|
||||
loc.path.length = 2
|
||||
loc.fragment = undefined
|
||||
loc.query = undefined
|
||||
loc.path[2] = driveId
|
||||
loc.path[3] = 'folder'
|
||||
loc.path[4] = _id
|
||||
|
||||
return loc
|
||||
}
|
||||
|
||||
export async function resolveLocation (loc: Location): Promise<ResolvedLocation | undefined> {
|
||||
if (loc.path[2] !== driveId) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
if (loc.path[3] === 'folder' && loc.path[4] !== undefined) {
|
||||
const folderId = loc.path[4] as Ref<Folder>
|
||||
return await generateFolderLocation(loc, folderId)
|
||||
}
|
||||
|
||||
if (loc.path[3] !== undefined) {
|
||||
const driveId = loc.path[3] as Ref<Drive>
|
||||
return await generateDriveLocation(loc, driveId)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export async function generateFolderLocation (loc: Location, id: Ref<Folder>): Promise<ResolvedLocation | undefined> {
|
||||
const client = getClient()
|
||||
|
||||
const doc = await client.findOne(drive.class.Folder, { _id: id })
|
||||
if (doc === undefined) {
|
||||
console.error(`Could not find folder ${id}.`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
const appComponent = loc.path[0] ?? ''
|
||||
const workspace = loc.path[1] ?? ''
|
||||
|
||||
return {
|
||||
loc: {
|
||||
path: [appComponent, workspace, driveId, doc.space],
|
||||
fragment: getPanelFragment(doc)
|
||||
},
|
||||
defaultLocation: {
|
||||
path: [appComponent, workspace, driveId],
|
||||
fragment: getPanelFragment(doc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateDriveLocation (loc: Location, id: Ref<Drive>): Promise<ResolvedLocation | undefined> {
|
||||
const client = getClient()
|
||||
|
||||
const doc = await client.findOne(drive.class.Drive, { _id: id })
|
||||
if (doc === undefined) {
|
||||
console.error(`Could not find drive ${id}.`)
|
||||
return undefined
|
||||
}
|
||||
|
||||
const appComponent = loc.path[0] ?? ''
|
||||
const workspace = loc.path[1] ?? ''
|
||||
|
||||
return {
|
||||
loc: {
|
||||
path: [appComponent, workspace, driveId, id],
|
||||
fragment: getPanelFragment(doc)
|
||||
},
|
||||
defaultLocation: {
|
||||
path: [appComponent, workspace, driveId],
|
||||
fragment: getPanelFragment(doc)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type IntlString, mergeIds } from '@hcengineering/platform'
|
||||
import drive, { driveId } from '@hcengineering/drive'
|
||||
|
||||
export default mergeIds(driveId, drive, {
|
||||
component: {},
|
||||
string: {
|
||||
CreateDrive: '' as IntlString,
|
||||
CreateFolder: '' as IntlString,
|
||||
UploadFile: '' as IntlString,
|
||||
UploadFolder: '' as IntlString,
|
||||
EditDrive: '' as IntlString,
|
||||
RoleLabel: '' as IntlString,
|
||||
Root: '' as IntlString
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright © 2024 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 attachment from '@hcengineering/attachment'
|
||||
import { type Blob, type Class, type Doc, type Ref } from '@hcengineering/core'
|
||||
import drive, { type Drive, type Folder } from '@hcengineering/drive'
|
||||
import { getResource, setPlatformStatus, unknownError } from '@hcengineering/platform'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { showPopup } from '@hcengineering/ui'
|
||||
import { openDoc } from '@hcengineering/view-resources'
|
||||
|
||||
import CreateDrive from './components/CreateDrive.svelte'
|
||||
import CreateFolder from './components/CreateFolder.svelte'
|
||||
|
||||
async function navigateToDoc (_id: Ref<Doc>, _class: Ref<Class<Doc>>): Promise<void> {
|
||||
const client = getClient()
|
||||
const doc = await client.findOne(_class, { _id })
|
||||
if (doc !== undefined) {
|
||||
void openDoc(client.getHierarchy(), doc)
|
||||
}
|
||||
}
|
||||
|
||||
export async function createFolder (space: Ref<Drive>, parent: Ref<Folder>, open = false): Promise<void> {
|
||||
showPopup(CreateFolder, { space, parent }, 'top', async (id) => {
|
||||
if (open && id !== undefined && id !== null) {
|
||||
await navigateToDoc(id, drive.class.Folder)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function createDrive (open = false): Promise<void> {
|
||||
showPopup(CreateDrive, {}, 'top', async (id) => {
|
||||
if (open && id !== undefined && id !== null) {
|
||||
await navigateToDoc(id, drive.class.Folder)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function editDrive (drive: Drive): Promise<void> {
|
||||
showPopup(CreateDrive, { drive })
|
||||
}
|
||||
|
||||
export async function createFiles (list: FileList, space: Ref<Drive>, parent: Ref<Folder>): Promise<void> {
|
||||
const client = getClient()
|
||||
const folder = await client.findOne(drive.class.Folder, { space, _id: parent })
|
||||
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
const file = list.item(index)
|
||||
if (file !== null) {
|
||||
await createFile(file, space, folder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function createFile (file: File, space: Ref<Drive>, parent: Folder | undefined): Promise<void> {
|
||||
const client = getClient()
|
||||
|
||||
try {
|
||||
const uploadFile = await getResource(attachment.helper.UploadFile)
|
||||
const uuid = await uploadFile(file)
|
||||
// TODO obtain metadata
|
||||
// const metadata = await getAttachmentMetadata(file, uuid)
|
||||
|
||||
await client.createDoc(drive.class.File, space, {
|
||||
name: file.name,
|
||||
file: uuid as Ref<Blob>,
|
||||
parent: parent?._id ?? drive.ids.Root,
|
||||
path: parent !== undefined ? [parent._id, ...parent.path] : []
|
||||
})
|
||||
} catch (e) {
|
||||
void setPlatformStatus(unknownError(e))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
const sveltePreprocess = require('svelte-preprocess')
|
||||
|
||||
module.exports = {
|
||||
preprocess: sveltePreprocess()
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/ui/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "@hcengineering/drive",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"format": "format src",
|
||||
"test": "jest --passWithNoTests --silent",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:test": "jest --passWithNoTests --silent",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.3.3",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/preference": "^0.6.9",
|
||||
"@hcengineering/ui": "^0.6.11"
|
||||
},
|
||||
"repository": "https://github.com/hcengineering/anticrm",
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// Copyright © 2024 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 { driveId, drivePlugin } from './plugin'
|
||||
|
||||
export * from './types'
|
||||
export { driveId }
|
||||
|
||||
export default drivePlugin
|
||||
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Class, Doc, Mixin, Ref, SpaceType, SpaceTypeDescriptor, Type } from '@hcengineering/core'
|
||||
import type { Asset, IntlString, Plugin, Resource as PlatformResource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import type { Location, ResolvedLocation } from '@hcengineering/ui'
|
||||
import { Drive, File, FileSize, Folder, Resource } from './types'
|
||||
|
||||
export * from './types'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const driveId = 'drive' as Plugin
|
||||
|
||||
export const drivePlugin = plugin(driveId, {
|
||||
class: {
|
||||
Drive: '' as Ref<Class<Drive>>,
|
||||
File: '' as Ref<Class<File>>,
|
||||
Folder: '' as Ref<Class<Folder>>,
|
||||
Resource: '' as Ref<Class<Resource>>,
|
||||
TypeFileSize: '' as Ref<Class<Type<FileSize>>>
|
||||
},
|
||||
mixin: {
|
||||
DefaultDriveTypeData: '' as Ref<Mixin<Drive>>
|
||||
},
|
||||
icon: {
|
||||
Drive: '' as Asset,
|
||||
File: '' as Asset,
|
||||
Folder: '' as Asset,
|
||||
FolderOpen: '' as Asset,
|
||||
FolderClosed: '' as Asset,
|
||||
Download: '' as Asset
|
||||
},
|
||||
app: {
|
||||
Drive: '' as Ref<Doc>
|
||||
},
|
||||
ids: {
|
||||
Root: '' as Ref<Folder>
|
||||
},
|
||||
resolver: {
|
||||
Location: '' as PlatformResource<(loc: Location) => Promise<ResolvedLocation | undefined>>
|
||||
},
|
||||
string: {
|
||||
Drive: '' as IntlString,
|
||||
File: '' as IntlString,
|
||||
Folder: '' as IntlString,
|
||||
Resource: '' as IntlString
|
||||
},
|
||||
descriptor: {
|
||||
DriveType: '' as Ref<SpaceTypeDescriptor>
|
||||
},
|
||||
spaceType: {
|
||||
DefaultDrive: '' as Ref<SpaceType>
|
||||
}
|
||||
})
|
||||
|
||||
export default drivePlugin
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright © 2024 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 { Blob, Doc, Ref, TypedSpace } from '@hcengineering/core'
|
||||
|
||||
/** @public */
|
||||
export type FileSize = number
|
||||
|
||||
/** @public */
|
||||
export interface Drive extends TypedSpace {}
|
||||
|
||||
/** @public */
|
||||
export interface Resource extends Doc<Drive> {
|
||||
name: string
|
||||
file?: Ref<Blob>
|
||||
|
||||
parent: Ref<Resource>
|
||||
path: Ref<Resource>[]
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface Folder extends Resource {
|
||||
parent: Ref<Folder>
|
||||
path: Ref<Folder>[]
|
||||
|
||||
file?: undefined
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface File extends Resource {
|
||||
file: Ref<Blob>
|
||||
|
||||
parent: Ref<Folder>
|
||||
path: Ref<Folder>[]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<!--
|
||||
// Copyright © 2023 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 { Doc } from '@hcengineering/core'
|
||||
import { Breadcrumbs, BreadcrumbsModel, getClient } from '@hcengineering/presentation'
|
||||
import { AttributeModel } from '@hcengineering/view'
|
||||
import { getObjectPresenter, restrictionStore } from '../utils'
|
||||
|
||||
export let elements: readonly Doc[]
|
||||
|
||||
const client = getClient()
|
||||
|
||||
async function getBreadcrumbsModels (elements: readonly Doc[]): Promise<readonly BreadcrumbsModel[]> {
|
||||
if (elements.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const models: BreadcrumbsModel[] = []
|
||||
for (const element of elements) {
|
||||
const attributeModel: AttributeModel | undefined = await getObjectPresenter(client, element._class, { key: '' })
|
||||
|
||||
if (attributeModel) {
|
||||
const breadcrumbsModel: BreadcrumbsModel = {
|
||||
component: attributeModel.presenter,
|
||||
props: {
|
||||
shouldShowAvatar: false,
|
||||
noUnderline: true,
|
||||
noSelect: true,
|
||||
...(attributeModel.props ?? {}),
|
||||
value: element
|
||||
}
|
||||
}
|
||||
|
||||
models.push(breadcrumbsModel)
|
||||
}
|
||||
}
|
||||
|
||||
return models
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await getBreadcrumbsModels(elements) then models}
|
||||
{#if models.length > 0}
|
||||
<Breadcrumbs {models} disabled={$restrictionStore.disableNavigation} />
|
||||
{/if}
|
||||
{/await}
|
||||
@@ -14,15 +14,19 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AttachedDoc, Doc } from '@hcengineering/core'
|
||||
import { Breadcrumbs, BreadcrumbsModel, getClient } from '@hcengineering/presentation'
|
||||
import { getObjectPresenter, isAttachedDoc, restrictionStore } from '../utils'
|
||||
import { AttributeModel } from '@hcengineering/view'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { isAttachedDoc } from '../utils'
|
||||
import DocsNavigator from './DocsNavigator.svelte'
|
||||
|
||||
export let element: Doc | AttachedDoc
|
||||
|
||||
const client = getClient()
|
||||
|
||||
async function getParents (doc: AttachedDoc): Promise<readonly Doc[]> {
|
||||
async function getParents (doc: Doc | AttachedDoc): Promise<readonly Doc[]> {
|
||||
if (!isAttachedDoc(doc)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const parents: Doc[] = []
|
||||
|
||||
let currentDoc: Doc | undefined = doc
|
||||
@@ -40,43 +44,8 @@
|
||||
|
||||
return parents.reverse()
|
||||
}
|
||||
|
||||
async function getBreadcrumbsModels (doc: typeof element): Promise<readonly BreadcrumbsModel[]> {
|
||||
if (!isAttachedDoc(doc)) {
|
||||
return []
|
||||
}
|
||||
|
||||
const parents = await getParents(doc)
|
||||
if (parents.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const models: BreadcrumbsModel[] = []
|
||||
for (const parent of parents) {
|
||||
const attributeModel: AttributeModel | undefined = await getObjectPresenter(client, parent._class, { key: '' })
|
||||
|
||||
if (attributeModel) {
|
||||
const breadcrumbsModel: BreadcrumbsModel = {
|
||||
component: attributeModel.presenter,
|
||||
props: {
|
||||
shouldShowAvatar: false,
|
||||
noUnderline: true,
|
||||
noSelect: true,
|
||||
...(attributeModel.props ?? {}),
|
||||
value: parent
|
||||
}
|
||||
}
|
||||
|
||||
models.push(breadcrumbsModel)
|
||||
}
|
||||
}
|
||||
|
||||
return models
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await getBreadcrumbsModels(element) then models}
|
||||
{#if models.length > 0}
|
||||
<Breadcrumbs {models} disabled={$restrictionStore.disableNavigation} />
|
||||
{/if}
|
||||
{#await getParents(element) then parents}
|
||||
<DocsNavigator elements={parents} />
|
||||
{/await}
|
||||
|
||||
@@ -133,6 +133,7 @@ export { getActions, getContextActions, invokeAction, showMenu } from './actions
|
||||
export { default as ActionButton } from './components/ActionButton.svelte'
|
||||
export { default as ActionHandler } from './components/ActionHandler.svelte'
|
||||
export { default as BaseDocPresenter } from './components/BaseDocPresenter.svelte'
|
||||
export { default as DocsNavigator } from './components/DocsNavigator.svelte'
|
||||
export { default as FixedColumn } from './components/FixedColumn.svelte'
|
||||
export { default as LinkPresenter } from './components/LinkPresenter.svelte'
|
||||
export { default as MarkupDiffPresenter } from './components/MarkupDiffPresenter.svelte'
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
"@hcengineering/workbench-assets": "^0.6.7",
|
||||
"@hcengineering/attachment-assets": "^0.6.7",
|
||||
"@hcengineering/lead-assets": "^0.6.0",
|
||||
"@hcengineering/drive-assets": "^0.6.0",
|
||||
"@hcengineering/gmail-assets": "^0.6.0",
|
||||
"@hcengineering/inventory-assets": "^0.6.7",
|
||||
"@hcengineering/templates-assets": "^0.6.7",
|
||||
@@ -144,6 +145,7 @@
|
||||
"@hcengineering/workbench": "^0.6.9",
|
||||
"@hcengineering/attachment": "^0.6.9",
|
||||
"@hcengineering/lead": "^0.6.0",
|
||||
"@hcengineering/drive": "^0.6.0",
|
||||
"@hcengineering/gmail": "^0.6.15",
|
||||
"@hcengineering/inventory": "^0.6.7",
|
||||
"@hcengineering/templates": "^0.6.7",
|
||||
|
||||
@@ -103,6 +103,7 @@ import { calendarId } from '@hcengineering/calendar'
|
||||
import { chunterId } from '@hcengineering/chunter'
|
||||
import { contactId } from '@hcengineering/contact'
|
||||
import { documentId } from '@hcengineering/document'
|
||||
import { driveId } from '@hcengineering/drive'
|
||||
import { gmailId } from '@hcengineering/gmail'
|
||||
import { hrId } from '@hcengineering/hr'
|
||||
import { inventoryId } from '@hcengineering/inventory'
|
||||
@@ -134,6 +135,7 @@ import calendarEn from '@hcengineering/calendar-assets/lang/en.json'
|
||||
import chunterEn from '@hcengineering/chunter-assets/lang/en.json'
|
||||
import contactEn from '@hcengineering/contact-assets/lang/en.json'
|
||||
import documentEn from '@hcengineering/document-assets/lang/en.json'
|
||||
import driveEn from '@hcengineering/drive-assets/lang/en.json'
|
||||
import gmailEn from '@hcengineering/gmail-assets/lang/en.json'
|
||||
import hrEn from '@hcengineering/hr-assets/lang/en.json'
|
||||
import inventoryEn from '@hcengineering/inventory-assets/lang/en.json'
|
||||
@@ -181,6 +183,7 @@ addStringsLoader(hrId, async (lang: string) => hrEn)
|
||||
addStringsLoader(bitrixId, async (lang: string) => bitrixEn)
|
||||
addStringsLoader(requestId, async (lang: string) => requestEn)
|
||||
addStringsLoader(documentId, async (lang: string) => documentEn)
|
||||
addStringsLoader(driveId, async (lang: string) => driveEn)
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
||||
@@ -1656,6 +1656,41 @@
|
||||
"packageName": "@hcengineering/model-server-document",
|
||||
"projectFolder": "models/server-document",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/drive",
|
||||
"projectFolder": "plugins/drive",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/drive-assets",
|
||||
"projectFolder": "plugins/drive-assets",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/drive-resources",
|
||||
"projectFolder": "plugins/drive-resources",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/model-drive",
|
||||
"projectFolder": "models/drive",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/server-drive",
|
||||
"projectFolder": "server-plugins/drive",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/model-server-drive",
|
||||
"projectFolder": "models/server-drive",
|
||||
"shouldPublish": false
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/server-drive-resources",
|
||||
"projectFolder": "server-plugins/drive-resources",
|
||||
"shouldPublish": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@hcengineering/server-drive-resources",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"format": "format src",
|
||||
"test": "jest --passWithNoTests --silent",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:test": "jest --passWithNoTests --silent",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.3.3",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/server-core": "^0.6.1",
|
||||
"@hcengineering/drive": "^0.6.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import {
|
||||
type Class,
|
||||
type Doc,
|
||||
type Hierarchy,
|
||||
type Ref,
|
||||
type Tx,
|
||||
type TxRemoveDoc,
|
||||
TxProcessor,
|
||||
DocumentQuery,
|
||||
FindOptions,
|
||||
FindResult
|
||||
} from '@hcengineering/core'
|
||||
import drive, { type File, type Folder } from '@hcengineering/drive'
|
||||
import type { TriggerControl } from '@hcengineering/server-core'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function OnFileDelete (
|
||||
tx: Tx,
|
||||
{ removedMap, ctx, storageAdapter, workspace }: TriggerControl
|
||||
): Promise<Tx[]> {
|
||||
const rmTx = TxProcessor.extractTx(tx) as TxRemoveDoc<File>
|
||||
|
||||
// Obtain document being deleted.
|
||||
const attach = removedMap.get(rmTx.objectId) as File
|
||||
|
||||
if (attach === undefined) {
|
||||
return []
|
||||
}
|
||||
|
||||
await storageAdapter.remove(ctx, workspace, [attach.file])
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function FindFolderResources (
|
||||
doc: Doc,
|
||||
hiearachy: Hierarchy,
|
||||
findAll: <T extends Doc>(
|
||||
clazz: Ref<Class<T>>,
|
||||
query: DocumentQuery<T>,
|
||||
options?: FindOptions<T>
|
||||
) => Promise<FindResult<T>>
|
||||
): Promise<Doc[]> {
|
||||
const folder = doc as Folder
|
||||
|
||||
const files = await findAll(drive.class.File, { parent: folder._id })
|
||||
const folders = await findAll(drive.class.Folder, { parent: folder._id })
|
||||
return [...files, ...folders]
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export default async () => ({
|
||||
trigger: {
|
||||
OnFileDelete
|
||||
},
|
||||
function: {
|
||||
FindFolderResources
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@hcengineering/server-drive",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"author": "Hardcore Engineering Inc.",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"format": "format src",
|
||||
"test": "jest --passWithNoTests --silent",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:test": "jest --passWithNoTests --silent",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@types/node": "~20.11.16",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.3.3",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/core": "^0.6.28",
|
||||
"@hcengineering/platform": "^0.6.9",
|
||||
"@hcengineering/server-core": "^0.6.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright © 2024 Hardcore Engineering Inc.
|
||||
//
|
||||
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License. You may
|
||||
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
//
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import type { Plugin, Resource } from '@hcengineering/platform'
|
||||
import { plugin } from '@hcengineering/platform'
|
||||
import type { ObjectDDParticipantFunc, TriggerFunc } from '@hcengineering/server-core'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const serverDriveId = 'server-drive' as Plugin
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export default plugin(serverDriveId, {
|
||||
trigger: {
|
||||
OnFileDelete: '' as Resource<TriggerFunc>
|
||||
},
|
||||
function: {
|
||||
FindFolderResources: '' as Resource<ObjectDDParticipantFunc>
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user