diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index dbb9d356c6..15c8809e54 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -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 diff --git a/dev/prod/package.json b/dev/prod/package.json index 1f51e28bdf..2efecb62d9 100644 --- a/dev/prod/package.json +++ b/dev/prod/package.json @@ -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", diff --git a/dev/prod/src/platform.ts b/dev/prod/src/platform.ts index 5e332d6245..23d2cf6e75 100644 --- a/dev/prod/src/platform.ts +++ b/dev/prod/src/platform.ts @@ -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]) diff --git a/dev/tool/package.json b/dev/tool/package.json index 826c826f11..8805858fc4 100644 --- a/dev/tool/package.json +++ b/dev/tool/package.json @@ -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", diff --git a/dev/tool/src/__start.ts b/dev/tool/src/__start.ts index 0138fd6e25..c1c0d9ff7b 100644 --- a/dev/tool/src/__start.ts +++ b/dev/tool/src/__start.ts @@ -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 diff --git a/models/all/package.json b/models/all/package.json index d22ea43642..0924accedc 100644 --- a/models/all/package.json +++ b/models/all/package.json @@ -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" } } diff --git a/models/all/src/index.ts b/models/all/src/index.ts index 89014f3ac4..d2be4dc440 100644 --- a/models/all/src/index.ts +++ b/models/all/src/index.ts @@ -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) { diff --git a/models/core/src/component.ts b/models/core/src/component.ts index 364fe92f9c..12d4b9f734 100644 --- a/models/core/src/component.ts +++ b/models/core/src/component.ts @@ -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, diff --git a/models/drive/.eslintrc.js b/models/drive/.eslintrc.js new file mode 100644 index 0000000000..c1cf82cba0 --- /dev/null +++ b/models/drive/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/model/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/models/drive/.npmignore b/models/drive/.npmignore new file mode 100644 index 0000000000..e3ec093c38 --- /dev/null +++ b/models/drive/.npmignore @@ -0,0 +1,4 @@ +* +!/lib/** +!CHANGELOG.md +/lib/**/__tests__/ diff --git a/models/drive/config/rig.json b/models/drive/config/rig.json new file mode 100644 index 0000000000..2f6be36605 --- /dev/null +++ b/models/drive/config/rig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig", + "rigProfile": "model" +} diff --git a/models/drive/package.json b/models/drive/package.json new file mode 100644 index 0000000000..216b8ba160 --- /dev/null +++ b/models/drive/package.json @@ -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" + } +} diff --git a/models/drive/src/index.ts b/models/drive/src/index.ts new file mode 100644 index 0000000000..ec470a8314 --- /dev/null +++ b/models/drive/src/index.ts @@ -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 { + 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]: Ref[] +} + +@Model(drive.class.Resource, core.class.Doc, DOMAIN_DRIVE) +@UX(drive.string.Resource) +export class TResource extends TDoc implements Resource { + declare space: Ref + + @Prop(TypeString(), drive.string.Name) + @Index(IndexKind.FullText) + name!: string + + @Prop(TypeRef(core.class.Blob), drive.string.File) + @ReadOnly() + file?: Ref + + @Prop(TypeRef(drive.class.Resource), drive.string.Parent) + @Index(IndexKind.Indexed) + @ReadOnly() + parent!: Ref + + @Prop(TypeRef(drive.class.Resource), drive.string.Path) + @ReadOnly() + path!: Ref[] +} + +@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 + + @Prop(TypeRef(drive.class.Folder), drive.string.Path) + @ReadOnly() + declare path: Ref[] + + 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 + + @Prop(TypeRef(drive.class.Folder), drive.string.Parent) + @Index(IndexKind.Indexed) + @ReadOnly() + declare parent: Ref + + @Prop(TypeRef(drive.class.Folder), drive.string.Path) + @ReadOnly() + declare path: Ref[] +} + +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( + 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( + // 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) +} diff --git a/models/drive/src/plugin.ts b/models/drive/src/plugin.ts new file mode 100644 index 0000000000..4d85ad9fbf --- /dev/null +++ b/models/drive/src/plugin.ts @@ -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) => Promise>, + FolderLinkProvider: '' as Resource<(doc: Doc, props: Record) => Promise> + }, + viewlet: { + Grid: '' as Ref, + DriveTable: '' as Ref, + FileTable: '' as Ref, + FileGrid: '' as Ref + }, + category: { + Drive: '' as Ref + }, + action: { + CreateChildFolder: '' as Ref, + CreateRootFolder: '' as Ref, + EditDrive: '' as Ref, + DownloadFile: '' as Ref + }, + 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 + } +}) diff --git a/models/drive/tsconfig.json b/models/drive/tsconfig.json new file mode 100644 index 0000000000..9765b6086d --- /dev/null +++ b/models/drive/tsconfig.json @@ -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" + } +} \ No newline at end of file diff --git a/models/server-drive/.eslintrc.js b/models/server-drive/.eslintrc.js new file mode 100644 index 0000000000..c1cf82cba0 --- /dev/null +++ b/models/server-drive/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/model/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/models/server-drive/.npmignore b/models/server-drive/.npmignore new file mode 100644 index 0000000000..e3ec093c38 --- /dev/null +++ b/models/server-drive/.npmignore @@ -0,0 +1,4 @@ +* +!/lib/** +!CHANGELOG.md +/lib/**/__tests__/ diff --git a/models/server-drive/config/rig.json b/models/server-drive/config/rig.json new file mode 100644 index 0000000000..2f6be36605 --- /dev/null +++ b/models/server-drive/config/rig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig", + "rigProfile": "model" +} diff --git a/models/server-drive/package.json b/models/server-drive/package.json new file mode 100644 index 0000000000..30c4a0eb35 --- /dev/null +++ b/models/server-drive/package.json @@ -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" + } +} diff --git a/models/server-drive/src/index.ts b/models/server-drive/src/index.ts new file mode 100644 index 0000000000..30310be4fc --- /dev/null +++ b/models/server-drive/src/index.ts @@ -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, ObjectDDParticipant>( + drive.class.Folder, + core.class.Class, + serverCore.mixin.ObjectDDParticipant, + { + collectDocs: serverDrive.function.FindFolderResources + } + ) +} diff --git a/models/server-drive/tsconfig.json b/models/server-drive/tsconfig.json new file mode 100644 index 0000000000..9765b6086d --- /dev/null +++ b/models/server-drive/tsconfig.json @@ -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" + } +} \ No newline at end of file diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index da2e42a808..d17d388582 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -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, diff --git a/plugins/document-resources/src/components/teamspace/CreateTeamspace.svelte b/plugins/document-resources/src/components/teamspace/CreateTeamspace.svelte index 51f72b8004..4a5eb98f05 100644 --- a/plugins/document-resources/src/components/teamspace/CreateTeamspace.svelte +++ b/plugins/document-resources/src/components/teamspace/CreateTeamspace.svelte @@ -70,7 +70,7 @@ $: isNew = teamspace === undefined - let typeId: Ref | undefined = teamspace?.type || document.spaceType.DefaultTeamspaceType + let typeId: Ref | undefined = teamspace?.type ?? document.spaceType.DefaultTeamspaceType let spaceType: WithLookup | undefined $: void loadSpaceType(typeId) diff --git a/plugins/document/src/plugin.ts b/plugins/document/src/plugin.ts index 667af064e3..91305b7906 100644 --- a/plugins/document/src/plugin.ts +++ b/plugins/document/src/plugin.ts @@ -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 - }, app: { Documents: '' as Ref }, diff --git a/plugins/drive-assets/.eslintrc.js b/plugins/drive-assets/.eslintrc.js new file mode 100644 index 0000000000..e73094bc7e --- /dev/null +++ b/plugins/drive-assets/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/assets/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/plugins/drive-assets/assets/icons.svg b/plugins/drive-assets/assets/icons.svg new file mode 100644 index 0000000000..42d65c2a11 --- /dev/null +++ b/plugins/drive-assets/assets/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/drive-assets/config/rig.json b/plugins/drive-assets/config/rig.json new file mode 100644 index 0000000000..b75800b9b7 --- /dev/null +++ b/plugins/drive-assets/config/rig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig", + "rigProfile": "assets" +} diff --git a/plugins/drive-assets/jest.config.js b/plugins/drive-assets/jest.config.js new file mode 100644 index 0000000000..2cfd408b67 --- /dev/null +++ b/plugins/drive-assets/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + roots: ["./src"], + coverageReporters: ["text-summary", "html"] +} diff --git a/plugins/drive-assets/lang/en.json b/plugins/drive-assets/lang/en.json new file mode 100644 index 0000000000..0742c38616 --- /dev/null +++ b/plugins/drive-assets/lang/en.json @@ -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": "/" + } +} diff --git a/plugins/drive-assets/lang/es.json b/plugins/drive-assets/lang/es.json new file mode 100644 index 0000000000..5f1041a851 --- /dev/null +++ b/plugins/drive-assets/lang/es.json @@ -0,0 +1,5 @@ +{ + "string": { + "Storage": "Depósito" + } +} diff --git a/plugins/drive-assets/lang/pt.json b/plugins/drive-assets/lang/pt.json new file mode 100644 index 0000000000..2aef4829c3 --- /dev/null +++ b/plugins/drive-assets/lang/pt.json @@ -0,0 +1,5 @@ +{ + "string": { + "Storage": "Armazenagem" + } +} diff --git a/plugins/drive-assets/lang/ru.json b/plugins/drive-assets/lang/ru.json new file mode 100644 index 0000000000..1c9d2f27b5 --- /dev/null +++ b/plugins/drive-assets/lang/ru.json @@ -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": "/" + } +} diff --git a/plugins/drive-assets/package.json b/plugins/drive-assets/package.json new file mode 100644 index 0000000000..043ae31cc5 --- /dev/null +++ b/plugins/drive-assets/package.json @@ -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" + } +} diff --git a/plugins/drive-assets/src/__tests__/lang.test.ts b/plugins/drive-assets/src/__tests__/lang.test.ts new file mode 100644 index 0000000000..cf96c6dcf7 --- /dev/null +++ b/plugins/drive-assets/src/__tests__/lang.test.ts @@ -0,0 +1,6 @@ +import { makeLocalesTest } from '@hcengineering/platform' + +it( + 'Locales are equale', + makeLocalesTest((lang) => import(`../../lang/${lang}.json`)) +) diff --git a/plugins/drive-assets/src/index.ts b/plugins/drive-assets/src/index.ts new file mode 100644 index 0000000000..18a19691c2 --- /dev/null +++ b/plugins/drive-assets/src/index.ts @@ -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` +}) diff --git a/plugins/drive-assets/tsconfig.json b/plugins/drive-assets/tsconfig.json new file mode 100644 index 0000000000..4449c73536 --- /dev/null +++ b/plugins/drive-assets/tsconfig.json @@ -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" + } +} \ No newline at end of file diff --git a/plugins/drive-resources/.eslintrc.js b/plugins/drive-resources/.eslintrc.js new file mode 100644 index 0000000000..bb8fd7450d --- /dev/null +++ b/plugins/drive-resources/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/ui/eslint.config.json'], + parserOptions: { tsconfigRootDir: __dirname } +} diff --git a/plugins/drive-resources/.prettierrc b/plugins/drive-resources/.prettierrc new file mode 100644 index 0000000000..792942803a --- /dev/null +++ b/plugins/drive-resources/.prettierrc @@ -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" + } + } + ] +} \ No newline at end of file diff --git a/plugins/drive-resources/config/rig.json b/plugins/drive-resources/config/rig.json new file mode 100644 index 0000000000..bcad6f7c33 --- /dev/null +++ b/plugins/drive-resources/config/rig.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig", + "rigProfile": "ui" +} diff --git a/plugins/drive-resources/jest.config.js b/plugins/drive-resources/jest.config.js new file mode 100644 index 0000000000..3656e284d3 --- /dev/null +++ b/plugins/drive-resources/jest.config.js @@ -0,0 +1,5 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'] +} diff --git a/plugins/drive-resources/package.json b/plugins/drive-resources/package.json new file mode 100644 index 0000000000..1d4ec3bf44 --- /dev/null +++ b/plugins/drive-resources/package.json @@ -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" + } +} diff --git a/plugins/drive-resources/postcss.config.js b/plugins/drive-resources/postcss.config.js new file mode 100644 index 0000000000..88752c6cb0 --- /dev/null +++ b/plugins/drive-resources/postcss.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + require('autoprefixer') + ] +} diff --git a/plugins/drive-resources/src/components/CreateDrive.svelte b/plugins/drive-resources/src/components/CreateDrive.svelte new file mode 100644 index 0000000000..a6013e815a --- /dev/null +++ b/plugins/drive-resources/src/components/CreateDrive.svelte @@ -0,0 +1,324 @@ + + + + +
+
+
+
+ + +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+ +
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ + {#each roles as role} +
+
+
+ { + handleRoleAssignmentChanged(role._id, refs) + }} + kind={'regular'} + size={'large'} + /> +
+ {/each} +
+
diff --git a/plugins/drive-resources/src/components/CreateFolder.svelte b/plugins/drive-resources/src/components/CreateFolder.svelte new file mode 100644 index 0000000000..9e9dda5105 --- /dev/null +++ b/plugins/drive-resources/src/components/CreateFolder.svelte @@ -0,0 +1,121 @@ + + + + + + { + dispatch('close') + }} + on:changeContent +> + + + { + console.log('selected', evt) + }} + /> + + +
+ +
+
diff --git a/plugins/drive-resources/src/components/DriveHeader.svelte b/plugins/drive-resources/src/components/DriveHeader.svelte new file mode 100644 index 0000000000..203266a000 --- /dev/null +++ b/plugins/drive-resources/src/components/DriveHeader.svelte @@ -0,0 +1,53 @@ + + + +
+
+
+ +
+
+
+
+
diff --git a/plugins/drive-resources/src/components/DrivePanel.svelte b/plugins/drive-resources/src/components/DrivePanel.svelte new file mode 100644 index 0000000000..3ee16e12be --- /dev/null +++ b/plugins/drive-resources/src/components/DrivePanel.svelte @@ -0,0 +1,63 @@ + + + +{#if object} +
+ + +
+
+ +
+ + {#if asideShown} + +
+ +
+ +
+
+ {/if} +
+
+{/if} diff --git a/plugins/drive-resources/src/components/DrivePresenter.svelte b/plugins/drive-resources/src/components/DrivePresenter.svelte new file mode 100644 index 0000000000..ff04b866ea --- /dev/null +++ b/plugins/drive-resources/src/components/DrivePresenter.svelte @@ -0,0 +1,56 @@ + + + +{#if value} + {#if inline} + + {:else if type === 'link'} + +
+ {#if shouldShowAvatar} +
+ +
+ {/if} + + {value.name} + +
+
+ {:else if type === 'text'} + + {value.name} + + {/if} +{/if} diff --git a/plugins/drive-resources/src/components/DriveSpaceHeader.svelte b/plugins/drive-resources/src/components/DriveSpaceHeader.svelte new file mode 100644 index 0000000000..d82fec057f --- /dev/null +++ b/plugins/drive-resources/src/components/DriveSpaceHeader.svelte @@ -0,0 +1,147 @@ + + + +{#if loading} + +{:else} + + +
+ {#if hasDrive} + { + void handleDropdownItemSelected(ev.detail) + }} + /> + {:else} +
+{/if} diff --git a/plugins/drive-resources/src/components/DriveSpacePresenter.svelte b/plugins/drive-resources/src/components/DriveSpacePresenter.svelte new file mode 100644 index 0000000000..90a5dffaed --- /dev/null +++ b/plugins/drive-resources/src/components/DriveSpacePresenter.svelte @@ -0,0 +1,119 @@ + + + +{#if space} + 0} + actions={() => getActions(space)} + on:click={() => { + handleDriveSelected(space._id) + }} + > + + { + handleFolderSelected(ev.detail) + }} + /> + + +{/if} diff --git a/plugins/drive-resources/src/components/EditFolder.svelte b/plugins/drive-resources/src/components/EditFolder.svelte new file mode 100644 index 0000000000..8b9b03e497 --- /dev/null +++ b/plugins/drive-resources/src/components/EditFolder.svelte @@ -0,0 +1,26 @@ + + + +{#if object} + +{/if} diff --git a/plugins/drive-resources/src/components/FilePresenter.svelte b/plugins/drive-resources/src/components/FilePresenter.svelte new file mode 100644 index 0000000000..bd23a3bf2d --- /dev/null +++ b/plugins/drive-resources/src/components/FilePresenter.svelte @@ -0,0 +1,56 @@ + + + +{#if value} + {#if inline} + + {:else if type === 'link'} + +
+ {#if shouldShowAvatar} +
+ +
+ {/if} + + {value.name} + +
+
+ {:else if type === 'text'} + + {value.name} + + {/if} +{/if} diff --git a/plugins/drive-resources/src/components/FileSizePresenter.svelte b/plugins/drive-resources/src/components/FileSizePresenter.svelte new file mode 100644 index 0000000000..a0dba4e57b --- /dev/null +++ b/plugins/drive-resources/src/components/FileSizePresenter.svelte @@ -0,0 +1,26 @@ + + + +{#if value} + + {value !== undefined ? filesize(value) : '-'} + +{/if} diff --git a/plugins/drive-resources/src/components/FolderBrowser.svelte b/plugins/drive-resources/src/components/FolderBrowser.svelte new file mode 100644 index 0000000000..33c22d707b --- /dev/null +++ b/plugins/drive-resources/src/components/FolderBrowser.svelte @@ -0,0 +1,105 @@ + + + +{#if space !== undefined} + +
{ + dragover = true + }} + on:dragleave={() => { + dragover = false + }} + on:drop|preventDefault|stopPropagation={(ev) => { + void handleDrop(ev) + }} + > +
+
+ {}} /> +
+ +
+
+ + +
+
+ + {#if viewlet !== undefined && viewOptions} + (resultQuery = e.detail)} /> +
+ {#if viewlet} + + + + {/if} +
+ {/if} +
+{/if} diff --git a/plugins/drive-resources/src/components/FolderHeader.svelte b/plugins/drive-resources/src/components/FolderHeader.svelte new file mode 100644 index 0000000000..14136e8381 --- /dev/null +++ b/plugins/drive-resources/src/components/FolderHeader.svelte @@ -0,0 +1,81 @@ + + + +
+
+ +
+ +
+
+
+
+
diff --git a/plugins/drive-resources/src/components/FolderPanel.svelte b/plugins/drive-resources/src/components/FolderPanel.svelte new file mode 100644 index 0000000000..79182d1e38 --- /dev/null +++ b/plugins/drive-resources/src/components/FolderPanel.svelte @@ -0,0 +1,63 @@ + + + +{#if object} +
+ + +
+
+ +
+ + {#if asideShown} + +
+ +
+ +
+
+ {/if} +
+
+{/if} diff --git a/plugins/drive-resources/src/components/FolderPresenter.svelte b/plugins/drive-resources/src/components/FolderPresenter.svelte new file mode 100644 index 0000000000..fc5508df64 --- /dev/null +++ b/plugins/drive-resources/src/components/FolderPresenter.svelte @@ -0,0 +1,56 @@ + + + +{#if value} + {#if inline} + + {:else if type === 'link'} + +
+ {#if shouldShowAvatar} +
+ +
+ {/if} + + {value.name} + +
+
+ {:else if type === 'text'} + + {value.name} + + {/if} +{/if} diff --git a/plugins/drive-resources/src/components/FolderTreeElement.svelte b/plugins/drive-resources/src/components/FolderTreeElement.svelte new file mode 100644 index 0000000000..a8f044f5fb --- /dev/null +++ b/plugins/drive-resources/src/components/FolderTreeElement.svelte @@ -0,0 +1,101 @@ + + + + + +
0 ? level * 1.25 + 0.125 : 0.75}rem`} + on:click={() => { + if (selected) { + collapsed = !collapsed + } + dispatch('click') + }} +> + {#if !folder} +
{ + if (parent) collapsed = !collapsed + }} + > + {#if parent}{/if} +
+ {/if} + + {#if icon} +
+ +
+ {/if} + + {#if label} +
+ +
+ +
+
+ +{#if parent && !collapsed} +
+{/if} diff --git a/plugins/drive-resources/src/components/FolderTreeLevel.svelte b/plugins/drive-resources/src/components/FolderTreeLevel.svelte new file mode 100644 index 0000000000..04d7d9de70 --- /dev/null +++ b/plugins/drive-resources/src/components/FolderTreeLevel.svelte @@ -0,0 +1,87 @@ + + + +{#each _folders as doc} + {@const desc = _descendants.get(doc._id) ?? []} + + {#if doc} + 0} + actions={async () => await getActions(doc)} + {level} + on:click={() => { + handleSelected(doc._id) + }} + > + {#if desc.length} + + {/if} + + {/if} +{/each} diff --git a/plugins/drive-resources/src/components/GridView.svelte b/plugins/drive-resources/src/components/GridView.svelte new file mode 100644 index 0000000000..15b055d8e9 --- /dev/null +++ b/plugins/drive-resources/src/components/GridView.svelte @@ -0,0 +1,18 @@ + + + +
Here will be grid view
diff --git a/plugins/drive-resources/src/components/ResourcePresenter.svelte b/plugins/drive-resources/src/components/ResourcePresenter.svelte new file mode 100644 index 0000000000..72bacd93af --- /dev/null +++ b/plugins/drive-resources/src/components/ResourcePresenter.svelte @@ -0,0 +1,53 @@ + + + +{#if value} + {#if isFile(value)} + + {:else if isFolder(value)} + + {/if} +{/if} diff --git a/plugins/drive-resources/src/index.ts b/plugins/drive-resources/src/index.ts new file mode 100644 index 0000000000..d2a67a555c --- /dev/null +++ b/plugins/drive-resources/src/index.ts @@ -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 { + await createFolder(doc._id, drive.ids.Root) +} + +async function CreateChildFolder (doc: Folder): Promise { + await createFolder(doc.space, doc._id) +} + +async function EditDrive (drive: Drive): Promise { + showPopup(CreateDrive, { drive }) +} + +async function DownloadFile (doc: File | File[]): Promise { + 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 { + return getDriveLink(doc._id as Ref) +} + +async function FolderLinkProvider (doc: Doc): Promise { + return getFolderLink(doc._id as Ref) +} + +export default async (): Promise => ({ + component: { + CreateDrive, + DrivePanel, + DriveSpaceHeader, + DriveSpacePresenter, + DrivePresenter, + EditFolder, + FilePresenter, + FileSizePresenter, + FolderPanel, + FolderPresenter, + GridView, + ResourcePresenter + }, + actionImpl: { + CreateChildFolder, + CreateRootFolder, + EditDrive, + DownloadFile + }, + function: { + DriveLinkProvider, + FolderLinkProvider + }, + resolver: { + Location: resolveLocation + } +}) diff --git a/plugins/drive-resources/src/navigation.ts b/plugins/drive-resources/src/navigation.ts new file mode 100644 index 0000000000..ba2072c526 --- /dev/null +++ b/plugins/drive-resources/src/navigation.ts @@ -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 (object: Pick): string { + const hierarchy = getClient().getHierarchy() + const objectPanelMixin = hierarchy.classHierarchyMixin(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 | undefined { + const [, _id] = decodeURIComponent(fragment).split('|') + return _id as Ref +} + +export function getDriveLink (_id: Ref): 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): 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 { + if (loc.path[2] !== driveId) { + return undefined + } + + if (loc.path[3] === 'folder' && loc.path[4] !== undefined) { + const folderId = loc.path[4] as Ref + return await generateFolderLocation(loc, folderId) + } + + if (loc.path[3] !== undefined) { + const driveId = loc.path[3] as Ref + return await generateDriveLocation(loc, driveId) + } + + return undefined +} + +export async function generateFolderLocation (loc: Location, id: Ref): Promise { + 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): Promise { + 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) + } + } +} diff --git a/plugins/drive-resources/src/plugin.ts b/plugins/drive-resources/src/plugin.ts new file mode 100644 index 0000000000..96071d4a0b --- /dev/null +++ b/plugins/drive-resources/src/plugin.ts @@ -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 + } +}) diff --git a/plugins/drive-resources/src/utils.ts b/plugins/drive-resources/src/utils.ts new file mode 100644 index 0000000000..3a3168e0ac --- /dev/null +++ b/plugins/drive-resources/src/utils.ts @@ -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, _class: Ref>): Promise { + const client = getClient() + const doc = await client.findOne(_class, { _id }) + if (doc !== undefined) { + void openDoc(client.getHierarchy(), doc) + } +} + +export async function createFolder (space: Ref, parent: Ref, open = false): Promise { + 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 { + showPopup(CreateDrive, {}, 'top', async (id) => { + if (open && id !== undefined && id !== null) { + await navigateToDoc(id, drive.class.Folder) + } + }) +} + +export async function editDrive (drive: Drive): Promise { + showPopup(CreateDrive, { drive }) +} + +export async function createFiles (list: FileList, space: Ref, parent: Ref): Promise { + 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, parent: Folder | undefined): Promise { + 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, + parent: parent?._id ?? drive.ids.Root, + path: parent !== undefined ? [parent._id, ...parent.path] : [] + }) + } catch (e) { + void setPlatformStatus(unknownError(e)) + } +} diff --git a/plugins/drive-resources/svelte.config.js b/plugins/drive-resources/svelte.config.js new file mode 100644 index 0000000000..944a06f73e --- /dev/null +++ b/plugins/drive-resources/svelte.config.js @@ -0,0 +1,5 @@ +const sveltePreprocess = require('svelte-preprocess') + +module.exports = { + preprocess: sveltePreprocess() +}; \ No newline at end of file diff --git a/plugins/drive-resources/tsconfig.json b/plugins/drive-resources/tsconfig.json new file mode 100644 index 0000000000..fb6ccb2d18 --- /dev/null +++ b/plugins/drive-resources/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "./node_modules/@hcengineering/platform-rig/profiles/ui/tsconfig.json", + + "compilerOptions": { + "rootDir": "./src", + "outDir": "./lib", + "declarationDir": "./types" + } +} \ No newline at end of file diff --git a/plugins/drive/.eslintrc.js b/plugins/drive/.eslintrc.js new file mode 100644 index 0000000000..72235dc283 --- /dev/null +++ b/plugins/drive/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/plugins/drive/.npmignore b/plugins/drive/.npmignore new file mode 100644 index 0000000000..e3ec093c38 --- /dev/null +++ b/plugins/drive/.npmignore @@ -0,0 +1,4 @@ +* +!/lib/** +!CHANGELOG.md +/lib/**/__tests__/ diff --git a/plugins/drive/config/rig.json b/plugins/drive/config/rig.json new file mode 100644 index 0000000000..0110930f55 --- /dev/null +++ b/plugins/drive/config/rig.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig" +} diff --git a/plugins/drive/jest.config.js b/plugins/drive/jest.config.js new file mode 100644 index 0000000000..2cfd408b67 --- /dev/null +++ b/plugins/drive/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + roots: ["./src"], + coverageReporters: ["text-summary", "html"] +} diff --git a/plugins/drive/package.json b/plugins/drive/package.json new file mode 100644 index 0000000000..62a6b9410d --- /dev/null +++ b/plugins/drive/package.json @@ -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" + } +} diff --git a/plugins/drive/src/index.ts b/plugins/drive/src/index.ts new file mode 100644 index 0000000000..3f99fc6ba1 --- /dev/null +++ b/plugins/drive/src/index.ts @@ -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 diff --git a/plugins/drive/src/plugin.ts b/plugins/drive/src/plugin.ts new file mode 100644 index 0000000000..f82c1b87f7 --- /dev/null +++ b/plugins/drive/src/plugin.ts @@ -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>, + File: '' as Ref>, + Folder: '' as Ref>, + Resource: '' as Ref>, + TypeFileSize: '' as Ref>> + }, + mixin: { + DefaultDriveTypeData: '' as Ref> + }, + icon: { + Drive: '' as Asset, + File: '' as Asset, + Folder: '' as Asset, + FolderOpen: '' as Asset, + FolderClosed: '' as Asset, + Download: '' as Asset + }, + app: { + Drive: '' as Ref + }, + ids: { + Root: '' as Ref + }, + resolver: { + Location: '' as PlatformResource<(loc: Location) => Promise> + }, + string: { + Drive: '' as IntlString, + File: '' as IntlString, + Folder: '' as IntlString, + Resource: '' as IntlString + }, + descriptor: { + DriveType: '' as Ref + }, + spaceType: { + DefaultDrive: '' as Ref + } +}) + +export default drivePlugin diff --git a/plugins/drive/src/types.ts b/plugins/drive/src/types.ts new file mode 100644 index 0000000000..0d827516e5 --- /dev/null +++ b/plugins/drive/src/types.ts @@ -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 { + name: string + file?: Ref + + parent: Ref + path: Ref[] +} + +/** @public */ +export interface Folder extends Resource { + parent: Ref + path: Ref[] + + file?: undefined +} + +/** @public */ +export interface File extends Resource { + file: Ref + + parent: Ref + path: Ref[] +} diff --git a/plugins/drive/tsconfig.json b/plugins/drive/tsconfig.json new file mode 100644 index 0000000000..59e4fd4297 --- /dev/null +++ b/plugins/drive/tsconfig.json @@ -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" + } +} \ No newline at end of file diff --git a/plugins/view-resources/src/components/DocsNavigator.svelte b/plugins/view-resources/src/components/DocsNavigator.svelte new file mode 100644 index 0000000000..0b2207c4e9 --- /dev/null +++ b/plugins/view-resources/src/components/DocsNavigator.svelte @@ -0,0 +1,58 @@ + + + +{#await getBreadcrumbsModels(elements) then models} + {#if models.length > 0} + + {/if} +{/await} diff --git a/plugins/view-resources/src/components/ParentsNavigator.svelte b/plugins/view-resources/src/components/ParentsNavigator.svelte index 8703be806d..b534514fa1 100644 --- a/plugins/view-resources/src/components/ParentsNavigator.svelte +++ b/plugins/view-resources/src/components/ParentsNavigator.svelte @@ -14,15 +14,19 @@ --> -{#await getBreadcrumbsModels(element) then models} - {#if models.length > 0} - - {/if} +{#await getParents(element) then parents} + {/await} diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts index 945fe1f7be..7ab3645911 100644 --- a/plugins/view-resources/src/index.ts +++ b/plugins/view-resources/src/index.ts @@ -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' diff --git a/pods/server/package.json b/pods/server/package.json index 2d1db32ce5..0a9da8b88b 100644 --- a/pods/server/package.json +++ b/pods/server/package.json @@ -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", diff --git a/pods/server/src/server.ts b/pods/server/src/server.ts index 3a697574f4..cb3c430976 100644 --- a/pods/server/src/server.ts +++ b/pods/server/src/server.ts @@ -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 diff --git a/rush.json b/rush.json index 76fe286f6d..81aa1c985b 100644 --- a/rush.json +++ b/rush.json @@ -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 } ] } diff --git a/server-plugins/drive-resources/.eslintrc.js b/server-plugins/drive-resources/.eslintrc.js new file mode 100644 index 0000000000..72235dc283 --- /dev/null +++ b/server-plugins/drive-resources/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/server-plugins/drive-resources/.npmignore b/server-plugins/drive-resources/.npmignore new file mode 100644 index 0000000000..e3ec093c38 --- /dev/null +++ b/server-plugins/drive-resources/.npmignore @@ -0,0 +1,4 @@ +* +!/lib/** +!CHANGELOG.md +/lib/**/__tests__/ diff --git a/server-plugins/drive-resources/config/rig.json b/server-plugins/drive-resources/config/rig.json new file mode 100644 index 0000000000..0110930f55 --- /dev/null +++ b/server-plugins/drive-resources/config/rig.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig" +} diff --git a/server-plugins/drive-resources/jest.config.js b/server-plugins/drive-resources/jest.config.js new file mode 100644 index 0000000000..2cfd408b67 --- /dev/null +++ b/server-plugins/drive-resources/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + roots: ["./src"], + coverageReporters: ["text-summary", "html"] +} diff --git a/server-plugins/drive-resources/package.json b/server-plugins/drive-resources/package.json new file mode 100644 index 0000000000..82bade5ba1 --- /dev/null +++ b/server-plugins/drive-resources/package.json @@ -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" + } +} diff --git a/server-plugins/drive-resources/src/index.ts b/server-plugins/drive-resources/src/index.ts new file mode 100644 index 0000000000..ce88aba57b --- /dev/null +++ b/server-plugins/drive-resources/src/index.ts @@ -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 { + const rmTx = TxProcessor.extractTx(tx) as TxRemoveDoc + + // 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: ( + clazz: Ref>, + query: DocumentQuery, + options?: FindOptions + ) => Promise> +): Promise { + 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 + } +}) diff --git a/server-plugins/drive-resources/tsconfig.json b/server-plugins/drive-resources/tsconfig.json new file mode 100644 index 0000000000..59e4fd4297 --- /dev/null +++ b/server-plugins/drive-resources/tsconfig.json @@ -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" + } +} \ No newline at end of file diff --git a/server-plugins/drive/.eslintrc.js b/server-plugins/drive/.eslintrc.js new file mode 100644 index 0000000000..72235dc283 --- /dev/null +++ b/server-plugins/drive/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'], + parserOptions: { + tsconfigRootDir: __dirname, + project: './tsconfig.json' + } +} diff --git a/server-plugins/drive/.npmignore b/server-plugins/drive/.npmignore new file mode 100644 index 0000000000..e3ec093c38 --- /dev/null +++ b/server-plugins/drive/.npmignore @@ -0,0 +1,4 @@ +* +!/lib/** +!CHANGELOG.md +/lib/**/__tests__/ diff --git a/server-plugins/drive/config/rig.json b/server-plugins/drive/config/rig.json new file mode 100644 index 0000000000..0110930f55 --- /dev/null +++ b/server-plugins/drive/config/rig.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", + "rigPackageName": "@hcengineering/platform-rig" +} diff --git a/server-plugins/drive/jest.config.js b/server-plugins/drive/jest.config.js new file mode 100644 index 0000000000..2cfd408b67 --- /dev/null +++ b/server-plugins/drive/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'], + roots: ["./src"], + coverageReporters: ["text-summary", "html"] +} diff --git a/server-plugins/drive/package.json b/server-plugins/drive/package.json new file mode 100644 index 0000000000..9a75558eeb --- /dev/null +++ b/server-plugins/drive/package.json @@ -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" + } +} diff --git a/server-plugins/drive/src/index.ts b/server-plugins/drive/src/index.ts new file mode 100644 index 0000000000..5e6cb74f40 --- /dev/null +++ b/server-plugins/drive/src/index.ts @@ -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 + }, + function: { + FindFolderResources: '' as Resource + } +}) diff --git a/server-plugins/drive/tsconfig.json b/server-plugins/drive/tsconfig.json new file mode 100644 index 0000000000..59e4fd4297 --- /dev/null +++ b/server-plugins/drive/tsconfig.json @@ -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" + } +} \ No newline at end of file