mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-30 05:25:00 +02:00
Show doc attrs and collaborators for cards (#10390)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Vendored
+1
-1
@@ -97,7 +97,7 @@
|
||||
"MODEL_JSON": "${workspaceRoot}/models/all/bundle/model.json",
|
||||
// "SERVER_PROVIDER":"uweb"
|
||||
"SERVER_PROVIDER": "ws",
|
||||
"MODEL_VERSION": "0.7.331",
|
||||
"MODEL_VERSION": "0.7.343",
|
||||
// "version": "0.7.0",
|
||||
"COMMUNICATION_API_ENABLED": "true",
|
||||
"ELASTIC_INDEX_NAME": "local_storage_index",
|
||||
|
||||
@@ -944,6 +944,7 @@ export type SocialKey = Pick<SocialId, 'type' | 'value'>
|
||||
|
||||
export interface ClassCollaborators<T extends Doc> extends Doc {
|
||||
attachedTo: Ref<Class<T>>
|
||||
allFields?: boolean // for all (PersonId | Ref<Employee> | PersonId[] | Ref<Employee>[]) attributes
|
||||
fields: (keyof T)[] // PersonId | Ref<Employee> | PersonId[] | Ref<Employee>[]
|
||||
provideSecurity?: boolean // If true, will provide security for collaborators
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import core, {
|
||||
AccountRole,
|
||||
type Blobs,
|
||||
type Class,
|
||||
type ClassCollaborators,
|
||||
ClassifierKind,
|
||||
type CollectionSize,
|
||||
type Doc,
|
||||
@@ -860,6 +861,12 @@ export function createModel (builder: Builder): void {
|
||||
})
|
||||
|
||||
createPublicLinkAction(builder, card.class.Card, card.action.PublicLink)
|
||||
|
||||
builder.createDoc<ClassCollaborators<Card>>(core.class.ClassCollaborators, core.space.Model, {
|
||||
attachedTo: card.class.Card,
|
||||
fields: ['modifiedBy'],
|
||||
allFields: true
|
||||
})
|
||||
}
|
||||
|
||||
function defineTabs (builder: Builder): void {
|
||||
|
||||
@@ -413,6 +413,7 @@ export class TCustomSequence extends TSequence implements CustomSequence {
|
||||
@Model(core.class.ClassCollaborators, core.class.Doc, DOMAIN_MODEL)
|
||||
export class TClassCollaborators extends TDoc implements ClassCollaborators<Doc> {
|
||||
attachedTo!: Ref<Class<Doc>>
|
||||
allFields?: boolean
|
||||
fields!: (keyof Doc)[]
|
||||
provideSecurity?: boolean
|
||||
}
|
||||
|
||||
@@ -1367,6 +1367,10 @@ export function createModel (builder: Builder): void {
|
||||
searchDisabled: true
|
||||
})
|
||||
|
||||
builder.mixin(core.class.TypePersonId, core.class.Class, view.mixin.AttributeEditor, {
|
||||
inlineEditor: view.component.PersonIdPresenter
|
||||
})
|
||||
|
||||
builder.mixin(core.class.TypePersonId, core.class.Class, view.mixin.AttributePresenter, {
|
||||
presenter: view.component.PersonIdPresenter,
|
||||
arrayPresenter: view.component.PersonArrayEditor
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
import { PermissionsStore } from '@hcengineering/contact'
|
||||
import { permissionsStore } from '@hcengineering/contact-resources'
|
||||
import core, { AnyAttribute, Class, Doc, Ref, toRank, TypedSpace } from '@hcengineering/core'
|
||||
import notification from '@hcengineering/notification'
|
||||
import {
|
||||
AttributeBarEditor,
|
||||
createQuery,
|
||||
getClient,
|
||||
getFiltredKeys,
|
||||
isCollectionAttr,
|
||||
KeyedAttribute
|
||||
} from '@hcengineering/presentation'
|
||||
@@ -29,11 +29,12 @@
|
||||
|
||||
export let object: Card
|
||||
export let _class: Ref<Class<Doc>>
|
||||
export let to: Ref<Class<Doc>> | undefined = core.class.Doc
|
||||
export let to: Ref<Class<Doc>> | undefined = core.class.Obj
|
||||
export let ignoreKeys: string[] = []
|
||||
export let readonly = false
|
||||
export let showHeader: boolean = true
|
||||
export let fourRows: boolean = false
|
||||
export let showCollaborators: boolean = false
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
@@ -41,14 +42,18 @@
|
||||
let keys: KeyedAttribute[] = []
|
||||
|
||||
function updateKeys (_class: Ref<Class<Doc>>, ignoreKeys: string[], to: Ref<Class<Doc>> | undefined): void {
|
||||
const filtredKeys = getFiltredKeys(hierarchy, _class, ignoreKeys, to)
|
||||
keys = filtredKeys
|
||||
.filter((key) => !isCollectionAttr(hierarchy, key))
|
||||
.sort((a, b) => {
|
||||
const rankA = a.attr.rank ?? toRank(a.attr._id) ?? ''
|
||||
const rankB = b.attr.rank ?? toRank(b.attr._id) ?? ''
|
||||
return rankA.localeCompare(rankB)
|
||||
})
|
||||
const filtredKeys = [...hierarchy.getAllAttributes(_class, to).entries()]
|
||||
.filter(
|
||||
([key, value]) =>
|
||||
value.hidden !== true && !ignoreKeys.includes(key) && !isCollectionAttr(hierarchy, { key, attr: value })
|
||||
)
|
||||
.map(([key, attr]) => ({ key, attr }))
|
||||
|
||||
keys = filtredKeys.sort((a, b) => {
|
||||
const rankA = a.attr.rank ?? toRank(a.attr._id) ?? ''
|
||||
const rankB = b.attr.rank ?? toRank(b.attr._id) ?? ''
|
||||
return rankA.localeCompare(rankB)
|
||||
})
|
||||
}
|
||||
|
||||
$: updateKeys(_class, ignoreKeys, to)
|
||||
@@ -75,6 +80,17 @@
|
||||
on:update
|
||||
/>
|
||||
{/each}
|
||||
{#if showCollaborators}
|
||||
<AttributeBarEditor
|
||||
key={'collaborators'}
|
||||
_class={notification.mixin.Collaborators}
|
||||
{object}
|
||||
{showHeader}
|
||||
{readonly}
|
||||
withIcon
|
||||
on:update
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
<ExpandCollapse isExpanded={!isCollapsed}>
|
||||
<CardAttributes object={value} _class={value._class} {readonly} {ignoreKeys} {fourRows} />
|
||||
<CardAttributes object={value} _class={value._class} {readonly} {ignoreKeys} {fourRows} showCollaborators />
|
||||
</ExpandCollapse>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
export let ignoreKeys: string[]
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const label = hierarchy.getClass(tag._id).label
|
||||
const h = client.getHierarchy()
|
||||
const label = h.getClass(tag._id).label
|
||||
|
||||
let isCollapsed = false
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
}
|
||||
|
||||
$: color = getPlatformColorDef(tag.background ?? 0, $themeStore.dark).color
|
||||
|
||||
$: isEditable = h.hasMixin(tag, setting.mixin.Editable) && h.as(tag, setting.mixin.Editable).value
|
||||
</script>
|
||||
|
||||
<div class="header flex flex-gap-2">
|
||||
@@ -66,7 +68,7 @@
|
||||
</span>
|
||||
<Chevron expanded={!isCollapsed} outline fill={'var(--content-color'} />
|
||||
</div>
|
||||
{#if hasAccountRole(getCurrentAccount(), AccountRole.Maintainer)}
|
||||
{#if hasAccountRole(getCurrentAccount(), AccountRole.Maintainer) && isEditable}
|
||||
<div class="btns">
|
||||
<Button
|
||||
icon={IconAdd}
|
||||
|
||||
@@ -311,14 +311,30 @@ export async function getDocCollaborators (
|
||||
control: TriggerControl
|
||||
): Promise<AccountUuid[]> {
|
||||
const collaborators = new Set<AccountUuid>()
|
||||
for (const field of mixin.fields) {
|
||||
const value = (doc as any)[field]
|
||||
const newCollaborators = await ctx.with('getKeyCollaborators', {}, (ctx) =>
|
||||
getKeyCollaborators(doc._class, value, field, control)
|
||||
)
|
||||
if (newCollaborators !== undefined) {
|
||||
for (const newCollaborator of newCollaborators) {
|
||||
collaborators.add(newCollaborator)
|
||||
if (mixin.allFields !== true) {
|
||||
for (const field of mixin.fields) {
|
||||
const value = (doc as any)[field]
|
||||
const newCollaborators = await ctx.with('getKeyCollaborators', {}, (ctx) =>
|
||||
getKeyCollaborators(doc._class, value, field, control)
|
||||
)
|
||||
if (newCollaborators !== undefined) {
|
||||
for (const newCollaborator of newCollaborators) {
|
||||
collaborators.add(newCollaborator)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const attrs = control.hierarchy.getAllAttributes(doc._class)
|
||||
// attr type will be checked into getKeyCollaborators
|
||||
for (const [field] of attrs) {
|
||||
const value = (doc as any)[field]
|
||||
const newCollaborators = await ctx.with('getKeyCollaborators', {}, (ctx) =>
|
||||
getKeyCollaborators(doc._class, value, field, control)
|
||||
)
|
||||
if (newCollaborators !== undefined) {
|
||||
for (const newCollaborator of newCollaborators) {
|
||||
collaborators.add(newCollaborator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1137,7 +1153,7 @@ async function getNewCollaborators (
|
||||
const newCollaborators = new Set<AccountUuid>()
|
||||
if (ops.$push !== undefined) {
|
||||
for (const key in ops.$push) {
|
||||
if (mixin.fields.includes(key as any)) {
|
||||
if (mixin.fields.includes(key as any) || mixin.allFields === true) {
|
||||
let value = (ops.$push as any)[key]
|
||||
if (typeof value !== 'string') {
|
||||
value = value.$each
|
||||
@@ -1153,7 +1169,7 @@ async function getNewCollaborators (
|
||||
}
|
||||
for (const key in ops) {
|
||||
if (key.startsWith('$')) continue
|
||||
if (mixin.fields.includes(key as any)) {
|
||||
if (mixin.fields.includes(key as any) || mixin.allFields === true) {
|
||||
const value = (ops as any)[key]
|
||||
const newCollabs = await getKeyCollaborators(docClass, value, key, control)
|
||||
if (newCollabs !== undefined) {
|
||||
@@ -1176,7 +1192,7 @@ async function getRemovedMembers (
|
||||
const removedCollaborators: AccountUuid[] = []
|
||||
if (ops.$pull !== undefined && 'members' in ops.$pull) {
|
||||
const key = 'members'
|
||||
if (mixin.fields.includes(key as any)) {
|
||||
if (mixin.fields.includes(key as any) || mixin.allFields === true) {
|
||||
let value = (ops.$pull as any)[key]
|
||||
if (typeof value !== 'string') {
|
||||
value = value.$in
|
||||
|
||||
Reference in New Issue
Block a user