mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
Section locking (#10702)
* implement section locking functionality with role-based access control Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Fix formatting Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> * Add translations Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com> --------- Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Generated
+4
-1
@@ -32346,6 +32346,9 @@ importers:
|
||||
|
||||
../../server-plugins/card-resources:
|
||||
dependencies:
|
||||
'@hcengineering/activity':
|
||||
specifier: workspace:^0.7.0
|
||||
version: link:../../plugins/activity
|
||||
'@hcengineering/card':
|
||||
specifier: workspace:^0.7.0
|
||||
version: link:../../plugins/card
|
||||
@@ -61563,7 +61566,7 @@ snapshots:
|
||||
node-loader@2.0.0(webpack@5.102.1):
|
||||
dependencies:
|
||||
loader-utils: 2.0.4
|
||||
webpack: 5.102.1
|
||||
webpack: 5.102.1(esbuild@0.25.12)(webpack-cli@5.1.4)
|
||||
|
||||
node-localstorage@2.2.1:
|
||||
dependencies:
|
||||
|
||||
@@ -83,7 +83,7 @@ import { PaletteColorIndexes } from '@hcengineering/ui/src/colors'
|
||||
import { type AnyComponent } from '@hcengineering/ui/src/types'
|
||||
import { type BuildModelKey } from '@hcengineering/view'
|
||||
import { createActions } from './actions'
|
||||
import { definePermissions } from './permissions'
|
||||
import { defineActionPermissions, definePermissions } from './permissions'
|
||||
import card from './plugin'
|
||||
import notification from '@hcengineering/notification'
|
||||
|
||||
@@ -426,6 +426,7 @@ export function createModel (builder: Builder): void {
|
||||
|
||||
defineTabs(builder)
|
||||
definePermissions(builder)
|
||||
defineActionPermissions(builder)
|
||||
|
||||
builder.mixin(card.class.Card, core.class.Class, view.mixin.ObjectIcon, {
|
||||
component: card.component.CardIcon
|
||||
|
||||
@@ -154,3 +154,35 @@ export function definePermissions (builder: Builder): void {
|
||||
card.permission.ForbidRemoveCard
|
||||
)
|
||||
}
|
||||
|
||||
export function defineActionPermissions (builder: Builder): void {
|
||||
builder.createDoc(
|
||||
core.class.Permission,
|
||||
core.space.Model,
|
||||
{
|
||||
label: card.string.LockSection,
|
||||
txClass: core.class.TxUpdateDoc,
|
||||
objectClass: card.class.Card,
|
||||
txMatch: {
|
||||
'operations.$push.readonlySections': { $exists: true }
|
||||
},
|
||||
scope: 'space'
|
||||
},
|
||||
card.permission.LockSection
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
core.class.Permission,
|
||||
core.space.Model,
|
||||
{
|
||||
label: card.string.UnLockSection,
|
||||
txClass: core.class.TxUpdateDoc,
|
||||
objectClass: card.class.Card,
|
||||
txMatch: {
|
||||
'operations.$pull.readonlySections': { $exists: true }
|
||||
},
|
||||
scope: 'space'
|
||||
},
|
||||
card.permission.UnlockSection
|
||||
)
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Karta aktualizována",
|
||||
"CardCreated": "Karta vytvořena",
|
||||
"MyCards": "Moje karty",
|
||||
"GotoMyCards": "Přejít na moje karty"
|
||||
"GotoMyCards": "Přejít na moje karty",
|
||||
"LockSection": "Zamknout sekci",
|
||||
"UnLockSection": "Odemknout sekci",
|
||||
"SectionLocked": "Sekce {section} zamknuta",
|
||||
"SectionUnlocked": "Sekce {section} odemknuta"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Karte aktualisiert",
|
||||
"CardCreated": "Karte erstellt",
|
||||
"MyCards": "Meine Karten",
|
||||
"GotoMyCards": "Zu meinen Karten"
|
||||
"GotoMyCards": "Zu meinen Karten",
|
||||
"LockSection": "Sperren",
|
||||
"UnLockSection": "Entsperren",
|
||||
"SectionLocked": "Sektion {section} gesperrt",
|
||||
"SectionUnlocked": "Sektion {section} entsperrt"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Card updated",
|
||||
"CardCreated": "Card created",
|
||||
"MyCards": "My cards",
|
||||
"GotoMyCards": "Go to my cards"
|
||||
"GotoMyCards": "Go to my cards",
|
||||
"LockSection": "Lock section",
|
||||
"UnLockSection": "Unlock section",
|
||||
"SectionLocked": "Section {section} locked",
|
||||
"SectionUnlocked": "Section {section} unlocked"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Tarjeta actualizada",
|
||||
"CardCreated": "Tarjeta creada",
|
||||
"MyCards": "Mis tarjetas",
|
||||
"GotoMyCards": "Ir a mis tarjetas"
|
||||
"GotoMyCards": "Ir a mis tarjetas",
|
||||
"LockSection": "Bloquear sección",
|
||||
"UnLockSection": "Desbloquear sección",
|
||||
"SectionLocked": "Sección {section} bloqueada",
|
||||
"SectionUnlocked": "Sección {section} desbloqueada"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Carte mise à jour",
|
||||
"CardCreated": "Carte créée",
|
||||
"MyCards": "Mes cartes",
|
||||
"GotoMyCards": "Aller à mes cartes"
|
||||
"GotoMyCards": "Aller à mes cartes",
|
||||
"LockSection": "Verrouiller la section",
|
||||
"UnLockSection": "Déverrouiller la section",
|
||||
"SectionLocked": "Section {section} verrouillée",
|
||||
"SectionUnlocked": "Section {section} déverrouillée"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Scheda aggiornata",
|
||||
"CardCreated": "Scheda creata",
|
||||
"MyCards": "Le mie carte",
|
||||
"GotoMyCards": "Vai alle mie carte"
|
||||
"GotoMyCards": "Vai alle mie carte",
|
||||
"LockSection": "Blocca sezione",
|
||||
"UnLockSection": "Sblocca sezione",
|
||||
"SectionLocked": "Sezione {section} bloccata",
|
||||
"SectionUnlocked": "Sezione {section} sbloccata"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "カードが更新されました",
|
||||
"CardCreated": "カードが作成されました",
|
||||
"MyCards": "マイカード",
|
||||
"GotoMyCards": "マイカードへ移動"
|
||||
"GotoMyCards": "マイカードへ移動",
|
||||
"LockSection": "セクションをロック",
|
||||
"UnLockSection": "セクションをアンロック",
|
||||
"SectionLocked": "セクション {section} ロック済み",
|
||||
"SectionUnlocked": "セクション {section} アンロック済み"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Cartão atualizado",
|
||||
"CardCreated": "Cartão criado",
|
||||
"MyCards": "Meus cartões",
|
||||
"GotoMyCards": "Ir para meus cartões"
|
||||
"GotoMyCards": "Ir para meus cartões",
|
||||
"LockSection": "Bloquear seção",
|
||||
"UnLockSection": "Desbloquear seção",
|
||||
"SectionLocked": "Seção {section} bloqueada",
|
||||
"SectionUnlocked": "Seção {section} desbloqueada"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Cartão atualizado",
|
||||
"CardCreated": "Cartão criado",
|
||||
"MyCards": "Meus cartões",
|
||||
"GotoMyCards": "Ir para meus cartões"
|
||||
"GotoMyCards": "Ir para meus cartões",
|
||||
"LockSection": "Bloquear seção",
|
||||
"UnLockSection": "Desbloquear seção",
|
||||
"SectionLocked": "Seção {section} bloqueada",
|
||||
"SectionUnlocked": "Seção {section} desbloqueada"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Карточка обновлена",
|
||||
"CardCreated": "Карточка создана",
|
||||
"MyCards": "Мои карты",
|
||||
"GotoMyCards": "Перейти к моим картам"
|
||||
"GotoMyCards": "Перейти к моим картам",
|
||||
"LockSection": "Заблокировать секцию",
|
||||
"UnLockSection": "Разблокировать секцию",
|
||||
"SectionLocked": "Секция {section} заблокирована",
|
||||
"SectionUnlocked": "Секция {section} разблокирована"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "Kart güncellendi",
|
||||
"CardCreated": "Kart oluşturuldu",
|
||||
"MyCards": "Benim kartlarım",
|
||||
"GotoMyCards": "Benim kartlarıma git"
|
||||
"GotoMyCards": "Benim kartlarıma git",
|
||||
"LockSection": "Bölümü kilitle",
|
||||
"UnLockSection": "Bölümü kilitle",
|
||||
"SectionLocked": "Bölüm {section} kilitli",
|
||||
"SectionUnlocked": "Bölüm {section} kilidi açıldı"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
"CardUpdated": "卡片已更新",
|
||||
"CardCreated": "卡片已创建",
|
||||
"MyCards": "我的卡片",
|
||||
"GotoMyCards": "转到我的卡片"
|
||||
"GotoMyCards": "转到我的卡片",
|
||||
"LockSection": "锁定部分",
|
||||
"UnLockSection": "解锁部分",
|
||||
"SectionLocked": "部分 {section} 已锁定",
|
||||
"SectionUnlocked": "部分 {section} 已解锁"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,11 @@
|
||||
import CardAttributes from './CardAttributes.svelte'
|
||||
import { AccountRole, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
|
||||
import CardIcon from './CardIcon.svelte'
|
||||
import { canLockSection, canUnlockSection } from '../utils'
|
||||
import { permissionsStore } from '@hcengineering/contact-resources'
|
||||
import Lock from './icons/Lock.svelte'
|
||||
import Unlock from './icons/Unlock.svelte'
|
||||
import card from '../plugin'
|
||||
|
||||
export let value: Card
|
||||
export let readonly: boolean = false
|
||||
@@ -49,6 +54,16 @@
|
||||
export function expand (): void {
|
||||
isCollapsed = false
|
||||
}
|
||||
|
||||
$: isLocked = value.readonlySections?.includes(value._class) ?? false
|
||||
$: canLock = canLockSection(value.space, $permissionsStore)
|
||||
$: canUnlock = canUnlockSection(value.space, $permissionsStore)
|
||||
|
||||
async function toggleLock (ev: MouseEvent): Promise<void> {
|
||||
ev.stopPropagation()
|
||||
const op = isLocked ? '$pull' : '$push'
|
||||
await client.update(value, { [op]: { readonlySections: value._class } })
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="header flex flex-gap-2">
|
||||
@@ -57,8 +72,19 @@
|
||||
<Label {label} />
|
||||
<Chevron expanded={!isCollapsed} outline fill={'var(--content-color)'} />
|
||||
</div>
|
||||
{#if hasAccountRole(getCurrentAccount(), AccountRole.Maintainer)}
|
||||
<div class="btns">
|
||||
<div class="btns">
|
||||
{#if (isLocked && canUnlock) || (!isLocked && canLock)}
|
||||
<div class="lock-btn">
|
||||
<Button
|
||||
icon={isLocked ? Unlock : Lock}
|
||||
kind={'link'}
|
||||
size={'medium'}
|
||||
showTooltip={{ label: isLocked ? card.string.UnLockSection : card.string.LockSection }}
|
||||
on:click={toggleLock}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if hasAccountRole(getCurrentAccount(), AccountRole.Maintainer)}
|
||||
<Button
|
||||
icon={IconAdd}
|
||||
kind={'link'}
|
||||
@@ -84,8 +110,8 @@
|
||||
navigate(loc)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<ExpandCollapse isExpanded={!isCollapsed}>
|
||||
<CardAttributes object={value} _class={value._class} {readonly} {ignoreKeys} {fourRows} showCollaborators />
|
||||
@@ -116,6 +142,14 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
visibility: hidden;
|
||||
|
||||
.lock-btn {
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.2s;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -30,7 +30,12 @@
|
||||
themeStore,
|
||||
tooltip
|
||||
} from '@hcengineering/ui'
|
||||
import { permissionsStore } from '@hcengineering/contact-resources'
|
||||
import { canLockSection, canUnlockSection } from '../utils'
|
||||
import CardAttributes from './CardAttributes.svelte'
|
||||
import Lock from './icons/Lock.svelte'
|
||||
import Unlock from './icons/Unlock.svelte'
|
||||
import card from '../plugin'
|
||||
|
||||
export let value: Card
|
||||
export let tag: Tag
|
||||
@@ -54,6 +59,16 @@
|
||||
$: color = getPlatformColorDef(tag.background ?? 0, $themeStore.dark).color
|
||||
|
||||
$: isEditable = h.hasMixin(tag, setting.mixin.Editable) && h.as(tag, setting.mixin.Editable).value
|
||||
|
||||
$: isLocked = value.readonlySections?.includes(tag._id) ?? false
|
||||
$: canLock = canLockSection(value.space, $permissionsStore)
|
||||
$: canUnlock = canUnlockSection(value.space, $permissionsStore)
|
||||
|
||||
async function toggleLock (ev: MouseEvent): Promise<void> {
|
||||
ev.stopPropagation()
|
||||
const op = isLocked ? '$pull' : '$push'
|
||||
await client.update(value, { [op]: { readonlySections: tag._id } })
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="header flex flex-gap-2">
|
||||
@@ -68,8 +83,19 @@
|
||||
</span>
|
||||
<Chevron expanded={!isCollapsed} outline fill={'var(--content-color'} />
|
||||
</div>
|
||||
{#if hasAccountRole(getCurrentAccount(), AccountRole.Maintainer) && isEditable}
|
||||
<div class="btns">
|
||||
<div class="btns">
|
||||
{#if (isLocked && canUnlock) || (!isLocked && canLock)}
|
||||
<div class="lock-btn">
|
||||
<Button
|
||||
icon={isLocked ? Unlock : Lock}
|
||||
kind={'link'}
|
||||
size={'medium'}
|
||||
showTooltip={{ label: isLocked ? card.string.UnLockSection : card.string.LockSection }}
|
||||
on:click={toggleLock}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{#if hasAccountRole(getCurrentAccount(), AccountRole.Maintainer) && isEditable}
|
||||
<Button
|
||||
icon={IconAdd}
|
||||
kind={'link'}
|
||||
@@ -95,8 +121,8 @@
|
||||
navigate(loc)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<ExpandCollapse isExpanded={!isCollapsed}>
|
||||
<CardAttributes object={value} _class={tag._id} to={tag.extends} {readonly} {ignoreKeys} />
|
||||
@@ -134,6 +160,14 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
visibility: hidden;
|
||||
|
||||
.lock-btn {
|
||||
opacity: 0.5;
|
||||
transition: opacity 0.2s;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { IconSize } from '@hcengineering/ui'
|
||||
|
||||
export let size: IconSize
|
||||
export let fill: string = 'currentColor'
|
||||
</script>
|
||||
|
||||
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M4.69141 14.6338H11.3018C12.2178 14.6338 12.6689 14.1826 12.6689 13.1914V8.08496C12.6689 7.18945 12.293 6.72461 11.541 6.64941V4.96094C11.541 2.36328 9.81152 1.1123 7.99316 1.1123C6.18164 1.1123 4.45215 2.36328 4.45215 4.96094V6.67676C3.74805 6.78613 3.32422 7.2373 3.32422 8.08496V13.1914C3.32422 14.1826 3.77539 14.6338 4.69141 14.6338ZM5.75098 4.83105C5.75098 3.22461 6.76953 2.35645 7.99316 2.35645C9.2168 2.35645 10.2422 3.22461 10.2422 4.83105V6.64258L5.75098 6.64941V4.83105Z"
|
||||
/>
|
||||
</svg>
|
||||
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { IconSize } from '@hcengineering/ui'
|
||||
|
||||
export let size: IconSize
|
||||
export let fill: string = 'currentColor'
|
||||
</script>
|
||||
|
||||
<svg class="svg-{size}" {fill} viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M2.33301 14.6338H8.94336C9.85938 14.6338 10.3105 14.1826 10.3105 13.1914V8.08496C10.3105 7.2168 9.95508 6.75195 9.24414 6.65625V4.83105C9.24414 3.22461 10.2627 2.35645 11.4863 2.35645C12.71 2.35645 13.7354 3.22461 13.7354 4.83105V6.28711C13.7354 6.76562 14.0156 7.01855 14.3848 7.01855C14.7471 7.01855 15.0273 6.7793 15.0273 6.28711V4.96094C15.0273 2.36328 13.2979 1.1123 11.4863 1.1123C9.6748 1.1123 7.94531 2.36328 7.94531 4.96094V6.64258L2.44922 6.64941C1.5332 6.64941 0.96582 7.10742 0.96582 8.08496V13.1914C0.96582 14.1826 1.41699 14.6338 2.33301 14.6338Z"
|
||||
/>
|
||||
</svg>
|
||||
@@ -73,7 +73,9 @@ export default mergeIds(cardId, card, {
|
||||
ForbidRemoveCard: '' as Ref<Permission>,
|
||||
ForbidUpdateCard: '' as Ref<Permission>,
|
||||
ForbidAddTag: '' as Ref<Permission>,
|
||||
ForbidRemoveTag: '' as Ref<Permission>
|
||||
ForbidRemoveTag: '' as Ref<Permission>,
|
||||
LockSection: '' as Ref<Permission>,
|
||||
UnlockSection: '' as Ref<Permission>
|
||||
},
|
||||
sectionComponent: {
|
||||
AttachmentsSection: '' as AnyComponent,
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Analytics } from '@hcengineering/analytics'
|
||||
import { type Card, CardEvents, cardId, type CardSpace, type MasterTag, type Tag } from '@hcengineering/card'
|
||||
import { chatId } from '@hcengineering/chat'
|
||||
import communication from '@hcengineering/communication'
|
||||
import { type PermissionsStore } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AccountRole,
|
||||
type Class,
|
||||
@@ -763,3 +764,19 @@ export async function canGetSpaceAccessPublicLink (doc?: Doc | Doc[]): Promise<b
|
||||
|
||||
return await canCopyLink(doc)
|
||||
}
|
||||
|
||||
export function canLockSection (space: Ref<Space>, store: PermissionsStore): boolean {
|
||||
if (getMetadata(core.metadata.DisablePermissions) === true) return true
|
||||
if (store.whitelist.has(space)) return true
|
||||
const allowed = store.ps[space]?.has(card.permission.LockSection)
|
||||
if (allowed) return true
|
||||
return !store.restrictedSpaces.has(space)
|
||||
}
|
||||
|
||||
export function canUnlockSection (space: Ref<Space>, store: PermissionsStore): boolean {
|
||||
if (getMetadata(core.metadata.DisablePermissions) === true) return true
|
||||
if (store.whitelist.has(space)) return true
|
||||
const allowed = store.ps[space]?.has(card.permission.UnlockSection)
|
||||
if (allowed) return true
|
||||
return !store.restrictedSpaces.has(space)
|
||||
}
|
||||
|
||||
@@ -206,7 +206,11 @@ const cardPlugin = plugin(cardId, {
|
||||
Favorites: '' as IntlString,
|
||||
CreateCard: '' as IntlString,
|
||||
Version: '' as IntlString,
|
||||
Versions: '' as IntlString
|
||||
Versions: '' as IntlString,
|
||||
LockSection: '' as IntlString,
|
||||
UnLockSection: '' as IntlString,
|
||||
SectionLocked: '' as IntlString,
|
||||
SectionUnlocked: '' as IntlString
|
||||
},
|
||||
section: {
|
||||
Attachments: '' as Ref<CardSection>,
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"@types/jest": "^29.5.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/activity": "workspace:^0.7.0",
|
||||
"@hcengineering/view": "workspace:^0.7.0",
|
||||
"@hcengineering/setting": "workspace:^0.7.0",
|
||||
"@hcengineering/card": "workspace:^0.7.0",
|
||||
|
||||
@@ -13,7 +13,22 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import activity from '@hcengineering/activity'
|
||||
import card, { Card, cardId, MasterTag, Tag } from '@hcengineering/card'
|
||||
import communication, { Direct } from '@hcengineering/communication'
|
||||
import {
|
||||
AddCollaboratorsEvent,
|
||||
CardEventType,
|
||||
CreatePeerEvent,
|
||||
MessageEventType,
|
||||
NotificationEventType,
|
||||
PeerEventType,
|
||||
RemoveCardEvent,
|
||||
ThreadPatchEvent,
|
||||
UpdateCardTypeEvent
|
||||
} from '@hcengineering/communication-sdk-types'
|
||||
import { CardPeer } from '@hcengineering/communication-types'
|
||||
import contact, { Employee, formatName, Person } from '@hcengineering/contact'
|
||||
import core, {
|
||||
AccountUuid,
|
||||
AnyAttribute,
|
||||
@@ -42,26 +57,12 @@ import core, {
|
||||
TxRemoveDoc,
|
||||
TxUpdateDoc
|
||||
} from '@hcengineering/core'
|
||||
import { getMetadata, translate } from '@hcengineering/platform'
|
||||
import { getEmployee, getPersonSpaces } from '@hcengineering/server-contact'
|
||||
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
||||
import setting from '@hcengineering/setting'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
import view from '@hcengineering/view'
|
||||
import {
|
||||
AddCollaboratorsEvent,
|
||||
CardEventType,
|
||||
NotificationEventType,
|
||||
PeerEventType,
|
||||
RemoveCardEvent,
|
||||
UpdateCardTypeEvent,
|
||||
CreatePeerEvent,
|
||||
ThreadPatchEvent,
|
||||
MessageEventType
|
||||
} from '@hcengineering/communication-sdk-types'
|
||||
import { getEmployee, getPersonSpaces } from '@hcengineering/server-contact'
|
||||
import contact, { Employee, formatName, Person } from '@hcengineering/contact'
|
||||
import communication, { Direct } from '@hcengineering/communication'
|
||||
import { CardPeer } from '@hcengineering/communication-types'
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import { workbenchId } from '@hcengineering/workbench'
|
||||
|
||||
async function OnAttribute (ctx: TxCreateDoc<AnyAttribute>[], control: TriggerControl): Promise<Tx[]> {
|
||||
const attr = TxProcessor.createDoc2Doc(ctx[0])
|
||||
@@ -433,6 +434,24 @@ async function OnCardUpdate (ctx: TxUpdateDoc<Card>[], control: TriggerControl):
|
||||
res.push(...(await updatePeers(control, doc, updateTx)))
|
||||
|
||||
await updateCollaborators(control, updateTx.operations, doc._class, doc, updateTx.modifiedBy)
|
||||
|
||||
const push = (updateTx.operations as any).$push?.readonlySections as Ref<Class<Doc>> | undefined
|
||||
const pull = (updateTx.operations as any).$pull?.readonlySections as Ref<Class<Doc>> | undefined
|
||||
const sectionId = push ?? pull
|
||||
if (sectionId !== undefined) {
|
||||
const sectionClass = control.hierarchy.getClass(sectionId)
|
||||
const label = sectionClass?.label ?? sectionId
|
||||
const section = await translate(label, {})
|
||||
res.push(
|
||||
control.txFactory.createTxCreateDoc(activity.class.ActivityInfoMessage, doc.space, {
|
||||
attachedTo: doc._id,
|
||||
attachedToClass: doc._class,
|
||||
message: push !== undefined ? card.string.SectionLocked : card.string.SectionUnlocked,
|
||||
props: { section },
|
||||
collection: 'activity'
|
||||
})
|
||||
)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user