From fbd18da122a41174b6c1285956fec6ab21f3d457 Mon Sep 17 00:00:00 2001 From: Artem Savchenko Date: Thu, 30 Apr 2026 16:27:55 +0700 Subject: [PATCH 1/5] feat: Configure workspaces during creation Signed-off-by: Artem Savchenko --- common/config/rush/pnpm-lock.yaml | 3 + .../packages/account-client/src/client.ts | 26 +- .../core/packages/account-client/src/types.ts | 7 + foundations/core/packages/core/src/classes.ts | 26 ++ foundations/core/packages/core/src/utils.ts | 12 + models/all/src/index.ts | 7 + packages/presentation/lang/cs.json | 3 +- packages/presentation/lang/de.json | 3 +- packages/presentation/lang/en.json | 3 +- packages/presentation/lang/es.json | 3 +- packages/presentation/lang/fr.json | 3 +- packages/presentation/lang/it.json | 3 +- packages/presentation/lang/ja.json | 3 +- packages/presentation/lang/pt-br.json | 3 +- packages/presentation/lang/pt.json | 3 +- packages/presentation/lang/ru.json | 3 +- packages/presentation/lang/tr.json | 3 +- packages/presentation/lang/zh.json | 3 +- .../components/PluginConfigurationCard.svelte | 220 ++++++++++++++ packages/presentation/src/index.ts | 1 + packages/presentation/src/plugin.ts | 3 +- plugins/login-assets/lang/cs.json | 12 +- plugins/login-assets/lang/de.json | 12 +- plugins/login-assets/lang/en.json | 12 +- plugins/login-assets/lang/es.json | 12 +- plugins/login-assets/lang/fr.json | 12 +- plugins/login-assets/lang/it.json | 12 +- plugins/login-assets/lang/ja.json | 12 +- plugins/login-assets/lang/pt-br.json | 12 +- plugins/login-assets/lang/pt.json | 12 +- plugins/login-assets/lang/ru.json | 12 +- plugins/login-assets/lang/tr.json | 12 +- plugins/login-assets/lang/zh.json | 12 +- .../src/components/CreateWorkspaceForm.svelte | 118 +++++--- .../src/components/LoginApp.svelte | 2 + .../WorkspaceConfigurationStep.svelte | 216 ++++++++++++++ plugins/login-resources/src/plugin.ts | 12 +- plugins/login-resources/src/utils.ts | 28 +- .../src/components/Configure.svelte | 64 ++-- pods/account/package.json | 1 + pods/account/src/__start.ts | 8 +- server/account-service/src/index.ts | 13 +- .../defaultPluginConfigurations.test.ts | 273 ++++++++++++++++++ .../src/collections/postgres/migrations.ts | 17 +- .../src/collections/postgres/postgres.ts | 1 + .../src/defaultPluginConfigurations.ts | 139 +++++++++ server/account/src/index.ts | 1 + server/account/src/operations.ts | 48 ++- server/account/src/serviceOperations.ts | 1 + server/account/src/types.ts | 3 + server/account/src/utils.ts | 7 +- .../src/__tests__/configuration.test.ts | 161 +++++++++++ server/workspace-service/src/configuration.ts | 55 ++++ server/workspace-service/src/ws-operations.ts | 51 ++-- .../sanity/tests/model/left-side-menu-page.ts | 4 + .../tests/model/select-workspace-page.ts | 41 +++ tests/sanity/tests/workspace/create.spec.ts | 41 +++ 57 files changed, 1643 insertions(+), 147 deletions(-) create mode 100644 packages/presentation/src/components/PluginConfigurationCard.svelte create mode 100644 plugins/login-resources/src/components/WorkspaceConfigurationStep.svelte create mode 100644 server/account/src/__tests__/defaultPluginConfigurations.test.ts create mode 100644 server/account/src/defaultPluginConfigurations.ts create mode 100644 server/workspace-service/src/__tests__/configuration.test.ts create mode 100644 server/workspace-service/src/configuration.ts diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 5f1981eebd5..b45bc5420be 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -30140,6 +30140,9 @@ importers: '@hcengineering/core': specifier: workspace:^0.7.26 version: link:../../foundations/core/packages/core + '@hcengineering/model-all': + specifier: workspace:^0.7.0 + version: link:../../models/all '@hcengineering/platform': specifier: workspace:^0.7.20 version: link:../../foundations/core/packages/platform diff --git a/foundations/core/packages/account-client/src/client.ts b/foundations/core/packages/account-client/src/client.ts index 1a8e6ea4308..62098aaccbc 100644 --- a/foundations/core/packages/account-client/src/client.ts +++ b/foundations/core/packages/account-client/src/client.ts @@ -23,6 +23,7 @@ import { type PersonId, type PersonInfo, type PersonUuid, + type PluginConfiguration, type SocialIdType, Version, type UsageStatus, @@ -55,6 +56,7 @@ import type { Subscription, SubscriptionData, UserProfile, + WorkspaceConfiguration, WorkspaceLoginInfo, WorkspaceOperation } from './types' @@ -134,7 +136,12 @@ export interface AccountClient { getWorkspacesInfo: (workspaces: WorkspaceUuid[]) => Promise updateLastVisit: (workspaces: WorkspaceUuid[]) => Promise getRegionInfo: () => Promise - createWorkspace: (name: string, region?: string) => Promise + createWorkspace: ( + name: string, + region?: string, + configuration?: WorkspaceConfiguration + ) => Promise + getDefaultPluginConfigurations: () => Promise[] | null> signUpOtp: (email: string, first: string, last: string) => Promise /** * Deprecated. Only to be used for dev setups without mail service. @@ -668,10 +675,23 @@ class AccountClientImpl implements AccountClient { return await this.rpc(request) } - async createWorkspace (workspaceName: string, region?: string): Promise { + async createWorkspace ( + workspaceName: string, + region?: string, + configuration?: WorkspaceConfiguration + ): Promise { const request = { method: 'createWorkspace' as const, - params: { workspaceName, region } + params: { workspaceName, region, configuration } + } + + return await this.rpc(request) + } + + async getDefaultPluginConfigurations (): Promise[] | null> { + const request = { + method: 'getDefaultPluginConfigurations' as const, + params: {} } return await this.rpc(request) diff --git a/foundations/core/packages/account-client/src/types.ts b/foundations/core/packages/account-client/src/types.ts index c9f791f3c21..868453c485a 100644 --- a/foundations/core/packages/account-client/src/types.ts +++ b/foundations/core/packages/account-client/src/types.ts @@ -14,6 +14,8 @@ import { IntegrationKind } from '@hcengineering/core' +export type { WorkspaceConfiguration } from '@hcengineering/core' + export interface LoginInfo { account: AccountUuid name?: string @@ -99,6 +101,11 @@ export interface RegionInfo { export type WorkspaceOperation = 'create' | 'upgrade' | 'all' | 'all+backup' +// `WorkspaceConfiguration` lives in `@hcengineering/core` so that `WorkspaceInfo` +// can carry it across the wire to non-account services (workspace-service). +// It is re-exported from this module above for callers who prefer the +// account-client surface. + export interface MailboxOptions { availableDomains: string[] minNameLength: number diff --git a/foundations/core/packages/core/src/classes.ts b/foundations/core/packages/core/src/classes.ts index dc242de9281..2e2f1af1131 100644 --- a/foundations/core/packages/core/src/classes.ts +++ b/foundations/core/packages/core/src/classes.ts @@ -898,6 +898,29 @@ export type WorkspaceUpdateEvent = | 'delete-started' | 'delete-done' +/** + * Initial-state configuration captured at workspace creation: which apps to + * disable on first run and whether to populate with demo content. Lives on + * `WorkspaceInfo.pendingConfiguration` until consumed by workspace-service + * after model init, then cleared back to `null`. + * + * @public + */ +export interface WorkspaceConfiguration { + /** + * Whether to run the workspace init script (sample projects and other demo content). + * Defaults to `true` on the server side to preserve legacy behavior. + */ + withDemoContent?: boolean + + /** + * List of `pluginId`s to mark as `enabled: false` in the new workspace's + * `core.class.PluginConfiguration` documents right after model initialization. + * Only non-system, non-hidden plugins are honored; unknown ids are ignored. + */ + disabledPlugins?: Plugin[] +} + export interface WorkspaceInfo { uuid: WorkspaceUuid dataId?: WorkspaceDataId // Old workspace identifier. E.g. Database name in Mongo, bucket in R2, etc. @@ -911,6 +934,9 @@ export interface WorkspaceInfo { allowReadOnlyGuest?: boolean // Should always be set for NEW workspaces allowGuestSignUp?: boolean // Should always be set for NEW workspaces passwordAgingRule?: number // in days + // Initial-state configuration set by the user at workspace creation. Read once + // by workspace-service after model init, then cleared back to `null`. + pendingConfiguration?: WorkspaceConfiguration | null } export interface BackupStatus { diff --git a/foundations/core/packages/core/src/utils.ts b/foundations/core/packages/core/src/utils.ts index 7f0fd164f1f..c66b33fc7ab 100644 --- a/foundations/core/packages/core/src/utils.ts +++ b/foundations/core/packages/core/src/utils.ts @@ -808,6 +808,18 @@ export function getBranding (brandings: BrandingMap, key: string | undefined): B return Object.values(brandings).find((branding) => branding.key === key) ?? null } +/** + * Returns the full set of `PluginConfiguration` documents that the given model + * would create in a freshly-initialized workspace. + * + * @public + */ +export function getDefaultPluginConfigurations (systemTx: Tx[]): PluginConfiguration[] { + const configs = new Map, PluginConfiguration>() + fillConfiguration(systemTx, configs) + return Array.from(configs.values()) +} + export function fillConfiguration (systemTx: Tx[], configs: Map, PluginConfiguration>): void { for (const t of systemTx) { if (t._class === core.class.TxCreateDoc) { diff --git a/models/all/src/index.ts b/models/all/src/index.ts index e41b28a9da4..41d33c3ebf5 100644 --- a/models/all/src/index.ts +++ b/models/all/src/index.ts @@ -246,6 +246,7 @@ export default function buildModel (): Builder { description: telegram.string.ConfigDescription, enabled: true, beta: true, + icon: contact.icon.Telegram, classFilter: defaultFilter } ], @@ -269,6 +270,7 @@ export default function buildModel (): Builder { description: gmail.string.ConfigDescription, enabled: true, beta: true, + icon: contact.icon.Email, classFilter: defaultFilter } ], @@ -420,6 +422,7 @@ export default function buildModel (): Builder { description: documents.string.ConfigDescription, enabled: false, beta: false, + icon: documents.icon.DocumentApplication, classFilter: defaultFilter } ], @@ -442,6 +445,7 @@ export default function buildModel (): Builder { description: trainings.string.ConfigDescription, enabled: false, beta: false, + icon: trainings.icon.TrainingApplication, classFilter: defaultFilter } ], @@ -453,6 +457,7 @@ export default function buildModel (): Builder { description: products.string.ConfigDescription, enabled: false, beta: false, + icon: products.icon.ProductsApplication, classFilter: defaultFilter } ], @@ -464,6 +469,7 @@ export default function buildModel (): Builder { description: testManagement.string.ConfigDescription, enabled: true, beta: true, + icon: testManagement.icon.TestManagementApplication, classFilter: defaultFilter } ], @@ -475,6 +481,7 @@ export default function buildModel (): Builder { description: survey.string.ConfigDescription, enabled: false, beta: true, + icon: survey.icon.Survey, classFilter: defaultFilter } ], diff --git a/packages/presentation/lang/cs.json b/packages/presentation/lang/cs.json index 83ff9d63001..ce569b48110 100644 --- a/packages/presentation/lang/cs.json +++ b/packages/presentation/lang/cs.json @@ -56,7 +56,8 @@ "LineTool": "Čára", "RectangleTool": "Obdélník", "EllipseTool": "Elipsa", - "PaletteManagementMenu": "Spravovat barevné předvolby" + "PaletteManagementMenu": "Spravovat barevné předvolby", + "BetaVersion": "Beta verze" }, "status": { "FileTooLarge": "Soubor je příliš velký" diff --git a/packages/presentation/lang/de.json b/packages/presentation/lang/de.json index d9ea8df19fc..742489df916 100644 --- a/packages/presentation/lang/de.json +++ b/packages/presentation/lang/de.json @@ -56,7 +56,8 @@ "LineTool": "Linie", "RectangleTool": "Rechteck", "EllipseTool": "Ellipse", - "PaletteManagementMenu": "Farbpresets verwalten" + "PaletteManagementMenu": "Farbpresets verwalten", + "BetaVersion": "Beta-Version" }, "status": { "FileTooLarge": "Datei zu groß" diff --git a/packages/presentation/lang/en.json b/packages/presentation/lang/en.json index 5bc374d2afe..2bbb1fb4317 100644 --- a/packages/presentation/lang/en.json +++ b/packages/presentation/lang/en.json @@ -56,7 +56,8 @@ "LineTool": "Line", "RectangleTool": "Rectangle", "EllipseTool": "Ellipse", - "PaletteManagementMenu": "Manage color presets" + "PaletteManagementMenu": "Manage color presets", + "BetaVersion": "Beta version" }, "status": { "FileTooLarge": "File too large" diff --git a/packages/presentation/lang/es.json b/packages/presentation/lang/es.json index 9381530fae9..ddf2d045524 100644 --- a/packages/presentation/lang/es.json +++ b/packages/presentation/lang/es.json @@ -56,7 +56,8 @@ "LineTool": "Línea", "RectangleTool": "Rectángulo", "EllipseTool": "Elipse", - "PaletteManagementMenu": "Gestionar preajustes de color" + "PaletteManagementMenu": "Gestionar preajustes de color", + "BetaVersion": "Versión beta" }, "status": { "FileTooLarge": "Archivo demasiado grande" diff --git a/packages/presentation/lang/fr.json b/packages/presentation/lang/fr.json index ca016bba899..c3c2188f455 100644 --- a/packages/presentation/lang/fr.json +++ b/packages/presentation/lang/fr.json @@ -56,7 +56,8 @@ "LineTool": "Ligne", "RectangleTool": "Rectangle", "EllipseTool": "Ellipse", - "PaletteManagementMenu": "Gérer les préréglages de couleur" + "PaletteManagementMenu": "Gérer les préréglages de couleur", + "BetaVersion": "Version bêta" }, "status": { "FileTooLarge": "Fichier trop volumineux" diff --git a/packages/presentation/lang/it.json b/packages/presentation/lang/it.json index 8331b58e276..6a54c2fbc4d 100644 --- a/packages/presentation/lang/it.json +++ b/packages/presentation/lang/it.json @@ -56,7 +56,8 @@ "LineTool": "Linea", "RectangleTool": "Rettangolo", "EllipseTool": "Ellisse", - "PaletteManagementMenu": "Gestisci i preset di colore" + "PaletteManagementMenu": "Gestisci i preset di colore", + "BetaVersion": "Versione beta" }, "status": { "FileTooLarge": "File troppo grande" diff --git a/packages/presentation/lang/ja.json b/packages/presentation/lang/ja.json index 55de4e0de76..fbedfaadb14 100644 --- a/packages/presentation/lang/ja.json +++ b/packages/presentation/lang/ja.json @@ -56,7 +56,8 @@ "LineTool": "直線", "RectangleTool": "長方形", "EllipseTool": "楕円", - "PaletteManagementMenu": "カラープリセットを管理" + "PaletteManagementMenu": "カラープリセットを管理", + "BetaVersion": "ベータ版" }, "status": { "FileTooLarge": "ファイルサイズが大きすぎます" diff --git a/packages/presentation/lang/pt-br.json b/packages/presentation/lang/pt-br.json index 3769f744a95..d67a79afb61 100644 --- a/packages/presentation/lang/pt-br.json +++ b/packages/presentation/lang/pt-br.json @@ -56,7 +56,8 @@ "LineTool": "Linha", "RectangleTool": "Retângulo", "EllipseTool": "Elipse", - "PaletteManagementMenu": "Gerenciar predefinições de cor" + "PaletteManagementMenu": "Gerenciar predefinições de cor", + "BetaVersion": "Versão beta" }, "status": { "FileTooLarge": "Arquivo muito grande" diff --git a/packages/presentation/lang/pt.json b/packages/presentation/lang/pt.json index 3fbb5c8d633..38a79eece40 100644 --- a/packages/presentation/lang/pt.json +++ b/packages/presentation/lang/pt.json @@ -56,7 +56,8 @@ "LineTool": "Linha", "RectangleTool": "Retângulo", "EllipseTool": "Elipse", - "PaletteManagementMenu": "Gerenciar predefinições de cor" + "PaletteManagementMenu": "Gerenciar predefinições de cor", + "BetaVersion": "Versão beta" }, "status": { "FileTooLarge": "Ficheiro demasiado grande" diff --git a/packages/presentation/lang/ru.json b/packages/presentation/lang/ru.json index 5bda323ec9d..eb88f8bc23e 100644 --- a/packages/presentation/lang/ru.json +++ b/packages/presentation/lang/ru.json @@ -56,7 +56,8 @@ "LineTool": "Линия", "RectangleTool": "Прямоугольник", "EllipseTool": "Эллипс", - "PaletteManagementMenu": "Управление цветовыми пресетами" + "PaletteManagementMenu": "Управление цветовыми пресетами", + "BetaVersion": "Бета-версия" }, "status": { "FileTooLarge": "Файл слишком большой" diff --git a/packages/presentation/lang/tr.json b/packages/presentation/lang/tr.json index 4fd772345ea..8dd146aafbd 100644 --- a/packages/presentation/lang/tr.json +++ b/packages/presentation/lang/tr.json @@ -56,7 +56,8 @@ "LineTool": "Çizgi", "RectangleTool": "Dikdörtgen", "EllipseTool": "Elips", - "PaletteManagementMenu": "Renk önayarlarını yönet" + "PaletteManagementMenu": "Renk önayarlarını yönet", + "BetaVersion": "Beta sürümü" }, "status": { "FileTooLarge": "Dosya çok büyük" diff --git a/packages/presentation/lang/zh.json b/packages/presentation/lang/zh.json index 6b110070861..d31e4e02497 100644 --- a/packages/presentation/lang/zh.json +++ b/packages/presentation/lang/zh.json @@ -56,7 +56,8 @@ "LineTool": "直线", "RectangleTool": "矩形", "EllipseTool": "椭圆", - "PaletteManagementMenu": "管理颜色预设" + "PaletteManagementMenu": "管理颜色预设", + "BetaVersion": "Beta 版本" }, "status": { "FileTooLarge": "文件太大" diff --git a/packages/presentation/src/components/PluginConfigurationCard.svelte b/packages/presentation/src/components/PluginConfigurationCard.svelte new file mode 100644 index 00000000000..3e256e71822 --- /dev/null +++ b/packages/presentation/src/components/PluginConfigurationCard.svelte @@ -0,0 +1,220 @@ + + + +
+
+ + + + + + + {#if suffix !== undefined && suffix !== ''} + ({suffix}) + {/if} + {#if compact && description !== undefined} + + {/if} + {#if beta} + β + {/if} + + + { + dispatch('toggle', { enabled: e.detail === true }) + }} + /> +
+ {#if !compact && description !== undefined} +
+
+ {/if} +
+ + diff --git a/packages/presentation/src/index.ts b/packages/presentation/src/index.ts index ba646872468..a10eb625916 100644 --- a/packages/presentation/src/index.ts +++ b/packages/presentation/src/index.ts @@ -29,6 +29,7 @@ export { default as MessageViewer } from './components/MessageViewer.svelte' export { default as ObjectPopup } from './components/ObjectPopup.svelte' export { default as DocPopup } from './components/DocPopup.svelte' export { default as PDFViewer } from './components/PDFViewer.svelte' +export { default as PluginConfigurationCard } from './components/PluginConfigurationCard.svelte' export { default as SpaceCreateCard } from './components/SpaceCreateCard.svelte' export { default as SpaceMultiBoxList } from './components/SpaceMultiBoxList.svelte' export { default as SpaceSelect } from './components/SpaceSelect.svelte' diff --git a/packages/presentation/src/plugin.ts b/packages/presentation/src/plugin.ts index 47c57d9d837..bf48b1d4adf 100644 --- a/packages/presentation/src/plugin.ts +++ b/packages/presentation/src/plugin.ts @@ -158,7 +158,8 @@ export default plugin(presentationId, { LineTool: '' as IntlString, RectangleTool: '' as IntlString, EllipseTool: '' as IntlString, - PaletteManagementMenu: '' as IntlString + PaletteManagementMenu: '' as IntlString, + BetaVersion: '' as IntlString }, extension: { FilePreviewExtension: '' as ComponentExtensionId, diff --git a/plugins/login-assets/lang/cs.json b/plugins/login-assets/lang/cs.json index c9279bbc501..f2e2aa2009c 100644 --- a/plugins/login-assets/lang/cs.json +++ b/plugins/login-assets/lang/cs.json @@ -101,6 +101,16 @@ "SSOPasswordDescription": "Váš účet používá externí přihlášení. Nastavte si heslo prostřednictvím e-mailové potvrzení.", "SendSetupLink": "Odeslat odkaz na nastavení", "SSOPasswordEmailSent": "Zkontrolujte svůj e-mail, zda neobsahuje odkaz pro nastavení hesla.", - "SSONoEmailLinked": "K vašemu účtu není přidružena žádná e-mailová adresa. Nejprve ji přidejte v Nastavení účtu → Spravovat identity." + "SSONoEmailLinked": "K vašemu účtu není přidružena žádná e-mailová adresa. Nejprve ji přidejte v Nastavení účtu → Spravovat identity.", + "CustomizeWorkspace": "Přizpůsobit pracovní prostor…", + "InitialContent": "Počáteční obsah", + "CreateSampleProjects": "Vytvořit ukázkové projekty a demo obsah", + "CreateSampleProjectsDesc": "Přidáme několik ukázkových projektů, dokumentů a úkolů, abyste mohli rychle začít. Můžete je kdykoli smazat.", + "Modules": "Moduly", + "ModulesDesc": "Vyberte, které aplikace budou v tomto pracovním prostoru aktivní. Můžete to později změnit v nastavení pracovního prostoru.", + "ModuleListUnavailable": "Seznam modulů ještě není k dispozici — budou použity výchozí hodnoty. Moduly můžete upravit v nastavení pracovního prostoru po vytvoření.", + "ModuleEnable": "Povolit", + "ModuleDisable": "Zakázat", + "BackToCreate": "Zpět" } } diff --git a/plugins/login-assets/lang/de.json b/plugins/login-assets/lang/de.json index 76bc7d35611..40fbdef4b77 100644 --- a/plugins/login-assets/lang/de.json +++ b/plugins/login-assets/lang/de.json @@ -101,6 +101,16 @@ "SSOPasswordDescription": "Ihr Konto verwendet externe Anmeldung. Richten Sie ein Passwort über die E-Mail-Bestätigung ein.", "SendSetupLink": "Setup-Link senden", "SSOPasswordEmailSent": "Überprüfen Sie Ihre E-Mail auf einen Link zum Festlegen des Passworts.", - "SSONoEmailLinked": "Keine E-Mail-Adresse mit Ihrem Konto verknüpft. Fügen Sie eine unter Kontoeinstellungen → Identitäten verwalten hinzu." + "SSONoEmailLinked": "Keine E-Mail-Adresse mit Ihrem Konto verknüpft. Fügen Sie eine unter Kontoeinstellungen → Identitäten verwalten hinzu.", + "CustomizeWorkspace": "Workspace anpassen…", + "InitialContent": "Anfangsinhalt", + "CreateSampleProjects": "Beispielprojekte und Demo-Inhalte erstellen", + "CreateSampleProjectsDesc": "Wir fügen einige Beispielprojekte, Dokumente und Aufgaben hinzu, damit Sie sofort loslegen können. Sie können sie jederzeit löschen.", + "Modules": "Module", + "ModulesDesc": "Wählen Sie, welche Apps in diesem Workspace aktiv sein sollen. Dies können Sie später in den Workspace-Einstellungen ändern.", + "ModuleListUnavailable": "Modulliste noch nicht verfügbar — Standardwerte werden verwendet. Sie können Module nach der Erstellung in den Workspace-Einstellungen anpassen.", + "ModuleEnable": "Aktivieren", + "ModuleDisable": "Deaktivieren", + "BackToCreate": "Zurück" } } diff --git a/plugins/login-assets/lang/en.json b/plugins/login-assets/lang/en.json index c16dd1c152e..4983384d986 100644 --- a/plugins/login-assets/lang/en.json +++ b/plugins/login-assets/lang/en.json @@ -100,6 +100,16 @@ "TwoFactorAuth": "Two-factor authentication", "EnterTwoFactorCode": "Enter two-factor authentication code", "TwoFactorCode": "Two-factor authentication code", - "Verify": "Verify" + "Verify": "Verify", + "CustomizeWorkspace": "Customize workspace…", + "InitialContent": "Initial content", + "CreateSampleProjects": "Create sample projects and demo content", + "CreateSampleProjectsDesc": "We'll add a few example projects, documents and tasks to help you get started. You can delete them at any time.", + "Modules": "Modules", + "ModulesDesc": "Pick which apps will be active in this workspace. You can change this later in workspace settings.", + "ModuleListUnavailable": "Module list is not available yet — defaults will be used. You can adjust modules in workspace settings after creation.", + "ModuleEnable": "Enable", + "ModuleDisable": "Disable", + "BackToCreate": "Back" } } diff --git a/plugins/login-assets/lang/es.json b/plugins/login-assets/lang/es.json index b337da57b91..be6babeb2bb 100644 --- a/plugins/login-assets/lang/es.json +++ b/plugins/login-assets/lang/es.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Tu cuenta utiliza inicio de sesión externo. Configura una contraseña mediante confirmación por correo electrónico.", "SendSetupLink": "Enviar enlace de configuración", "SSOPasswordEmailSent": "Revisa tu correo electrónico para encontrar un enlace para configurar la contraseña.", - "SSONoEmailLinked": "No hay dirección de correo electrónico vinculada a tu cuenta. Añade una en Configuración de la cuenta → Gestionar identidades primero." + "SSONoEmailLinked": "No hay dirección de correo electrónico vinculada a tu cuenta. Añade una en Configuración de la cuenta → Gestionar identidades primero.", + "CustomizeWorkspace": "Personalizar workspace…", + "InitialContent": "Contenido inicial", + "CreateSampleProjects": "Crear proyectos de ejemplo y contenido de demostración", + "CreateSampleProjectsDesc": "Añadiremos algunos proyectos, documentos y tareas de ejemplo para ayudarte a empezar. Puedes eliminarlos en cualquier momento.", + "Modules": "Módulos", + "ModulesDesc": "Elige qué aplicaciones estarán activas en este workspace. Puedes cambiarlo más tarde en la configuración del workspace.", + "ModuleListUnavailable": "La lista de módulos aún no está disponible — se usarán los valores predeterminados. Puedes ajustar los módulos en la configuración del workspace después de crearlo.", + "ModuleEnable": "Habilitar", + "ModuleDisable": "Deshabilitar", + "BackToCreate": "Atrás" } } diff --git a/plugins/login-assets/lang/fr.json b/plugins/login-assets/lang/fr.json index 24eedf83a8f..7542db5d9dc 100644 --- a/plugins/login-assets/lang/fr.json +++ b/plugins/login-assets/lang/fr.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Votre compte utilise une connexion externe. Définissez un mot de passe via confirmation par e-mail.", "SendSetupLink": "Envoyer le lien de configuration", "SSOPasswordEmailSent": "Vérifiez votre e-mail pour trouver un lien de configuration de mot de passe.", - "SSONoEmailLinked": "Aucune adresse e-mail n'est liée à votre compte. Ajoutez-en une dans Paramètres du compte → Gérer les identités d'abord." + "SSONoEmailLinked": "Aucune adresse e-mail n'est liée à votre compte. Ajoutez-en une dans Paramètres du compte → Gérer les identités d'abord.", + "CustomizeWorkspace": "Personnaliser le workspace…", + "InitialContent": "Contenu initial", + "CreateSampleProjects": "Créer des projets d'exemple et du contenu de démonstration", + "CreateSampleProjectsDesc": "Nous ajouterons quelques projets, documents et tâches d'exemple pour vous aider à démarrer. Vous pourrez les supprimer à tout moment.", + "Modules": "Modules", + "ModulesDesc": "Choisissez quelles applications seront actives dans ce workspace. Vous pourrez le modifier plus tard dans les paramètres du workspace.", + "ModuleListUnavailable": "La liste des modules n'est pas encore disponible — les valeurs par défaut seront utilisées. Vous pourrez ajuster les modules dans les paramètres du workspace après la création.", + "ModuleEnable": "Activer", + "ModuleDisable": "Désactiver", + "BackToCreate": "Retour" } } diff --git a/plugins/login-assets/lang/it.json b/plugins/login-assets/lang/it.json index 4d9468bf4a5..3a966c06f52 100644 --- a/plugins/login-assets/lang/it.json +++ b/plugins/login-assets/lang/it.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Il tuo account utilizza l'accesso esterno. Imposta una password tramite conferma via email.", "SendSetupLink": "Invia link di configurazione", "SSOPasswordEmailSent": "Controlla la tua email per trovare un link per impostare la password.", - "SSONoEmailLinked": "Nessun indirizzo email è collegato al tuo account. Aggiungine uno in Impostazioni account → Gestisci identità prima." + "SSONoEmailLinked": "Nessun indirizzo email è collegato al tuo account. Aggiungine uno in Impostazioni account → Gestisci identità prima.", + "CustomizeWorkspace": "Personalizza workspace…", + "InitialContent": "Contenuto iniziale", + "CreateSampleProjects": "Crea progetti di esempio e contenuto demo", + "CreateSampleProjectsDesc": "Aggiungeremo alcuni progetti, documenti e attività di esempio per aiutarti a iniziare. Puoi eliminarli in qualsiasi momento.", + "Modules": "Moduli", + "ModulesDesc": "Scegli quali applicazioni saranno attive in questo workspace. Puoi modificarlo in seguito nelle impostazioni del workspace.", + "ModuleListUnavailable": "L'elenco dei moduli non è ancora disponibile — verranno utilizzati i valori predefiniti. Puoi regolare i moduli nelle impostazioni del workspace dopo la creazione.", + "ModuleEnable": "Abilita", + "ModuleDisable": "Disabilita", + "BackToCreate": "Indietro" } } diff --git a/plugins/login-assets/lang/ja.json b/plugins/login-assets/lang/ja.json index 06538a51484..2d6f77f65cb 100644 --- a/plugins/login-assets/lang/ja.json +++ b/plugins/login-assets/lang/ja.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "アカウントは外部ログインを使用しています。メール確認でパスワードを設定してください。", "SendSetupLink": "セットアップリンクを送信", "SSOPasswordEmailSent": "パスワードを設定するためのリンクが記載されたメールを確認してください。", - "SSONoEmailLinked": "アカウントにメールアドレスがリンクされていません。まず、アカウント設定 → IDの管理 で追加してください。" + "SSONoEmailLinked": "アカウントにメールアドレスがリンクされていません。まず、アカウント設定 → IDの管理 で追加してください。", + "CustomizeWorkspace": "ワークスペースをカスタマイズ…", + "InitialContent": "初期コンテンツ", + "CreateSampleProjects": "サンプルプロジェクトとデモコンテンツを作成", + "CreateSampleProjectsDesc": "始めやすいように、サンプルのプロジェクト、ドキュメント、タスクをいくつか追加します。いつでも削除できます。", + "Modules": "モジュール", + "ModulesDesc": "このワークスペースで有効にするアプリを選択してください。ワークスペース設定から後で変更できます。", + "ModuleListUnavailable": "モジュール一覧はまだ利用できません — デフォルトが使用されます。作成後にワークスペース設定でモジュールを調整できます。", + "ModuleEnable": "有効にする", + "ModuleDisable": "無効にする", + "BackToCreate": "戻る" } } diff --git a/plugins/login-assets/lang/pt-br.json b/plugins/login-assets/lang/pt-br.json index 03a2be87bf2..a6920033be3 100644 --- a/plugins/login-assets/lang/pt-br.json +++ b/plugins/login-assets/lang/pt-br.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Sua conta usa login externo. Defina uma senha através da confirmação por e-mail.", "SendSetupLink": "Enviar link de configuração", "SSOPasswordEmailSent": "Verifique seu e-mail para encontrar o link de configuração da senha.", - "SSONoEmailLinked": "Nenhum endereço de e-mail está vinculado à sua conta. Adicione um em Configurações da Conta → Gerenciar Identidades primeiro." + "SSONoEmailLinked": "Nenhum endereço de e-mail está vinculado à sua conta. Adicione um em Configurações da Conta → Gerenciar Identidades primeiro.", + "CustomizeWorkspace": "Personalizar workspace…", + "InitialContent": "Conteúdo inicial", + "CreateSampleProjects": "Criar projetos de exemplo e conteúdo demo", + "CreateSampleProjectsDesc": "Adicionaremos alguns projetos, documentos e tarefas de exemplo para ajudar você a começar. Você pode excluí-los a qualquer momento.", + "Modules": "Módulos", + "ModulesDesc": "Escolha quais aplicativos estarão ativos neste workspace. Você pode alterar isso depois nas configurações do workspace.", + "ModuleListUnavailable": "A lista de módulos ainda não está disponível — os padrões serão usados. Você pode ajustar os módulos nas configurações do workspace após a criação.", + "ModuleEnable": "Ativar", + "ModuleDisable": "Desativar", + "BackToCreate": "Voltar" } } diff --git a/plugins/login-assets/lang/pt.json b/plugins/login-assets/lang/pt.json index 14e30dbdc1c..b3ec1cfa209 100644 --- a/plugins/login-assets/lang/pt.json +++ b/plugins/login-assets/lang/pt.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Sua conta usa login externo. Defina uma senha através da confirmação por e-mail.", "SendSetupLink": "Enviar link de configuração", "SSOPasswordEmailSent": "Verifique seu e-mail para encontrar o link de configuração da senha.", - "SSONoEmailLinked": "Nenhum endereço de e-mail está vinculado à sua conta. Adicione um em Configurações da Conta → Gerenciar Identidades primeiro." + "SSONoEmailLinked": "Nenhum endereço de e-mail está vinculado à sua conta. Adicione um em Configurações da Conta → Gerenciar Identidades primeiro.", + "CustomizeWorkspace": "Personalizar workspace…", + "InitialContent": "Conteúdo inicial", + "CreateSampleProjects": "Criar projetos de exemplo e conteúdo de demonstração", + "CreateSampleProjectsDesc": "Adicionaremos alguns projetos, documentos e tarefas de exemplo para ajudá-lo a começar. Pode excluí-los a qualquer momento.", + "Modules": "Módulos", + "ModulesDesc": "Escolha quais aplicações estarão ativas neste workspace. Pode alterar mais tarde nas configurações do workspace.", + "ModuleListUnavailable": "A lista de módulos ainda não está disponível — serão usados os padrões. Pode ajustar os módulos nas configurações do workspace após a criação.", + "ModuleEnable": "Ativar", + "ModuleDisable": "Desativar", + "BackToCreate": "Voltar" } } diff --git a/plugins/login-assets/lang/ru.json b/plugins/login-assets/lang/ru.json index eaf7bcaf383..312a83a0ced 100644 --- a/plugins/login-assets/lang/ru.json +++ b/plugins/login-assets/lang/ru.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Ваша учетная запись использует внешний вход. Установите пароль через подтверждение по электронной почте.", "SendSetupLink": "Отправить ссылку для настройки", "SSOPasswordEmailSent": "Проверьте свою электронную почту, чтобы найти ссылку для установки пароля.", - "SSONoEmailLinked": "К вашей учетной записи не привязан адрес электронной почты. Сначала добавьте его в Настройки аккаунта → Управление идентификаторами." + "SSONoEmailLinked": "К вашей учетной записи не привязан адрес электронной почты. Сначала добавьте его в Настройки аккаунта → Управление идентификаторами.", + "CustomizeWorkspace": "Настроить workspace…", + "InitialContent": "Начальное содержимое", + "CreateSampleProjects": "Создать примеры проектов и демо-контент", + "CreateSampleProjectsDesc": "Мы добавим несколько примеров проектов, документов и задач, чтобы вам было проще начать. Их можно удалить в любой момент.", + "Modules": "Модули", + "ModulesDesc": "Выберите, какие приложения будут активны в этом workspace. Это можно изменить позже в настройках workspace.", + "ModuleListUnavailable": "Список модулей пока недоступен — будут использованы значения по умолчанию. Модули можно настроить в настройках workspace после создания.", + "ModuleEnable": "Включить", + "ModuleDisable": "Выключить", + "BackToCreate": "Назад" } } diff --git a/plugins/login-assets/lang/tr.json b/plugins/login-assets/lang/tr.json index 5a5e3b25f13..12a6f171372 100644 --- a/plugins/login-assets/lang/tr.json +++ b/plugins/login-assets/lang/tr.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "Hesabınız harici girişi kullanıyor. E-posta onayı ile bir şifre belirleyin.", "SendSetupLink": "Kurulum bağlantısı gönder", "SSOPasswordEmailSent": "Şifrenizi belirlemek için bir bağlantı içeren e-postayı kontrol edin.", - "SSONoEmailLinked": "Hesabınıza bağlı bir e-posta adresi yok. Önce Hesap Ayarları → Kimlikleri Yönet bölümünden bir tane ekleyin." + "SSONoEmailLinked": "Hesabınıza bağlı bir e-posta adresi yok. Önce Hesap Ayarları → Kimlikleri Yönet bölümünden bir tane ekleyin.", + "CustomizeWorkspace": "Çalışma alanını özelleştir…", + "InitialContent": "Başlangıç içeriği", + "CreateSampleProjects": "Örnek projeler ve demo içerik oluştur", + "CreateSampleProjectsDesc": "Başlamanıza yardımcı olmak için birkaç örnek proje, belge ve görev ekleyeceğiz. Dilediğiniz zaman silebilirsiniz.", + "Modules": "Modüller", + "ModulesDesc": "Bu çalışma alanında hangi uygulamaların aktif olacağını seçin. Bunu daha sonra çalışma alanı ayarlarından değiştirebilirsiniz.", + "ModuleListUnavailable": "Modül listesi henüz mevcut değil — varsayılanlar kullanılacak. Oluşturduktan sonra çalışma alanı ayarlarından modülleri ayarlayabilirsiniz.", + "ModuleEnable": "Etkinleştir", + "ModuleDisable": "Devre dışı bırak", + "BackToCreate": "Geri" } } diff --git a/plugins/login-assets/lang/zh.json b/plugins/login-assets/lang/zh.json index 85948995087..a8d84c47edb 100644 --- a/plugins/login-assets/lang/zh.json +++ b/plugins/login-assets/lang/zh.json @@ -100,6 +100,16 @@ "SSOPasswordDescription": "您的账户使用外部登录。请通过电子邮件确认设置密码。", "SendSetupLink": "发送设置链接", "SSOPasswordEmailSent": "请检查您的电子邮件,获取设置密码的链接。", - "SSONoEmailLinked": "您的账户没有关联的电子邮件地址。请先在账户设置 → 管理身份中添加。" + "SSONoEmailLinked": "您的账户没有关联的电子邮件地址。请先在账户设置 → 管理身份中添加。", + "CustomizeWorkspace": "自定义工作区…", + "InitialContent": "初始内容", + "CreateSampleProjects": "创建示例项目和演示内容", + "CreateSampleProjectsDesc": "我们将添加一些示例项目、文档和任务以帮助您快速开始。您可以随时删除它们。", + "Modules": "模块", + "ModulesDesc": "选择此工作区中要启用的应用。您可以稍后在工作区设置中更改。", + "ModuleListUnavailable": "模块列表尚不可用 — 将使用默认值。创建后可在工作区设置中调整模块。", + "ModuleEnable": "启用", + "ModuleDisable": "禁用", + "BackToCreate": "返回" } } diff --git a/plugins/login-resources/src/components/CreateWorkspaceForm.svelte b/plugins/login-resources/src/components/CreateWorkspaceForm.svelte index c7d3a74a9e5..b6026a0bd93 100644 --- a/plugins/login-resources/src/components/CreateWorkspaceForm.svelte +++ b/plugins/login-resources/src/components/CreateWorkspaceForm.svelte @@ -14,7 +14,7 @@ // limitations under the License. --> -
{ - goTo('selectWorkspace') +{#if customizing} + +{:else} + { + goTo('selectWorkspace') + } } - } - ]} -> - - {#if regions.length > 1} -
- it.region === selectedRegion)?.name} - items={regions.map((it) => ({ id: it.region, label: getEmbeddedLabel(it.name) }))} - on:selected={(it) => { - selectedRegion = it.detail - }} - /> -
- {/if} -
- + ]} + > + + {#if regions.length > 1} +
+ it.region === selectedRegion)?.name} + items={regions.map((it) => ({ id: it.region, label: getEmbeddedLabel(it.name) }))} + on:selected={(it) => { + selectedRegion = it.detail + }} + /> +
+ {/if} +
+ +{/if} diff --git a/plugins/login-resources/src/components/LoginApp.svelte b/plugins/login-resources/src/components/LoginApp.svelte index 2af6f572bd3..6e7d3f7ee4b 100644 --- a/plugins/login-resources/src/components/LoginApp.svelte +++ b/plugins/login-resources/src/components/LoginApp.svelte @@ -20,6 +20,7 @@ Location, Popup, Scroller, + TooltipInstance, deviceOptionsStore as deviceInfo, fetchMetadataLocalStorage, getCurrentLocation, @@ -192,6 +193,7 @@ + {/if} diff --git a/plugins/login-resources/src/components/WorkspaceConfigurationStep.svelte b/plugins/login-resources/src/components/WorkspaceConfigurationStep.svelte new file mode 100644 index 00000000000..634c8c97a65 --- /dev/null +++ b/plugins/login-resources/src/components/WorkspaceConfigurationStep.svelte @@ -0,0 +1,216 @@ + + + +
+ +
+
+ +
+
+ +
+

+

+ +
+ +
+

+

+ {#if modules === undefined} +
+
+ {:else if modules === null} +
+
+ {:else} +
+
+
+ {#each modules as module} + { + setEnabled(module.pluginId, e.detail.enabled) + }} + /> + {/each} +
+ {/if} +
+
+ + +
+ + diff --git a/plugins/login-resources/src/plugin.ts b/plugins/login-resources/src/plugin.ts index 54872176f4c..5ef4d737f87 100644 --- a/plugins/login-resources/src/plugin.ts +++ b/plugins/login-resources/src/plugin.ts @@ -83,6 +83,16 @@ export default mergeIds(loginId, login, { LogInAndJoin: '' as IntlString, SignUpAndJoin: '' as IntlString, CreateNewAccount: '' as IntlString, - SignedInAs: '' as IntlString<{ name: string }> + SignedInAs: '' as IntlString<{ name: string }>, + CustomizeWorkspace: '' as IntlString, + InitialContent: '' as IntlString, + CreateSampleProjects: '' as IntlString, + CreateSampleProjectsDesc: '' as IntlString, + Modules: '' as IntlString, + ModulesDesc: '' as IntlString, + ModuleListUnavailable: '' as IntlString, + ModuleEnable: '' as IntlString, + ModuleDisable: '' as IntlString, + BackToCreate: '' as IntlString } }) diff --git a/plugins/login-resources/src/utils.ts b/plugins/login-resources/src/utils.ts index 57abff5b844..2a4cc00c292 100644 --- a/plugins/login-resources/src/utils.ts +++ b/plugins/login-resources/src/utils.ts @@ -18,6 +18,7 @@ import type { LoginInfo, OtpInfo, RegionInfo, + WorkspaceConfiguration, WorkspaceLoginInfo, WorkspaceInviteInfo, ProviderInfo, @@ -32,7 +33,9 @@ import { concatLink, getCurrentAccount, type AccountUuid, + type Data, type Person, + type PluginConfiguration, type WorkspaceUuid, type WorkspaceInfoWithStatus, type WorkspaceUserOperation @@ -177,7 +180,8 @@ export async function signUpOtp (email: string, first: string, last: string): Pr export async function createWorkspace ( workspaceName: string, - region?: string + region?: string, + configuration?: WorkspaceConfiguration ): Promise<[Status, WorkspaceLoginInfo | null]> { const token = getMetadata(presentation.metadata.Token) if (token == null) { @@ -190,7 +194,7 @@ export async function createWorkspace ( } try { - const workspaceLoginInfo = await getAccountClient(token).createWorkspace(workspaceName, region) + const workspaceLoginInfo = await getAccountClient(token).createWorkspace(workspaceName, region, configuration) Analytics.handleEvent(LoginEvents.CreateWorkspace, { name: workspaceName, ok: true }) @@ -411,6 +415,26 @@ export async function getRegionInfo (doNavigate: boolean = true): Promise> | null> { + const token = getMetadata(presentation.metadata.Token) + try { + return await getAccountClient(token ?? undefined).getDefaultPluginConfigurations() + } catch (err: any) { + if (err instanceof PlatformError) { + await handleStatusError('Get default plugin configurations error', err.status) + } else { + Analytics.handleError(err) + } + return null + } +} + export async function selectWorkspace ( workspaceUrl: string, token?: string | null | undefined diff --git a/plugins/setting-resources/src/components/Configure.svelte b/plugins/setting-resources/src/components/Configure.svelte index 8e03c0e6bf6..478ffa485ac 100644 --- a/plugins/setting-resources/src/components/Configure.svelte +++ b/plugins/setting-resources/src/components/Configure.svelte @@ -20,10 +20,10 @@ pluginConfigurationStore, hasResource, isDisabled, - isAdminUser + PluginConfigurationCard } from '@hcengineering/presentation' import ratingPlugin, { getRaiting, type PersonRating } from '@hcengineering/rating' - import { Breadcrumb, Button, Header, Icon, IconInfo, Label, Scroller } from '@hcengineering/ui' + import { Breadcrumb, Header, Label, Scroller } from '@hcengineering/ui' import setting from '../plugin' const client = getClient() @@ -57,41 +57,20 @@