From efc3583376abf2e88eee77e067420f30fada53bb Mon Sep 17 00:00:00 2001 From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> Date: Fri, 1 Jul 2022 21:22:58 +0600 Subject: [PATCH] Owners (#2183) Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> --- changelog.md | 3 +- dev/tool/src/index.ts | 9 ++ models/automation/src/index.ts | 5 +- models/contact/src/index.ts | 3 +- models/contact/src/migration.ts | 35 ++++- models/core/src/security.ts | 3 +- models/demo/src/migration.ts | 5 +- models/setting/src/index.ts | 65 ++++++--- models/setting/src/plugin.ts | 3 +- models/templates/src/index.ts | 5 +- models/view/src/index.ts | 1 + packages/core/src/__tests__/memdb.test.ts | 2 +- packages/core/src/classes.ts | 10 ++ packages/query/src/__tests__/minmodel.ts | 4 +- packages/query/src/__tests__/query.test.ts | 3 +- .../src/components/DropdownLabelsIntl.svelte | 13 +- .../components/DropdownLabelsPopupIntl.svelte | 30 +--- .../src/components/FileBrowserFilters.svelte | 2 - .../src/components/CreateEmployee.svelte | 5 +- plugins/contact-resources/src/index.ts | 1 + plugins/setting-assets/lang/en.json | 10 +- plugins/setting-assets/lang/ru.json | 10 +- .../src/components/CategoryElement.svelte | 19 ++- .../src/components/EnumSetting.svelte | 2 +- .../src/components/Owners.svelte | 91 ++++++++++++ .../src/components/Setting.svelte | 25 ---- .../src/components/Settings.svelte | 37 ++++- .../src/components/WorkspaceSettings.svelte | 74 ++++++++++ plugins/setting-resources/src/index.ts | 8 +- plugins/setting-resources/src/plugin.ts | 8 +- plugins/setting/src/index.ts | 11 +- plugins/view-resources/src/actions.ts | 7 +- .../src/components/BooleanEditor.svelte | 5 +- plugins/view/src/index.ts | 3 + .../src/components/AccountPopup.svelte | 134 ++++++++---------- .../src/components/Workbench.svelte | 17 ++- server/account/src/index.ts | 26 +++- server/mongo/src/__tests__/minmodel.ts | 4 +- server/ws/src/__tests__/minmodel.ts | 4 +- tests/sanity/tests/settings.spec.ts | 17 +-- tests/sanity/tests/workbench.spec.ts | 12 -- 41 files changed, 502 insertions(+), 229 deletions(-) create mode 100644 plugins/setting-resources/src/components/Owners.svelte delete mode 100644 plugins/setting-resources/src/components/Setting.svelte create mode 100644 plugins/setting-resources/src/components/WorkspaceSettings.svelte diff --git a/changelog.md b/changelog.md index 748487f1be..0456425541 100644 --- a/changelog.md +++ b/changelog.md @@ -5,9 +5,10 @@ Core: - Allow to leave workspace -- Allow to kick employee +- Allow to kick employee (Only for owner) - Browser notifications - Allow to create employee +- Owner role for employee HR: diff --git a/dev/tool/src/index.ts b/dev/tool/src/index.ts index f6ad9bdb53..b5d602789d 100644 --- a/dev/tool/src/index.ts +++ b/dev/tool/src/index.ts @@ -23,6 +23,7 @@ import { dropWorkspace, getAccount, getWorkspace, + setRole, listAccounts, listWorkspaces, upgradeWorkspace @@ -114,6 +115,14 @@ program }) }) +program + .command('set-user-role ') + .description('set user role') + .action(async (email: string, workspace: string, role: number, cmd) => { + console.log(`set user ${email} role for ${workspace}...`) + await setRole(email, workspace, role) + }) + program .command('upgrade-workspace ') .description('upgrade workspace') diff --git a/models/automation/src/index.ts b/models/automation/src/index.ts index 00d1c31093..4f471f6453 100644 --- a/models/automation/src/index.ts +++ b/models/automation/src/index.ts @@ -71,14 +71,15 @@ export function createModel (builder: Builder): void { /** Disable Automation UI builder.createDoc( - setting.class.SettingsCategory, + setting.class.WorkspaceSettingCategory, core.space.Model, { name: 'automation', label: automation.string.Automation, icon: automation.icon.Automation, // TODO: update icon component: plugin.component.AutomationSettingsElement, - order: 3600 + order: 3600, + secured: false }, plugin.ids.Automation ) diff --git a/models/contact/src/index.ts b/models/contact/src/index.ts index 5040a055bb..4df4b18047 100644 --- a/models/contact/src/index.ts +++ b/models/contact/src/index.ts @@ -420,7 +420,8 @@ export function createModel (builder: Builder): void { context: { mode: ['context'], group: 'other' - } + }, + secured: true }, contact.action.KickEmployee ) diff --git a/models/contact/src/migration.ts b/models/contact/src/migration.ts index 708f5e682d..f493ea4d7f 100644 --- a/models/contact/src/migration.ts +++ b/models/contact/src/migration.ts @@ -1,6 +1,5 @@ // -// Copyright © 2020, 2021 Anticrm Platform Contributors. -// Copyright © 2021 Hardcore Engineering Inc. +// Copyright © 2022 Hardcore Engineering Inc. // // Licensed under the Eclipse Public License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. You may @@ -14,7 +13,8 @@ // limitations under the License. // -import { TxOperations } from '@anticrm/core' +import { Employee, EmployeeAccount } from '@anticrm/contact' +import { AccountRole, DOMAIN_TX, TxCreateDoc, TxOperations } from '@anticrm/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' import core from '@anticrm/model-core' import contact, { DOMAIN_CONTACT } from './index' @@ -66,11 +66,40 @@ async function setActiveEmployee (client: MigrationClient): Promise { active: true } ) + await setActiveEmployeeTx(client) +} + +async function setActiveEmployeeTx (client: MigrationClient): Promise { + await client.update>( + DOMAIN_TX, + { + _class: core.class.TxCreateDoc, + objectClass: contact.class.Employee, + 'attributes.active': { $exists: false } + }, + { + 'attributes.active': true + } + ) +} + +async function setRole (client: MigrationClient): Promise { + await client.update>( + DOMAIN_TX, + { + _class: core.class.TxCreateDoc, + objectClass: contact.class.Employee + }, + { + 'attributes.role': AccountRole.User + } + ) } export const contactOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { await setActiveEmployee(client) + await setRole(client) }, async upgrade (client: MigrationUpgradeClient): Promise { const tx = new TxOperations(client, core.account.System) diff --git a/models/core/src/security.ts b/models/core/src/security.ts index e831f1f7a8..d8a02ea13d 100644 --- a/models/core/src/security.ts +++ b/models/core/src/security.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import { Account, Arr, Domain, DOMAIN_MODEL, IndexKind, Ref, Space } from '@anticrm/core' +import { Account, AccountRole, Arr, Domain, DOMAIN_MODEL, IndexKind, Ref, Space } from '@anticrm/core' import { Index, Model, Prop, TypeBoolean, TypeString, UX } from '@anticrm/model' import core from './component' import { TDoc } from './core' @@ -45,4 +45,5 @@ export class TSpace extends TDoc implements Space { @Model(core.class.Account, core.class.Doc, DOMAIN_MODEL) export class TAccount extends TDoc implements Account { email!: string + role!: AccountRole } diff --git a/models/demo/src/migration.ts b/models/demo/src/migration.ts index 83acec306e..cc9331cdeb 100644 --- a/models/demo/src/migration.ts +++ b/models/demo/src/migration.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import core, { TxOperations } from '@anticrm/core' +import core, { AccountRole, TxOperations } from '@anticrm/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' import contact, { EmployeeAccount } from '@anticrm/contact' import recruit from '@anticrm/model-recruit' @@ -61,7 +61,8 @@ export const demoOperation: MigrateOperation = { await tx.createDoc(contact.class.EmployeeAccount, core.space.Model, { email: 'rosamund@hc.engineering', employee, - name: 'Chen,Rosamund' + name: 'Chen,Rosamund', + role: AccountRole.Owner }) } diff --git a/models/setting/src/index.ts b/models/setting/src/index.ts index be82e05209..6c861c3224 100644 --- a/models/setting/src/index.ts +++ b/models/setting/src/index.ts @@ -40,6 +40,16 @@ export class TSettingsCategory extends TDoc implements SettingsCategory { label!: IntlString icon!: Asset component!: AnyComponent + secured!: boolean +} + +@Model(setting.class.WorkspaceSettingCategory, core.class.Doc, DOMAIN_MODEL) +export class TWorkspaceSettingCategory extends TDoc implements SettingsCategory { + name!: string + label!: IntlString + icon!: Asset + component!: AnyComponent + secured!: boolean } @Model(setting.class.IntegrationType, core.class.Doc, DOMAIN_MODEL) @@ -56,7 +66,7 @@ export class TIntegrationType extends TDoc implements IntegrationType { export class TEditable extends TClass implements Editable {} export function createModel (builder: Builder): void { - builder.createModel(TIntegration, TIntegrationType, TSettingsCategory, TEditable) + builder.createModel(TIntegration, TIntegrationType, TSettingsCategory, TWorkspaceSettingCategory, TEditable) builder.createDoc( setting.class.SettingsCategory, @@ -66,7 +76,8 @@ export function createModel (builder: Builder): void { label: setting.string.EditProfile, icon: setting.icon.EditProfile, component: setting.component.Profile, - order: 0 + order: 0, + secured: false }, setting.ids.Profile ) @@ -79,7 +90,8 @@ export function createModel (builder: Builder): void { label: setting.string.ChangePassword, icon: setting.icon.Password, component: setting.component.Password, - order: 1000 + order: 1000, + secured: false }, setting.ids.Password ) @@ -88,10 +100,11 @@ export function createModel (builder: Builder): void { core.space.Model, { name: 'setting', - label: setting.string.Setting, + label: setting.string.WorkspaceSetting, icon: setting.icon.Setting, - component: setting.component.Setting, - order: 2000 + component: setting.component.WorkspaceSettings, + order: 2000, + secured: false }, setting.ids.Setting ) @@ -103,43 +116,60 @@ export function createModel (builder: Builder): void { label: setting.string.Integrations, icon: setting.icon.Integrations, component: setting.component.Integrations, - order: 3000 + order: 3000, + secured: false }, setting.ids.Integrations ) builder.createDoc( - setting.class.SettingsCategory, + setting.class.WorkspaceSettingCategory, + core.space.Model, + { + name: 'owners', + label: setting.string.Owners, + icon: setting.icon.Password, + component: setting.component.Owners, + order: 1000, + secured: true + }, + setting.ids.Owners + ) + builder.createDoc( + setting.class.WorkspaceSettingCategory, core.space.Model, { name: 'statuses', label: setting.string.ManageStatuses, icon: task.icon.ManageStatuses, component: setting.component.ManageStatuses, - order: 4000 + order: 4000, + secured: false }, setting.ids.ManageStatuses ) builder.createDoc( - setting.class.SettingsCategory, + setting.class.WorkspaceSettingCategory, core.space.Model, { name: 'classes', label: setting.string.ClassSetting, icon: setting.icon.Setting, component: setting.component.ClassSetting, - order: 4500 + order: 4500, + secured: false }, setting.ids.ClassSetting ) builder.createDoc( - setting.class.SettingsCategory, + setting.class.WorkspaceSettingCategory, core.space.Model, { name: 'enums', label: setting.string.Enums, icon: setting.icon.Setting, component: setting.component.EnumSetting, - order: 4600 + order: 4600, + secured: false }, setting.ids.EnumSetting ) @@ -151,7 +181,8 @@ export function createModel (builder: Builder): void { label: setting.string.Support, icon: setting.icon.Support, component: setting.component.Support, - order: 5000 + order: 5000, + secured: false }, setting.ids.Support ) @@ -163,7 +194,8 @@ export function createModel (builder: Builder): void { label: setting.string.Privacy, icon: setting.icon.Privacy, component: setting.component.Privacy, - order: 6000 + order: 6000, + secured: false }, setting.ids.Privacy ) @@ -175,7 +207,8 @@ export function createModel (builder: Builder): void { label: setting.string.Terms, icon: setting.icon.Terms, component: setting.component.Terms, - order: 10000 + order: 10000, + secured: false }, setting.ids.Terms ) diff --git a/models/setting/src/plugin.ts b/models/setting/src/plugin.ts index 7d65894c5f..c7cdda165c 100644 --- a/models/setting/src/plugin.ts +++ b/models/setting/src/plugin.ts @@ -36,6 +36,7 @@ export default mergeIds(settingId, setting, { NumberTypeEditor: '' as AnyComponent, DateTypeEditor: '' as AnyComponent, RefEditor: '' as AnyComponent, - EnumTypeEditor: '' as AnyComponent + EnumTypeEditor: '' as AnyComponent, + Owners: '' as AnyComponent } }) diff --git a/models/templates/src/index.ts b/models/templates/src/index.ts index a6a2b39095..94af90da6b 100644 --- a/models/templates/src/index.ts +++ b/models/templates/src/index.ts @@ -39,14 +39,15 @@ export function createModel (builder: Builder): void { builder.createModel(TMessageTemplate) builder.createDoc( - setting.class.SettingsCategory, + setting.class.WorkspaceSettingCategory, core.space.Model, { name: 'message-templates', label: templates.string.Templates, icon: templates.icon.Templates, component: templates.component.Templates, - order: 3500 + order: 3500, + secured: false }, templates.ids.Templates ) diff --git a/models/view/src/index.ts b/models/view/src/index.ts index b457a7d455..5e25dc9e9f 100644 --- a/models/view/src/index.ts +++ b/models/view/src/index.ts @@ -202,6 +202,7 @@ export class TAction extends TDoc implements Action { description!: IntlString category!: Ref context!: ViewContext + secured?: boolean } @Model(view.class.ActionCategory, core.class.Doc, DOMAIN_MODEL) diff --git a/packages/core/src/__tests__/memdb.test.ts b/packages/core/src/__tests__/memdb.test.ts index 954f13b59a..a5d33c1628 100644 --- a/packages/core/src/__tests__/memdb.test.ts +++ b/packages/core/src/__tests__/memdb.test.ts @@ -236,7 +236,7 @@ describe('memdb', () => { members: [], archived: false }) - const account = await model.createDoc(core.class.Account, core.space.Model, { email: 'email' }) + const account = await model.createDoc(core.class.Account, core.space.Model, { email: 'email', role: 0 }) await model.updateDoc(core.class.Space, core.space.Model, space, { $push: { members: account } }) const txSpace = await model.findAll(core.class.Space, { _id: space }) expect(txSpace[0].members).toEqual(expect.arrayContaining([account])) diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 3058e70934..30f813a6de 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -279,6 +279,16 @@ export interface Space extends Doc { */ export interface Account extends Doc { email: string + role: AccountRole +} + +/** + * @public + */ +export enum AccountRole { + User, + Maintainer, + Owner } /** diff --git a/packages/query/src/__tests__/minmodel.ts b/packages/query/src/__tests__/minmodel.ts index 9b6f3c8f41..a065c2b2cb 100644 --- a/packages/query/src/__tests__/minmodel.ts +++ b/packages/query/src/__tests__/minmodel.ts @@ -194,8 +194,8 @@ export function genMinModel (): TxCUD[] { const u1 = 'User1' as Ref const u2 = 'User2' as Ref txes.push( - createDoc(core.class.Account, { email: 'user1@site.com' }, u1), - createDoc(core.class.Account, { email: 'user2@site.com' }, u2), + createDoc(core.class.Account, { email: 'user1@site.com', role: 0 }, u1), + createDoc(core.class.Account, { email: 'user2@site.com', role: 0 }, u2), createDoc(core.class.Space, { name: 'Sp1', description: '', diff --git a/packages/query/src/__tests__/query.test.ts b/packages/query/src/__tests__/query.test.ts index f156019ffc..5a9df53b60 100644 --- a/packages/query/src/__tests__/query.test.ts +++ b/packages/query/src/__tests__/query.test.ts @@ -100,7 +100,8 @@ describe('query', () => { }) await factory.createDoc(core.class.Account, core.space.Model, { - email: 'user1@site.com' + email: 'user1@site.com', + role: 0 }) await factory.createDoc(core.class.Space, core.space.Model, { private: true, diff --git a/packages/ui/src/components/DropdownLabelsIntl.svelte b/packages/ui/src/components/DropdownLabelsIntl.svelte index 6c296f9564..fe266ab121 100644 --- a/packages/ui/src/components/DropdownLabelsIntl.svelte +++ b/packages/ui/src/components/DropdownLabelsIntl.svelte @@ -16,7 +16,6 @@ import { IntlString, Asset } from '@anticrm/platform' import { createEventDispatcher } from 'svelte' import type { AnySvelteComponent, TooltipAlignment, ButtonKind, ButtonSize, DropdownIntlItem } from '../types' - import ui from '../plugin' import { showPopup } from '../popups' import Button from './Button.svelte' import DropdownLabelsPopupIntl from './DropdownLabelsPopupIntl.svelte' @@ -24,10 +23,9 @@ export let icon: Asset | AnySvelteComponent | undefined = undefined export let label: IntlString - export let placeholder: IntlString | undefined = ui.string.SearchDots export let items: DropdownIntlItem[] export let selected: DropdownIntlItem['id'] | undefined = undefined - + export let disabled: boolean = false export let kind: ButtonKind = 'no-border' export let size: ButtonSize = 'small' export let justify: 'left' | 'center' = 'center' @@ -52,12 +50,13 @@ width={width ?? 'min-content'} {size} {kind} + {disabled} {justify} showTooltip={{ label, direction: labelDirection }} on:click={() => { if (!opened) { opened = true - showPopup(DropdownLabelsPopupIntl, { placeholder, items, selected }, container, (result) => { + showPopup(DropdownLabelsPopupIntl, { items, selected }, container, (result) => { if (result) { selected = result dispatch('selected', result) @@ -68,11 +67,7 @@ }} > - {#if selectedItem} - diff --git a/packages/ui/src/components/DropdownLabelsPopupIntl.svelte b/packages/ui/src/components/DropdownLabelsPopupIntl.svelte index 84dcc37be8..b547285f5e 100644 --- a/packages/ui/src/components/DropdownLabelsPopupIntl.svelte +++ b/packages/ui/src/components/DropdownLabelsPopupIntl.svelte @@ -13,26 +13,16 @@ // limitations under the License. -->
-
- {}} - on:change - /> -
- {#each items.filter((x) => x.label.toLowerCase().includes(search.toLowerCase())) as item, i} + {#each items as item, i}
-
+
{#if selected !== undefined} {/if} diff --git a/plugins/setting-resources/src/components/Owners.svelte b/plugins/setting-resources/src/components/Owners.svelte new file mode 100644 index 0000000000..be8ca8b787 --- /dev/null +++ b/plugins/setting-resources/src/components/Owners.svelte @@ -0,0 +1,91 @@ + + + +
+
+
+
+
+
+
+ {#each accounts as account (account._id)} +
+ + currentRole || (account.role === AccountRole.Owner && owners.length === 1)} + kind={'transparent'} + size={'medium'} + {items} + selected={account.role.toString()} + on:selected={(e) => { + change(account, Number(e.detail)) + }} + /> +
+ {/each} +
+
+
diff --git a/plugins/setting-resources/src/components/Setting.svelte b/plugins/setting-resources/src/components/Setting.svelte deleted file mode 100644 index 04c649da6a..0000000000 --- a/plugins/setting-resources/src/components/Setting.svelte +++ /dev/null @@ -1,25 +0,0 @@ - - - -
-
-
-
-
-
diff --git a/plugins/setting-resources/src/components/Settings.svelte b/plugins/setting-resources/src/components/Settings.svelte index 3243cf588e..193b268700 100644 --- a/plugins/setting-resources/src/components/Settings.svelte +++ b/plugins/setting-resources/src/components/Settings.svelte @@ -1,5 +1,19 @@ + + +
+
+
+ + +
+ {#each categories as category} + { + selectCategory(category) + }} + /> + {/each} +
+ +
+ {#if category} + + {/if} +
+
diff --git a/plugins/setting-resources/src/index.ts b/plugins/setting-resources/src/index.ts index 6a4ac0136b..443f85523d 100644 --- a/plugins/setting-resources/src/index.ts +++ b/plugins/setting-resources/src/index.ts @@ -16,7 +16,7 @@ import { Resources } from '@anticrm/platform' import Profile from './components/Profile.svelte' import Password from './components/Password.svelte' -import Setting from './components/Setting.svelte' +import WorkspaceSettings from './components/WorkspaceSettings.svelte' import Integrations from './components/Integrations.svelte' import ManageStatuses from './components/statuses/ManageStatuses.svelte' import Support from './components/Support.svelte' @@ -34,6 +34,7 @@ import RefEditor from './components/typeEditors/RefEditor.svelte' import EnumTypeEditor from './components/typeEditors/EnumTypeEditor.svelte' import EditEnum from './components/EditEnum.svelte' import EnumSetting from './components/EnumSetting.svelte' +import Owners from './components/Owners.svelte' export default async (): Promise => ({ activity: { @@ -44,7 +45,7 @@ export default async (): Promise => ({ Settings, Profile, Password, - Setting, + WorkspaceSettings, Integrations, Support, Privacy, @@ -58,6 +59,7 @@ export default async (): Promise => ({ DateTypeEditor, EnumTypeEditor, EditEnum, - EnumSetting + EnumSetting, + Owners } }) diff --git a/plugins/setting-resources/src/plugin.ts b/plugins/setting-resources/src/plugin.ts index 12910c59b4..79ee1fd42d 100644 --- a/plugins/setting-resources/src/plugin.ts +++ b/plugins/setting-resources/src/plugin.ts @@ -41,6 +41,12 @@ export default mergeIds(settingId, setting, { Enums: '' as IntlString, NewValue: '' as IntlString, Leave: '' as IntlString, - LeaveDescr: '' as IntlString + LeaveDescr: '' as IntlString, + Select: '' as IntlString, + AddOwner: '' as IntlString, + User: '' as IntlString, + Maintainer: '' as IntlString, + Owner: '' as IntlString, + Role: '' as IntlString } }) diff --git a/plugins/setting/src/index.ts b/plugins/setting/src/index.ts index e77788d3c4..e9e24ef1fc 100644 --- a/plugins/setting/src/index.ts +++ b/plugins/setting/src/index.ts @@ -60,6 +60,7 @@ export interface SettingsCategory extends Doc { // If defined, will sort using order. order?: number + secured: boolean } /** @@ -78,13 +79,15 @@ export default plugin(settingId, { Support: '' as Ref, Privacy: '' as Ref, Terms: '' as Ref, - ClassSetting: '' as Ref + ClassSetting: '' as Ref, + Owners: '' as Ref }, mixin: { Editable: '' as Ref> }, class: { SettingsCategory: '' as Ref>, + WorkspaceSettingCategory: '' as Ref>, Integration: '' as Ref>, IntegrationType: '' as Ref> }, @@ -92,7 +95,7 @@ export default plugin(settingId, { Settings: '' as AnyComponent, Profile: '' as AnyComponent, Password: '' as AnyComponent, - Setting: '' as AnyComponent, + WorkspaceSettings: '' as AnyComponent, Integrations: '' as AnyComponent, ManageStatuses: '' as AnyComponent, Support: '' as AnyComponent, @@ -103,6 +106,7 @@ export default plugin(settingId, { string: { Settings: '' as IntlString, Setting: '' as IntlString, + WorkspaceSetting: '' as IntlString, Integrations: '' as IntlString, ManageStatuses: '' as IntlString, Support: '' as IntlString, @@ -127,7 +131,8 @@ export default plugin(settingId, { InviteWorkspace: '' as IntlString, SelectWorkspace: '' as IntlString, Reconnect: '' as IntlString, - ClassSetting: '' as IntlString + ClassSetting: '' as IntlString, + Owners: '' as IntlString }, icon: { EditProfile: '' as Asset, diff --git a/plugins/view-resources/src/actions.ts b/plugins/view-resources/src/actions.ts index 12e9b35710..2c3d3ce2ab 100644 --- a/plugins/view-resources/src/actions.ts +++ b/plugins/view-resources/src/actions.ts @@ -14,8 +14,7 @@ // limitations under the License. // -import type { Doc, WithLookup } from '@anticrm/core' -import core, { Class, Client, matchQuery, Ref } from '@anticrm/core' +import core, { AccountRole, Doc, getCurrentAccount, WithLookup, Class, Client, matchQuery, Ref } from '@anticrm/core' import { getResource } from '@anticrm/platform' import type { Action, ViewAction, ViewActionInput, ViewContextType } from '@anticrm/view' import view from './plugin' @@ -118,6 +117,7 @@ export function filterActions ( ): Array> { let result: Array> = [] const hierarchy = client.getHierarchy() + const role = getCurrentAccount().role const clazz = hierarchy.getClass(doc._class) const ignoreActions = hierarchy.as(clazz, view.mixin.IgnoreActions) const ignore = ignoreActions?.actions ?? [] @@ -126,6 +126,9 @@ export function filterActions ( if (ignore.includes(action._id)) { continue } + if (role < AccountRole.Maintainer && action.secured === true) { + continue + } if (action.override !== undefined) { overrideRemove.push(...action.override) } diff --git a/plugins/view-resources/src/components/BooleanEditor.svelte b/plugins/view-resources/src/components/BooleanEditor.svelte index 89df42791f..dde7aa1c04 100644 --- a/plugins/view-resources/src/components/BooleanEditor.svelte +++ b/plugins/view-resources/src/components/BooleanEditor.svelte @@ -22,7 +22,7 @@ export let value: any export let withoutUndefined: boolean = false export let onChange: (value: any) => void - + export let disabled: boolean = false export let kind: ButtonKind = 'no-border' export let size: ButtonSize = 'small' export let justify: 'left' | 'center' = 'center' @@ -36,8 +36,9 @@ {size} {justify} {width} + {disabled} on:click={(ev) => { - if (!shown) { + if (!shown && !disabled) { showPopup(BooleanEditorPopup, { value, withoutUndefined }, eventToHTMLElement(ev), (res) => { if (res !== undefined) { if (res === 1) value = true diff --git a/plugins/view/src/index.ts b/plugins/view/src/index.ts index aa87cf95c8..3e1b0d2363 100644 --- a/plugins/view/src/index.ts +++ b/plugins/view/src/index.ts @@ -262,6 +262,9 @@ export interface Action> extends Do // A list of actions replaced by this one. // For example it could be global action and action for focus class, second one fill override first one. override?: Ref[] + + // Avaible only for workspace owners + secured?: boolean } /** diff --git a/plugins/workbench-resources/src/components/AccountPopup.svelte b/plugins/workbench-resources/src/components/AccountPopup.svelte index ba072d1eae..e30d50485d 100644 --- a/plugins/workbench-resources/src/components/AccountPopup.svelte +++ b/plugins/workbench-resources/src/components/AccountPopup.svelte @@ -14,10 +14,10 @@ -->
- {#await getItems() then items} - - {#if items} - +
diff --git a/plugins/workbench-resources/src/components/Workbench.svelte b/plugins/workbench-resources/src/components/Workbench.svelte index c3139febb9..19e7816995 100644 --- a/plugins/workbench-resources/src/components/Workbench.svelte +++ b/plugins/workbench-resources/src/components/Workbench.svelte @@ -15,7 +15,7 @@