From 34fc0024d326f0420590d4a25114ce4da04ed50b Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Mon, 24 Mar 2025 07:56:55 +0500 Subject: [PATCH] Card refs (#8319) --- models/card/src/index.ts | 102 ++++++++++------- .../src/components/AttributeBarEditor.svelte | 2 + .../src/components/AttributeEditor.svelte | 1 + plugins/card-assets/assets/icons.svg | 3 + plugins/card-assets/lang/cs.json | 3 +- plugins/card-assets/lang/de.json | 3 +- plugins/card-assets/lang/en.json | 3 +- plugins/card-assets/lang/es.json | 3 +- plugins/card-assets/lang/fr.json | 3 +- plugins/card-assets/lang/it.json | 3 +- plugins/card-assets/lang/pt.json | 3 +- plugins/card-assets/lang/ru.json | 3 +- plugins/card-assets/lang/zh.json | 3 +- plugins/card-assets/src/index.ts | 3 +- .../src/components/CardEditor.svelte | 105 ++++++++++++++++++ .../src/components/CardRefPresenter.svelte | 43 +++++++ .../src/components/CardsPopup.svelte | 64 +++++++++++ .../src/components/CreateTag.svelte | 4 +- .../src/components/MasterTagAttributes.svelte | 2 +- .../src/components/TagAttributes.svelte | 2 +- .../components/settings/ChildsSection.svelte | 1 - .../settings/ManageMasterTagsTools.svelte | 25 ++++- .../settings/ProperitiesSection.svelte | 9 +- .../components/settings/TagsHierarchy.svelte | 17 ++- plugins/card-resources/src/index.ts | 6 +- plugins/card-resources/src/plugin.ts | 7 +- plugins/card/src/index.ts | 6 +- .../src/components/ClassAttributes.svelte | 5 +- .../src/components/CreateAttribute.svelte | 11 +- .../components/CreateAttributePopup.svelte | 3 + .../components/typeEditors/ArrayEditor.svelte | 4 +- .../components/typeEditors/RefEditor.svelte | 51 ++++++--- 32 files changed, 410 insertions(+), 93 deletions(-) create mode 100644 plugins/card-resources/src/components/CardEditor.svelte create mode 100644 plugins/card-resources/src/components/CardRefPresenter.svelte create mode 100644 plugins/card-resources/src/components/CardsPopup.svelte diff --git a/models/card/src/index.ts b/models/card/src/index.ts index edd077863c..4e563768cd 100644 --- a/models/card/src/index.ts +++ b/models/card/src/index.ts @@ -43,7 +43,7 @@ import presentation from '@hcengineering/model-presentation' import setting from '@hcengineering/model-setting' import view, { createAction } from '@hcengineering/model-view' import workbench from '@hcengineering/model-workbench' -import { getEmbeddedLabel, type IntlString } from '@hcengineering/platform' +import { type Asset, getEmbeddedLabel, type IntlString } from '@hcengineering/platform' import time, { type ToDo } from '@hcengineering/time' import { type AnyComponent } from '@hcengineering/ui/src/types' import { type BuildModelKey } from '@hcengineering/view' @@ -102,58 +102,43 @@ export class MasterTagEditorSection extends TDoc implements MasterTagEditorSecti export * from './migration' -export function createModel (builder: Builder): void { - builder.createModel(TMasterTag, TTag, TCard, MasterTagEditorSection) +const listConfig: (BuildModelKey | string)[] = [ + { key: '', props: { showParent: true }, displayProps: { fixed: 'left', key: 'card' } }, + { key: '_class', displayProps: { fixed: 'left', key: 'type' } }, + { key: '', displayProps: { grow: true } }, + { + key: '', + presenter: view.component.RolePresenter, + label: card.string.Tags, + props: { fullSize: true }, + displayProps: { key: 'tags', fixed: 'right' } + }, + { + key: 'modifiedOn', + displayProps: { fixed: 'right', dividerBefore: true } + } +] +export function createSystemType ( + builder: Builder, + type: Ref, + label: IntlString, + icon: Asset = card.icon.MasterTag +): void { builder.createDoc( card.class.MasterTag, core.space.Model, { - label: attachment.string.File, + label, extends: card.class.Card, - icon: card.icon.File, + icon, kind: ClassifierKind.CLASS }, - card.types.File + type ) - builder.mixin(card.types.File, card.class.MasterTag, setting.mixin.Editable, { - value: false - }) - builder.createDoc(view.class.Viewlet, core.space.Model, { - attachTo: card.types.File, - descriptor: view.viewlet.Table, - configOptions: { - hiddenKeys: ['content', 'title'] - }, - config: [ - '', - '_class', - { key: '', presenter: view.component.RolePresenter, label: card.string.Tags, props: { fullSize: true } }, - 'modifiedOn' - ] - }) - - const listConfig: (BuildModelKey | string)[] = [ - { key: '', props: { showParent: true }, displayProps: { fixed: 'left', key: 'card' } }, - { key: '_class', displayProps: { fixed: 'left', key: 'type' } }, - { key: '', displayProps: { grow: true } }, - { - key: '', - presenter: view.component.RolePresenter, - label: card.string.Tags, - props: { fullSize: true }, - displayProps: { key: 'tags', fixed: 'right' } - }, - { - key: 'modifiedOn', - displayProps: { fixed: 'right', dividerBefore: true } - } - ] - - builder.createDoc(view.class.Viewlet, core.space.Model, { - attachTo: card.types.File, + attachTo: type, descriptor: view.viewlet.List, viewOptions: { groupBy: ['_class', 'createdBy', 'modifiedBy'], @@ -169,6 +154,31 @@ export function createModel (builder: Builder): void { config: listConfig }) + builder.mixin(type, card.class.MasterTag, setting.mixin.Editable, { + value: false + }) + + builder.createDoc(view.class.Viewlet, core.space.Model, { + attachTo: type, + descriptor: view.viewlet.Table, + configOptions: { + hiddenKeys: ['content', 'title'] + }, + config: [ + '', + '_class', + { key: '', presenter: view.component.RolePresenter, label: card.string.Tags, props: { fullSize: true } }, + 'modifiedOn' + ] + }) +} + +export function createModel (builder: Builder): void { + builder.createModel(TMasterTag, TTag, TCard, MasterTagEditorSection) + + createSystemType(builder, card.types.File, attachment.string.File, card.icon.File) + createSystemType(builder, card.types.Document, card.string.Document, card.icon.Document) + builder.createDoc( workbench.class.Application, core.space.Model, @@ -210,6 +220,10 @@ export function createModel (builder: Builder): void { card.action.SetParent ) + builder.mixin(card.class.Card, core.class.Class, view.mixin.AttributeEditor, { + inlineEditor: card.component.CardEditor + }) + createAction( builder, { @@ -304,6 +318,10 @@ export function createModel (builder: Builder): void { presenter: card.component.CardPresenter }) + builder.mixin(card.class.Card, core.class.Class, view.mixin.AttributePresenter, { + presenter: card.component.CardRefPresenter + }) + builder.mixin(card.class.Card, core.class.Class, activity.mixin.ActivityDoc, {}) builder.createDoc(activity.class.ActivityExtension, core.space.Model, { diff --git a/packages/presentation/src/components/AttributeBarEditor.svelte b/packages/presentation/src/components/AttributeBarEditor.svelte index 6bb9fed1f4..a315a178eb 100644 --- a/packages/presentation/src/components/AttributeBarEditor.svelte +++ b/packages/presentation/src/components/AttributeBarEditor.svelte @@ -103,6 +103,7 @@ {justify} type={attribute?.type} {maxWidth} + {attribute} {attributeKey} value={getAttribute(client, object, { key: attributeKey, attr: attribute })} space={object.space} @@ -123,6 +124,7 @@ disabled={isReadonly} space={object.space} {onChange} + {attribute} {focus} {object} {size} diff --git a/packages/presentation/src/components/AttributeEditor.svelte b/packages/presentation/src/components/AttributeEditor.svelte index 56ce7b4805..ecc4afd504 100644 --- a/packages/presentation/src/components/AttributeEditor.svelte +++ b/packages/presentation/src/components/AttributeEditor.svelte @@ -76,6 +76,7 @@ {focus} {focusIndex} {editKind} + {attribute} /> {/await} {/if} diff --git a/plugins/card-assets/assets/icons.svg b/plugins/card-assets/assets/icons.svg index 7aaa6b1033..8ca2248461 100644 --- a/plugins/card-assets/assets/icons.svg +++ b/plugins/card-assets/assets/icons.svg @@ -43,4 +43,7 @@ + + + diff --git a/plugins/card-assets/lang/cs.json b/plugins/card-assets/lang/cs.json index c716a42f63..626ffddf19 100644 --- a/plugins/card-assets/lang/cs.json +++ b/plugins/card-assets/lang/cs.json @@ -27,6 +27,7 @@ "Views": "Zobrazení", "CreateView": "Vytvořit zobrazení", "EditView": "Upravit zobrazení", - "SelectViewType": "Vybrat typ zobrazení" + "SelectViewType": "Vybrat typ zobrazení", + "Document": "Dokument" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/de.json b/plugins/card-assets/lang/de.json index e20121310d..60fbfada4b 100644 --- a/plugins/card-assets/lang/de.json +++ b/plugins/card-assets/lang/de.json @@ -27,6 +27,7 @@ "Views": "Ansichten", "CreateView": "Ansicht erstellen", "EditView": "Ansicht bearbeiten", - "SelectViewType": "Ansichtstyp auswählen" + "SelectViewType": "Ansichtstyp auswählen", + "Document": "Dokument" } } diff --git a/plugins/card-assets/lang/en.json b/plugins/card-assets/lang/en.json index 8365a5669d..8c0f960f45 100644 --- a/plugins/card-assets/lang/en.json +++ b/plugins/card-assets/lang/en.json @@ -27,6 +27,7 @@ "Views": "Views", "CreateView": "Create View", "EditView": "Edit View", - "SelectViewType": "Select View Type" + "SelectViewType": "Select View Type", + "Document": "Document" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/es.json b/plugins/card-assets/lang/es.json index 028eb69548..5b9e0a45c7 100644 --- a/plugins/card-assets/lang/es.json +++ b/plugins/card-assets/lang/es.json @@ -27,6 +27,7 @@ "Views": "Vistas", "CreateView": "Crear vista", "EditView": "Editar vista", - "SelectViewType": "Seleccionar tipo de vista" + "SelectViewType": "Seleccionar tipo de vista", + "Document": "Documento" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/fr.json b/plugins/card-assets/lang/fr.json index 9b885dce26..86edd2689c 100644 --- a/plugins/card-assets/lang/fr.json +++ b/plugins/card-assets/lang/fr.json @@ -27,6 +27,7 @@ "Views": "Vues", "CreateView": "Créer une vue", "EditView": "Modifier la vue", - "SelectViewType": "Sélectionner le type de vue" + "SelectViewType": "Sélectionner le type de vue", + "Document": "Document" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/it.json b/plugins/card-assets/lang/it.json index 4838b50173..48acc665f7 100644 --- a/plugins/card-assets/lang/it.json +++ b/plugins/card-assets/lang/it.json @@ -27,6 +27,7 @@ "Views": "Viste", "CreateView": "Crea vista", "EditView": "Modifica vista", - "SelectViewType": "Seleziona il tipo di vista" + "SelectViewType": "Seleziona il tipo di vista", + "Document": "Documento" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/pt.json b/plugins/card-assets/lang/pt.json index 0ebbeba6e7..a40411314b 100644 --- a/plugins/card-assets/lang/pt.json +++ b/plugins/card-assets/lang/pt.json @@ -27,6 +27,7 @@ "Views": "Visualizações", "CreateView": "Criar visualização", "EditView": "Editar visualização", - "SelectViewType": "Selecionar tipo de visualização" + "SelectViewType": "Selecionar tipo de visualização", + "Document": "Documento" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/ru.json b/plugins/card-assets/lang/ru.json index 0ea67180c6..2a463c31d4 100644 --- a/plugins/card-assets/lang/ru.json +++ b/plugins/card-assets/lang/ru.json @@ -27,6 +27,7 @@ "Views": "Представления", "CreateView": "Создать представление", "EditView": "Редактировать представление", - "SelectViewType": "Выбрать тип представления" + "SelectViewType": "Выбрать тип представления", + "Document": "Документ" } } \ No newline at end of file diff --git a/plugins/card-assets/lang/zh.json b/plugins/card-assets/lang/zh.json index 558e079fbb..59ed5c24e6 100644 --- a/plugins/card-assets/lang/zh.json +++ b/plugins/card-assets/lang/zh.json @@ -27,6 +27,7 @@ "Views": "视图", "CreateView": "创建视图", "EditView": "编辑视图", - "SelectViewType": "选择视图类型" + "SelectViewType": "选择视图类型", + "Document": "文档" } } \ No newline at end of file diff --git a/plugins/card-assets/src/index.ts b/plugins/card-assets/src/index.ts index e72b945e26..5bc6855c69 100644 --- a/plugins/card-assets/src/index.ts +++ b/plugins/card-assets/src/index.ts @@ -22,5 +22,6 @@ loadMetadata(card.icon, { Tag: `${icons}#tag`, Card: `${icons}#card`, File: `${icons}#file`, - View: `${icons}#view` + View: `${icons}#view`, + Document: `${icons}#document` }) diff --git a/plugins/card-resources/src/components/CardEditor.svelte b/plugins/card-resources/src/components/CardEditor.svelte new file mode 100644 index 0000000000..3f80552654 --- /dev/null +++ b/plugins/card-resources/src/components/CardEditor.svelte @@ -0,0 +1,105 @@ + + + + diff --git a/plugins/card-resources/src/components/CardRefPresenter.svelte b/plugins/card-resources/src/components/CardRefPresenter.svelte new file mode 100644 index 0000000000..c6ccc19c2f --- /dev/null +++ b/plugins/card-resources/src/components/CardRefPresenter.svelte @@ -0,0 +1,43 @@ + + + + diff --git a/plugins/card-resources/src/components/CardsPopup.svelte b/plugins/card-resources/src/components/CardsPopup.svelte new file mode 100644 index 0000000000..8ac4b13c14 --- /dev/null +++ b/plugins/card-resources/src/components/CardsPopup.svelte @@ -0,0 +1,64 @@ + + + + dispatch('close', doc.detail)} + {readonly} +> + +
+ {it.title} +
+
+ + + {@const cl = hierarchy.getClass(it._class)} + + +
diff --git a/plugins/card-resources/src/components/CreateTag.svelte b/plugins/card-resources/src/components/CreateTag.svelte index 720c6f306d..ab58ebb410 100644 --- a/plugins/card-resources/src/components/CreateTag.svelte +++ b/plugins/card-resources/src/components/CreateTag.svelte @@ -39,10 +39,10 @@ icon: isMasterTag ? card.icon.MasterTag : card.icon.Tag } - await client.createDoc(_class, core.space.Model, data) + const id = await client.createDoc(_class, core.space.Model, data) Analytics.handleEvent(isMasterTag ? CardEvents.TypeCreated : CardEvents.TagCreated) - dispatch('close') + dispatch('close', id) } diff --git a/plugins/card-resources/src/components/MasterTagAttributes.svelte b/plugins/card-resources/src/components/MasterTagAttributes.svelte index 405a8799d2..c9f8fc3c1b 100644 --- a/plugins/card-resources/src/components/MasterTagAttributes.svelte +++ b/plugins/card-resources/src/components/MasterTagAttributes.svelte @@ -70,7 +70,7 @@ size={'medium'} showTooltip={{ label: setting.string.AddAttribute }} on:click={(ev) => { - showPopup(setting.component.CreateAttributePopup, { _class: value._class }, 'top') + showPopup(setting.component.CreateAttributePopup, { _class: value._class, isCard: true }, 'top') }} /> diff --git a/plugins/card-resources/src/index.ts b/plugins/card-resources/src/index.ts index c6bcf2fbac..c48ba4db4a 100644 --- a/plugins/card-resources/src/index.ts +++ b/plugins/card-resources/src/index.ts @@ -38,6 +38,8 @@ import SetParentActionPopup from './components/SetParentActionPopup.svelte' import RelationSetting from './components/settings/RelationSetting.svelte' import ViewsSection from './components/settings/view/ViewsSection.svelte' import EditView from './components/settings/view/EditView.svelte' +import CardEditor from './components/CardEditor.svelte' +import CardRefPresenter from './components/CardRefPresenter.svelte' export default async (): Promise => ({ component: { @@ -57,7 +59,9 @@ export default async (): Promise => ({ SetParentActionPopup, RelationSetting, ViewsSection, - EditView + EditView, + CardEditor, + CardRefPresenter }, completion: { CardQuery: queryCard diff --git a/plugins/card-resources/src/plugin.ts b/plugins/card-resources/src/plugin.ts index 25017e425c..4177d2b16a 100644 --- a/plugins/card-resources/src/plugin.ts +++ b/plugins/card-resources/src/plugin.ts @@ -38,7 +38,9 @@ export default mergeIds(cardId, card, { SetParentActionPopup: '' as AnyComponent, RelationSetting: '' as AnyComponent, ViewsSection: '' as AnyComponent, - EditView: '' as AnyComponent + EditView: '' as AnyComponent, + CardEditor: '' as AnyComponent, + CardRefPresenter: '' as AnyComponent }, completion: { CardQuery: '' as Resource, @@ -71,6 +73,7 @@ export default mergeIds(cardId, card, { Children: '' as IntlString, CreateView: '' as IntlString, EditView: '' as IntlString, - SelectViewType: '' as IntlString + SelectViewType: '' as IntlString, + Document: '' as IntlString } }) diff --git a/plugins/card/src/index.ts b/plugins/card/src/index.ts index d7b32fbfe1..9208e96240 100644 --- a/plugins/card/src/index.ts +++ b/plugins/card/src/index.ts @@ -67,7 +67,8 @@ const cardPlugin = plugin(cardId, { MasterTagEditorSection: '' as Ref> }, types: { - File: '' as Ref + File: '' as Ref, + Document: '' as Ref }, icon: { MasterTags: '' as Asset, @@ -76,7 +77,8 @@ const cardPlugin = plugin(cardId, { Tags: '' as Asset, Card: '' as Asset, File: '' as Asset, - View: '' as Asset + View: '' as Asset, + Document: '' as Asset }, extensions: { EditCardExtension: '' as ComponentExtensionId diff --git a/plugins/setting-resources/src/components/ClassAttributes.svelte b/plugins/setting-resources/src/components/ClassAttributes.svelte index 5bf5eead7e..954ddb536e 100644 --- a/plugins/setting-resources/src/components/ClassAttributes.svelte +++ b/plugins/setting-resources/src/components/ClassAttributes.svelte @@ -46,6 +46,7 @@ export let showTitle: boolean = !showHierarchy export let showHeader: boolean = true export let disabled: boolean = true + export let isCard: boolean = false export let attributeMapper: | { component: AnySvelteComponent @@ -90,7 +91,9 @@ } showPopup(TypesPopup, { _class }, getEventPositionElement(ev), (_id) => { - if (_id !== undefined) $settingsStore = { component: CreateAttribute, props: { selectedType: _id, _class } } + if (_id !== undefined) { + $settingsStore = { component: CreateAttribute, props: { selectedType: _id, _class, isCard } } + } }) } diff --git a/plugins/setting-resources/src/components/CreateAttribute.svelte b/plugins/setting-resources/src/components/CreateAttribute.svelte index d354d54190..f14b44c345 100644 --- a/plugins/setting-resources/src/components/CreateAttribute.svelte +++ b/plugins/setting-resources/src/components/CreateAttribute.svelte @@ -46,6 +46,7 @@ export let _id: Ref>> | undefined = undefined export let _class: Ref> + export let isCard: boolean = false let name: string let icon: Asset | undefined @@ -93,19 +94,20 @@ const items = getTypes() export let selectedType: Ref>> | undefined = undefined - $: selectedType && selectType(selectedType) + $: selectType(selectedType) - function selectType (type: Ref>>): void { + function selectType (type: Ref>> | undefined): void { + if (type === undefined) return const _class = hierarchy.getClass(type) const editor = hierarchy.as(_class, view.mixin.ObjectEditor) if (editor.editor !== undefined) { is = editor.editor } } - const handleSelection = (e: { detail: Ref>> }) => { + const handleSelection = (e: { detail: Ref>> }): void => { selectType(e.detail) } - const handleChange = (e: any) => { + const handleChange = (e: any): void => { type = e.detail?.type index = e.detail?.index defaultValue = e.detail?.defaultValue @@ -169,6 +171,7 @@ props={{ type, defaultValue, + isCard, kind: 'regular', size: 'large' }} diff --git a/plugins/setting-resources/src/components/CreateAttributePopup.svelte b/plugins/setting-resources/src/components/CreateAttributePopup.svelte index 0f76b75bc1..90a1b45421 100644 --- a/plugins/setting-resources/src/components/CreateAttributePopup.svelte +++ b/plugins/setting-resources/src/components/CreateAttributePopup.svelte @@ -42,6 +42,8 @@ import { IconPicker } from '@hcengineering/view-resources' export let _class: Ref> + export let isCard: boolean = false + let selectedType: Ref>> | undefined = undefined let name: string @@ -159,6 +161,7 @@ props={{ type, defaultValue, + isCard, kind: 'regular', size: 'large' }} diff --git a/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte b/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte index c1ed07a70c..38ebb6d2e3 100644 --- a/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte +++ b/plugins/setting-resources/src/components/typeEditors/ArrayEditor.svelte @@ -26,6 +26,7 @@ export let editable: boolean = true export let kind: ButtonKind = 'regular' export let size: ButtonSize = 'medium' + export let isCard: boolean = false const dispatch = createEventDispatcher() const client = getClient() @@ -49,7 +50,7 @@ $: selected = types.find((p) => p._id === refClass) - const handleChange = (e: any) => { + const handleChange = (e: any): void => { const type = e.detail?.type const res = { type: createArrOf(type) } dispatch('change', res) @@ -86,6 +87,7 @@ props={{ type: type?.of, nested: true, + isCard, editable, kind, size diff --git a/plugins/setting-resources/src/components/typeEditors/RefEditor.svelte b/plugins/setting-resources/src/components/typeEditors/RefEditor.svelte index 611a535a49..c3a228f6b7 100644 --- a/plugins/setting-resources/src/components/typeEditors/RefEditor.svelte +++ b/plugins/setting-resources/src/components/typeEditors/RefEditor.svelte @@ -18,37 +18,58 @@ import { getClient } from '@hcengineering/presentation' import { DropdownLabelsIntl, Label } from '@hcengineering/ui' import view from '@hcengineering/view-resources/src/plugin' + import card from '@hcengineering/card' import { createEventDispatcher } from 'svelte' - import type { ButtonKind, ButtonSize } from '@hcengineering/ui' + import type { ButtonKind, ButtonSize, DropdownIntlItem } from '@hcengineering/ui' + import contactPlugin from '@hcengineering/contact' export let type: RefTo | undefined export let editable: boolean = true export let kind: ButtonKind = 'regular' export let size: ButtonSize = 'medium' + export let isCard: boolean = false + + const _classes = isCard ? [card.class.Card, contactPlugin.class.Contact] : [core.class.Doc] + const exclude = !isCard ? [card.class.Card] : [] const dispatch = createEventDispatcher() const client = getClient() const hierarchy = client.getHierarchy() - const descendants = hierarchy.getDescendants(core.class.Doc) - const classes = descendants - .map((p) => hierarchy.getClass(p)) - .filter((p) => { - return ( - hierarchy.hasMixin(p, view.mixin.AttributeEditor) && - p.label !== undefined && - hierarchy.getDomain(p._id) !== DOMAIN_STATUS - ) - }) - .map((p) => { - return { id: p._id, label: p.label } - }) + const classes = fillClasses(_classes, exclude) + + function fillClasses (classes: Ref>[], exclude: Ref>[]): DropdownIntlItem[] { + const res: DropdownIntlItem[] = [] + const descendants = new Set( + classes + .map((p) => hierarchy.getDescendants(p)) + .reduce((a, b) => a.concat(b)) + .filter((p) => p !== card.class.Card) + ) + const excluded = new Set() + for (const _class of exclude) { + const desc = hierarchy.getDescendants(_class) + for (const _id of desc) { + excluded.add(_id) + } + } + for (const desc of descendants) { + if (excluded.has(desc)) continue + const domain = hierarchy.findDomain(desc) + if (domain === DOMAIN_STATUS || domain === undefined) continue + if (hierarchy.classHierarchyMixin(desc, view.mixin.AttributeEditor) === undefined) continue + const _class = hierarchy.getClass(desc) + if (_class.label === undefined) continue + res.push({ id: _class._id, label: _class.label }) + } + return res + } let refClass: Ref> | undefined = type?.to $: selected = classes.find((p) => p.id === refClass) - $: refClass && dispatch('change', { type: TypeRef(refClass) }) + $: refClass !== undefined && dispatch('change', { type: TypeRef(refClass) })