From 280a0819a2064a9d57cf6f3534f97bfe4111b5cd Mon Sep 17 00:00:00 2001 From: Victor Ilyushchenko Date: Wed, 9 Apr 2025 15:14:38 +0300 Subject: [PATCH] Cherry Pick of recent changes in qms (#8498) Signed-off-by: Victor Ilyushchenko --- packages/core/src/component.ts | 5 +- packages/core/src/utils.ts | 5 +- packages/presentation/src/configuration.ts | 31 ++++-- .../controlled-documents-assets/lang/cs.json | 6 +- .../controlled-documents-assets/lang/de.json | 6 +- .../controlled-documents-assets/lang/en.json | 6 +- .../controlled-documents-assets/lang/fr.json | 6 +- .../controlled-documents-assets/lang/it.json | 6 +- .../controlled-documents-assets/lang/ru.json | 6 +- .../controlled-documents-assets/lang/zh.json | 6 +- .../src/components/EditDocPanel.svelte | 101 +++++++++-------- .../create-doc/QmsDocumentWizard.svelte | 6 + .../create-doc/QmsTemplateWizard.svelte | 6 + .../components/document/EditDocContent.svelte | 4 + .../right-panel/DocumentInfoTab.svelte | 10 +- .../src/plugin.ts | 5 +- .../src/stores/editors/document.ts | 1 + .../editors/document/canRestoreDraft.ts | 29 +++++ .../src/utils.ts | 103 +++++++++++------- plugins/controlled-documents/src/docutils.ts | 4 +- plugins/controlled-documents/src/plugin.ts | 1 + plugins/controlled-documents/src/utils.ts | 63 ++++++++--- plugins/setting-assets/lang/cs.json | 6 +- plugins/setting-assets/lang/de.json | 6 +- plugins/setting-assets/lang/en.json | 10 +- plugins/setting-assets/lang/es.json | 6 +- plugins/setting-assets/lang/fr.json | 6 +- plugins/setting-assets/lang/it.json | 6 +- plugins/setting-assets/lang/pt.json | 6 +- plugins/setting-assets/lang/ru.json | 7 +- plugins/setting-assets/lang/zh.json | 6 +- .../src/components/Configure.svelte | 4 +- .../src/components/General.svelte | 79 +++++++++++--- plugins/setting-resources/src/plugin.ts | 6 +- plugins/setting/src/index.ts | 1 + .../related/RelatedIssuesSection.svelte | 4 +- plugins/workbench-resources/src/workbench.ts | 38 ++++--- server/middleware/src/configuration.ts | 23 +--- 38 files changed, 428 insertions(+), 202 deletions(-) create mode 100644 plugins/controlled-documents-resources/src/stores/editors/document/canRestoreDraft.ts diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 3dad7ffa74..e700b561e0 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -import type { Asset, IntlString, Plugin, StatusCode } from '@hcengineering/platform' +import type { Asset, IntlString, Metadata, Plugin, StatusCode } from '@hcengineering/platform' import { plugin } from '@hcengineering/platform' import type { BenchmarkDoc } from './benchmark' import { AccountRole } from './classes' @@ -288,5 +288,8 @@ export default plugin(coreId, { }, role: { Admin: '' as Ref + }, + metadata: { + DisablePermissions: '' as Metadata } }) diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 2c20921077..7a661f6f82 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import { getEmbeddedLabel, IntlString } from '@hcengineering/platform' +import { getEmbeddedLabel, getMetadata, IntlString } from '@hcengineering/platform' import { deepEqual } from 'fast-equals' import { DOMAIN_BENCHMARK } from './benchmark' import { @@ -555,6 +555,9 @@ export async function checkPermission ( _space: Ref, space?: TypedSpace ): Promise { + const arePermissionsDisabled = getMetadata(core.metadata.DisablePermissions) ?? false + if (arePermissionsDisabled) return true + space = space ?? (await client.findOne(core.class.TypedSpace, { _id: _space })) const type = await client .getModel() diff --git a/packages/presentation/src/configuration.ts b/packages/presentation/src/configuration.ts index 9cee84e65f..41bdafe127 100644 --- a/packages/presentation/src/configuration.ts +++ b/packages/presentation/src/configuration.ts @@ -13,7 +13,15 @@ // limitations under the License. // -import core, { SortingOrder, type PluginConfiguration, type Tx, type TxUpdateDoc } from '@hcengineering/core' +import core, { + type Configuration, + type PluginConfiguration, + type Ref, + SortingOrder, + toIdMap, + type Tx, + type TxUpdateDoc +} from '@hcengineering/core' import { getResourcePlugin, type Plugin, type Resource } from '@hcengineering/platform' import { writable } from 'svelte/store' import { addTxListener, createQuery } from '.' @@ -41,10 +49,10 @@ export class ConfigurationManager { } } // Issue status live query -export let configuration = new ConfigurationManager([], new Map()) -export const configurationStore = writable(configuration) +export let pluginConfiguration = new ConfigurationManager([], new Map()) +export const pluginConfigurationStore = writable(pluginConfiguration) -const configQuery = createQuery(true) +const pluginConfigQuery = createQuery(true) addTxListener((txes: Tx[]) => { for (const tx of txes) { @@ -63,15 +71,22 @@ addTxListener((txes: Tx[]) => { * @public */ export function hasResource (resource?: Resource): boolean | undefined { - return configuration.hasResource(resource) + return pluginConfiguration.hasResource(resource) } -configQuery.query( +pluginConfigQuery.query( core.class.PluginConfiguration, {}, (res) => { - configuration = new ConfigurationManager(res, new Map(res.map((it) => [it.pluginId, it]))) - configurationStore.set(configuration) + pluginConfiguration = new ConfigurationManager(res, new Map(res.map((it) => [it.pluginId, it]))) + pluginConfigurationStore.set(pluginConfiguration) }, { sort: { pluginId: SortingOrder.Ascending } } ) + +const configQuery = createQuery(true) +export const configurationStore = writable, Configuration>>(new Map()) + +configQuery.query(core.class.Configuration, {}, (res) => { + configurationStore.set(toIdMap(res)) +}) diff --git a/plugins/controlled-documents-assets/lang/cs.json b/plugins/controlled-documents-assets/lang/cs.json index 4241ef4869..4a8c9dc26d 100644 --- a/plugins/controlled-documents-assets/lang/cs.json +++ b/plugins/controlled-documents-assets/lang/cs.json @@ -252,6 +252,7 @@ "Name": "Název", "DraftRevision": "Revize konceptu", "CreateNewDraft": "Vytvořit nový koncept", + "RestoreDraft": "Obnovit koncept", "ChangeSeverity": "Změnit závažnost", "Reference": "Reference", "History": "Historie", @@ -302,7 +303,10 @@ "MakeDocumentObsoleteDialog": "Označit {count, plural, one {dokument jako zastaralý} other {dokumenty jako zastaralé}}", "MakeDocumentObsoleteConfirm": "Opravdu chcete označit následující dokumenty jako zastaralé: {titles}?", - "LatestVersionHint": "nejnovější" + "LatestVersionHint": "nejnovější", + + "CannotDeleteFolder": "Složku nelze smazat", + "CannotDeleteFolderHint": "Před odstraněním složky prosím přesuňte všechny podřízené dokumenty na jiné místo." }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-assets/lang/de.json b/plugins/controlled-documents-assets/lang/de.json index f1866edaf9..cf7445dca5 100644 --- a/plugins/controlled-documents-assets/lang/de.json +++ b/plugins/controlled-documents-assets/lang/de.json @@ -254,6 +254,7 @@ "Name": "Name", "DraftRevision": "Entwurfsrevision", "CreateNewDraft": "Neue Version entwerfen", + "RestoreDraft": "Entwurf wiederherstellen", "ChangeSeverity": "Änderungsschwere", "Reference": "Referenz", "History": "Historie", @@ -309,7 +310,10 @@ "MakeDocumentObsoleteDialog": "{count, plural, one {Dokument als veraltet markieren} other {Dokumente als veraltet markieren}}", "MakeDocumentObsoleteConfirm": "Möchten Sie die folgenden Dokumente wirklich als veraltet markieren: {titles}?", - "LatestVersionHint": "neueste" + "LatestVersionHint": "neueste", + + "CannotDeleteFolder": "Der Ordner kann nicht gelöscht werden", + "CannotDeleteFolderHint": "Bitte verschieben Sie alle untergeordneten Dokumente an einen anderen Ort, bevor Sie den Ordner löschen." }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-assets/lang/en.json b/plugins/controlled-documents-assets/lang/en.json index a98bc2d854..866c649147 100644 --- a/plugins/controlled-documents-assets/lang/en.json +++ b/plugins/controlled-documents-assets/lang/en.json @@ -261,6 +261,7 @@ "Name": "Name", "DraftRevision": "Draft revision", "CreateNewDraft": "Draft new version", + "RestoreDraft": "Restore draft", "ChangeSeverity": "Change severity", "Reference": "Reference", "History": "History", @@ -311,7 +312,10 @@ "RenameFolder": "Rename folder", "CreateChildFolder": "Create child folder", - "LatestVersionHint": "latest" + "LatestVersionHint": "latest", + + "CannotDeleteFolder": "The folder cannot be deleted", + "CannotDeleteFolderHint": "Please move all child documents to another location before deleting the folder." }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-assets/lang/fr.json b/plugins/controlled-documents-assets/lang/fr.json index 82b93dbd9b..0ca6966086 100644 --- a/plugins/controlled-documents-assets/lang/fr.json +++ b/plugins/controlled-documents-assets/lang/fr.json @@ -219,6 +219,7 @@ "Name": "Nom", "DraftRevision": "Révision du brouillon", "CreateNewDraft": "Créer une nouvelle version brouillon", + "RestoreDraft": "Restaurer le brouillon", "ChangeSeverity": "Changer la gravité", "Reference": "Référence", "History": "Historique", @@ -269,7 +270,10 @@ "MakeDocumentObsoleteDialog": "Marquer {count, plural, one {le document comme obsolète} other {les documents comme obsolètes}}", "MakeDocumentObsoleteConfirm": "Voulez-vous vraiment marquer les documents suivants comme obsolètes : {titles} ?", - "LatestVersionHint": "dernier" + "LatestVersionHint": "dernier", + + "CannotDeleteFolder": "Le dossier ne peut pas être supprimé", + "CannotDeleteFolderHint": "Veuillez déplacer tous les documents enfants vers un autre emplacement avant de supprimer le dossier." }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-assets/lang/it.json b/plugins/controlled-documents-assets/lang/it.json index 79b28decd0..2af465bb05 100644 --- a/plugins/controlled-documents-assets/lang/it.json +++ b/plugins/controlled-documents-assets/lang/it.json @@ -217,6 +217,7 @@ "Name": "Nome", "DraftRevision": "Revisione della bozza", "CreateNewDraft": "Crea nuova versione", + "RestoreDraft": "Ripristina bozza", "ChangeSeverity": "Cambia gravità", "Reference": "Riferimento", "History": "Storia", @@ -267,7 +268,10 @@ "MakeDocumentObsoleteDialog": "Segna {count, plural, one {il documento come obsoleto} other {i documenti come obsoleti}}", "MakeDocumentObsoleteConfirm": "Vuoi davvero segnare i seguenti documenti come obsoleti: {titles}?", - "LatestVersionHint": "ultimo" + "LatestVersionHint": "ultimo", + + "CannotDeleteFolder": "Impossibile eliminare la cartella", + "CannotDeleteFolderHint": "Sposta tutti i documenti figli in un'altra posizione prima di eliminare la cartella." }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-assets/lang/ru.json b/plugins/controlled-documents-assets/lang/ru.json index 37fc54813b..5e0e832780 100644 --- a/plugins/controlled-documents-assets/lang/ru.json +++ b/plugins/controlled-documents-assets/lang/ru.json @@ -256,6 +256,7 @@ "Name": "Название", "DraftRevision": "Ревизия рабочей копии", "CreateNewDraft": "Создать новую рабочую копию", + "RestoreDraft": "Восстановить черновик", "ChangeSeverity": "Серьезность изменений", "Reference": "Референс", "History": "История", @@ -311,7 +312,10 @@ "MakeDocumentObsoleteDialog": "Пометить {count, plural, one {документ как устаревший} other {документы как устаревшие}}", "MakeDocumentObsoleteConfirm": "Вы действительно хотите пометить следующие документы как устаревшие: {titles}?", - "LatestVersionHint": "последняя" + "LatestVersionHint": "последняя", + + "CannotDeleteFolder": "Папка не может быть удалена", + "CannotDeleteFolderHint": "Пожалуйста, переместите все дочерние документы в другое место перед удалением папки." }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-assets/lang/zh.json b/plugins/controlled-documents-assets/lang/zh.json index 7b4c2f584e..a068e52b05 100644 --- a/plugins/controlled-documents-assets/lang/zh.json +++ b/plugins/controlled-documents-assets/lang/zh.json @@ -253,6 +253,7 @@ "Name": "名称", "DraftRevision": "草稿修订", "CreateNewDraft": "创建新版本草稿", + "RestoreDraft": "恢复草稿", "ChangeSeverity": "更改严重性", "Reference": "参考", "History": "历史", @@ -308,7 +309,10 @@ "MakeDocumentObsoleteDialog": "标记 {count, plural, one {文档为过时} other {文档为过时}}", "MakeDocumentObsoleteConfirm": "您确定要将以下文档标记为过时吗:{titles}?", - "LatestVersionHint": "最新" + "LatestVersionHint": "最新", + + "CannotDeleteFolder": "无法删除文件夹", + "CannotDeleteFolderHint": "请在删除文件夹之前将所有子文档移动到其他位置。" }, "controlledDocStates": { "Empty": "", diff --git a/plugins/controlled-documents-resources/src/components/EditDocPanel.svelte b/plugins/controlled-documents-resources/src/components/EditDocPanel.svelte index e11c2c176f..df95feb8f9 100644 --- a/plugins/controlled-documents-resources/src/components/EditDocPanel.svelte +++ b/plugins/controlled-documents-resources/src/components/EditDocPanel.svelte @@ -13,6 +13,13 @@ // limitations under the License. --> -{#if $configurationStore.has(trackerId)} +{#if $pluginConfigurationStore.has(trackerId)}
diff --git a/plugins/workbench-resources/src/workbench.ts b/plugins/workbench-resources/src/workbench.ts index 86bdb6c00b..db145d4452 100644 --- a/plugins/workbench-resources/src/workbench.ts +++ b/plugins/workbench-resources/src/workbench.ts @@ -12,36 +12,37 @@ // See the License for the specific language governing permissions and // limitations under the License. // -import { derived, get, writable } from 'svelte/store' import core, { type Class, concatLink, type Doc, - getCurrentAccount, - type Ref, generateId, - reduceCalls + getCurrentAccount, + reduceCalls, + type Ref } from '@hcengineering/core' -import { type Application, workbenchId, type WorkbenchTab } from '@hcengineering/workbench' +import notification, { notificationId } from '@hcengineering/notification' +import { type Asset, getMetadata, getResource, type IntlString, setMetadata, translate } from '@hcengineering/platform' +import presentation, { configurationStore, getClient } from '@hcengineering/presentation' import { - location as locationStore, - locationToUrl, - parseLocation, - type Location, - navigate, + type AnyComponent, getCurrentLocation, languageStore, - type AnyComponent, - locationStorageKeyId + type Location, + locationStorageKeyId, + location as locationStore, + locationToUrl, + navigate, + parseLocation } from '@hcengineering/ui' -import presentation, { getClient } from '@hcengineering/presentation' import view from '@hcengineering/view' -import { type Asset, type IntlString, getMetadata, getResource, translate } from '@hcengineering/platform' import { parseLinkId } from '@hcengineering/view-resources' -import notification, { notificationId } from '@hcengineering/notification' +import { type Application, workbenchId, type WorkbenchTab } from '@hcengineering/workbench' +import { derived, get, writable } from 'svelte/store' -import { locationWorkspaceStore } from './utils' +import setting from '@hcengineering/setting' import workbench from './plugin' +import { locationWorkspaceStore } from './utils' export const tabIdStore = writable | undefined>() export const prevTabIdStore = writable | undefined>() @@ -297,3 +298,8 @@ async function getDefaultTabName (loc: Location): Promise { console.error(err) } } + +configurationStore.subscribe((config) => { + const arePermissionsDisabled = config.get(setting.ids.DisablePermissionsConfiguration)?.enabled ?? false + setMetadata(core.metadata.DisablePermissions, arePermissionsDisabled) +}) diff --git a/server/middleware/src/configuration.ts b/server/middleware/src/configuration.ts index aac9b569dc..bc6f8c7ed7 100644 --- a/server/middleware/src/configuration.ts +++ b/server/middleware/src/configuration.ts @@ -13,16 +13,11 @@ // limitations under the License. // -import core, { +import { AccountRole, - Class, Doc, - DocumentQuery, DOMAIN_CONFIGURATION, - FindOptions, - FindResult, MeasureContext, - Ref, Tx, TxCUD, TxProcessor, @@ -68,20 +63,4 @@ export class ConfigurationMiddleware extends BaseMiddleware implements Middlewar } return this.provideTx(ctx, txes) } - - findAll( - ctx: MeasureContext, - _class: Ref>, - query: DocumentQuery, - options?: FindOptions - ): Promise> { - const domain = this.context.hierarchy.getDomain(_class) - if (this.targetDomains.includes(domain)) { - const account = ctx.contextData.account - if (account.role !== AccountRole.Owner && account._id !== core.account.System && ctx.contextData.admin !== true) { - throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) - } - } - return this.provideFindAll(ctx, _class, query, options) - } }