diff --git a/models/core/src/core.ts b/models/core/src/core.ts index 0215f7b635..69e5b3dbf2 100644 --- a/models/core/src/core.ts +++ b/models/core/src/core.ts @@ -14,6 +14,13 @@ // import { + DOMAIN_BLOB, + DOMAIN_CONFIGURATION, + DOMAIN_DOC_INDEX_STATE, + DOMAIN_FULLTEXT_BLOB, + DOMAIN_MIGRATION, + DOMAIN_MODEL, + IndexKind, type Account, type AnyAttribute, type ArrOf, @@ -27,21 +34,15 @@ import { type Doc, type DocIndexState, type Domain, - DOMAIN_BLOB, - DOMAIN_CONFIGURATION, - DOMAIN_MIGRATION, - DOMAIN_DOC_INDEX_STATE, - DOMAIN_FULLTEXT_BLOB, - DOMAIN_MODEL, type Enum, type EnumOf, type FieldIndex, type FullTextData, type FullTextSearchContext, - type IndexingConfiguration, - IndexKind, type IndexStageState, + type IndexingConfiguration, type Interface, + type MigrationState, type Mixin, type Obj, type PluginConfiguration, @@ -50,8 +51,8 @@ import { type Space, type Timestamp, type Type, - type Version, - type MigrationState + type TypeAny, + type Version } from '@hcengineering/core' import { Hidden, @@ -243,6 +244,13 @@ export class TEnumOf extends TType implements EnumOf { of!: Ref } +@UX(getEmbeddedLabel('Any')) +@Model(core.class.TypeAny, core.class.Type) +export class TTypeAny extends TType implements TypeAny { + presenter!: any + editor!: any +} + @Model(core.class.Version, core.class.Doc, DOMAIN_MODEL) export class TVersion extends TDoc implements Version { major!: number diff --git a/models/core/src/index.ts b/models/core/src/index.ts index ac4e906398..0a72723527 100644 --- a/models/core/src/index.ts +++ b/models/core/src/index.ts @@ -15,13 +15,13 @@ import { AccountRole, + systemAccountEmail, type AttachedDoc, type Class, type Doc, type DocIndexState, type IndexingConfiguration, - type TxCollectionCUD, - systemAccountEmail + type TxCollectionCUD } from '@hcengineering/core' import { type Builder } from '@hcengineering/model' import core from './component' @@ -49,6 +49,7 @@ import { TPluginConfiguration, TRefTo, TType, + TTypeAny, TTypeAttachment, TTypeBoolean, TTypeCollaborativeMarkup, @@ -126,6 +127,7 @@ export function createModel (builder: Builder): void { TPluginConfiguration, TUserStatus, TEnum, + TTypeAny, TBlobData, TFulltextData, TTypeRelatedDocument, diff --git a/packages/core/src/classes.ts b/packages/core/src/classes.ts index 80ca0612ed..3f0578151b 100644 --- a/packages/core/src/classes.ts +++ b/packages/core/src/classes.ts @@ -291,6 +291,16 @@ export interface EnumOf extends Type { */ export interface TypeHyperlink extends Type {} +/** + * @public + * + * A type for some custom serialized field with a set of editors + */ +export interface TypeAny extends Type { + presenter: AnyComponent + editor?: AnyComponent +} + /** * @public */ diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 66da30d6ce..9addc59fbd 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -45,6 +45,7 @@ import type { Space, Timestamp, Type, + TypeAny, UserStatus } from './classes' import { Status, StatusCategory } from './status' @@ -109,6 +110,7 @@ export default plugin(coreId, { Enum: '' as Ref>, EnumOf: '' as Ref>, Collection: '' as Ref>>, + TypeAny: '' as Ref>, Version: '' as Ref>, PluginConfiguration: '' as Ref>, UserStatus: '' as Ref>, diff --git a/packages/model/src/dsl.ts b/packages/model/src/dsl.ts index 2d4819c45b..944ff9a18d 100644 --- a/packages/model/src/dsl.ts +++ b/packages/model/src/dsl.ts @@ -15,25 +15,22 @@ import core, { Account, - ArrOf as TypeArrOf, AttachedDoc, Attribute, Class, Classifier, ClassifierKind, - Collection as TypeCollection, Data, DateRangeMode, Doc, Domain, Enum, EnumOf, - generateId, Hyperlink, + Mixin as IMixin, IndexKind, Interface, Markup, - Mixin as IMixin, MixinUpdate, Obj, PropertyType, @@ -46,7 +43,11 @@ import core, { TxFactory, TxProcessor, Type, - TypeDate as TypeDateType + TypeAny as TypeAnyType, + ArrOf as TypeArrOf, + Collection as TypeCollection, + TypeDate as TypeDateType, + generateId } from '@hcengineering/core' import type { Asset, IntlString } from '@hcengineering/platform' import toposort from 'toposort' @@ -464,6 +465,17 @@ export function TypeEnum (of: Ref): EnumOf { return { _class: core.class.EnumOf, label: core.string.Enum, of } } +/** + * @public + */ +export function TypeAny ( + presenter: AnyComponent, + label: IntlString, + editor?: AnyComponent +): TypeAnyType { + return { _class: core.class.TypeAny, label, presenter, editor } +} + /** * @public */ diff --git a/packages/presentation/src/components/AttributeBarEditor.svelte b/packages/presentation/src/components/AttributeBarEditor.svelte index cccf6d3841..2caa299a94 100644 --- a/packages/presentation/src/components/AttributeBarEditor.svelte +++ b/packages/presentation/src/components/AttributeBarEditor.svelte @@ -40,7 +40,7 @@ const dispatch = createEventDispatcher() let editor: AnySvelteComponent | undefined - function onChange (value: any) { + function onChange (value: any): void { const doc = object as Doc dispatch('update', { key, value }) @@ -48,12 +48,14 @@ if (draft) { ;(doc as any)[attributeKey] = value } else { - updateAttribute(client, doc, doc._class, { key: attributeKey, attr: attribute }, value) + void updateAttribute(client, doc, doc._class, { key: attributeKey, attr: attribute }, value) } } - function getEditor (_class: Ref>, key: KeyedAttribute | string) { - getAttributeEditor(client, _class, key).then((p) => (editor = p)) + function getEditor (_class: Ref>, key: KeyedAttribute | string): void { + void getAttributeEditor(client, _class, key).then((p) => { + editor = p + }) } $: getEditor(_class, key) diff --git a/packages/presentation/src/components/AttributeEditor.svelte b/packages/presentation/src/components/AttributeEditor.svelte index 4b1712bf16..7f1f1c99de 100644 --- a/packages/presentation/src/components/AttributeEditor.svelte +++ b/packages/presentation/src/components/AttributeEditor.svelte @@ -48,10 +48,10 @@ } } - function onChange (value: any) { + function onChange (value: any): void { if (!editable) return const doc = object as Doc - updateAttribute(client, doc, _class, { key: attributeKey, attr: attribute }, value) + void updateAttribute(client, doc, _class, { key: attributeKey, attr: attribute }, value) } diff --git a/packages/presentation/src/utils.ts b/packages/presentation/src/utils.ts index a5596daa7c..0b477d2cf2 100644 --- a/packages/presentation/src/utils.ts +++ b/packages/presentation/src/utils.ts @@ -15,6 +15,9 @@ // import core, { + TxOperations, + type TypeAny, + getCurrentAccount, type AnyAttribute, type ArrOf, type AttachedDoc, @@ -25,28 +28,26 @@ import core, { type DocumentQuery, type FindOptions, type FindResult, - getCurrentAccount, type Hierarchy, type Mixin, type Obj, type Ref, type RefTo, - type Tx, - TxOperations, - type TxResult, - type WithLookup, - type SearchQuery, type SearchOptions, - type SearchResult + type SearchQuery, + type SearchResult, + type Tx, + type TxResult, + type WithLookup } from '@hcengineering/core' import { getMetadata, getResource } from '@hcengineering/platform' import { LiveQuery as LQ } from '@hcengineering/query' -import { type AnySvelteComponent, type IconSize } from '@hcengineering/ui' +import { type AnyComponent, type AnySvelteComponent, type IconSize } from '@hcengineering/ui' import view, { type AttributeEditor } from '@hcengineering/view' import { deepEqual } from 'fast-equals' import { onDestroy } from 'svelte' import { type KeyedAttribute } from '..' -import { OptimizeQueryMiddleware, type PresentationPipeline, PresentationPipelineImpl } from './pipeline' +import { OptimizeQueryMiddleware, PresentationPipelineImpl, type PresentationPipeline } from './pipeline' import plugin from './plugin' let liveQuery: LQ @@ -406,6 +407,12 @@ export async function getAttributeEditor ( ): Promise { const hierarchy = client.getHierarchy() const attribute = typeof key === 'string' ? hierarchy.getAttribute(_class, key) : key.attr + + if (attribute.type._class === core.class.TypeAny) { + const _type: TypeAny = attribute.type as TypeAny + return await getResource(_type.editor ?? _type.presenter) + } + const presenterClass = attribute !== undefined ? getAttributePresenterClass(hierarchy, attribute) : undefined if (presenterClass === undefined) { diff --git a/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte b/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte index a27a69c540..ba3e9ebaef 100644 --- a/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte +++ b/plugins/tracker-resources/src/components/issues/edit/EditIssue.svelte @@ -19,13 +19,14 @@ import { Panel } from '@hcengineering/panel' import { getResource } from '@hcengineering/platform' import presentation, { - createQuery, - getClient, ActionContext, + ComponentExtensions, contextStore, - ComponentExtensions + createQuery, + getClient } from '@hcengineering/presentation' import setting, { settingId } from '@hcengineering/setting' + import { taskTypeStore, typeStore } from '@hcengineering/task-resources' import { Issue, Project } from '@hcengineering/tracker' import { AnyComponent, @@ -42,8 +43,8 @@ navigate, showPopup } from '@hcengineering/ui' - import { ContextMenu, DocNavLink, ParentsNavigator } from '@hcengineering/view-resources' import view from '@hcengineering/view' + import { ContextMenu, DocNavLink, ParentsNavigator } from '@hcengineering/view-resources' import { createEventDispatcher, onDestroy } from 'svelte' import { generateIssueShortLink, getIssueId } from '../../../issues' import tracker from '../../../plugin' @@ -161,6 +162,10 @@ $: editorFooter = getEditorFooter(issue?._class) let content: HTMLElement + + $: taskType = issue?.kind !== undefined ? $taskTypeStore.get(issue?.kind) : undefined + + $: projectType = taskType?.parent !== undefined ? $typeStore.get(taskType.parent) : undefined {#if !embedded} @@ -187,12 +192,24 @@ on:select > - {#if !embedded}{/if} + {#if !embedded} + + {/if} {#if embedded && issueId}
{issueId}
- {:else if issueId}
{issueId}
{/if} + {:else if issueId} +
{issueId}
+ {/if} + + {#if (projectType?.tasks.length ?? 0) > 1 && taskType !== undefined} + ({taskType.name}) + {/if} +
,