Search for the attribute editor throughout the hierarchy (#2647)

Signed-off-by: Sergei Ogorelkov <sergei.ogorelkov@xored.com>
This commit is contained in:
Sergei Ogorelkov 2023-02-16 21:14:47 +06:00 committed by GitHub
parent e8d6a10ab3
commit acc5e124a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 39 deletions

View File

@ -14,13 +14,11 @@
// limitations under the License.
-->
<script lang="ts">
import type { AnyAttribute, Class, Doc, Ref } from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
import type { Class, Doc, Ref } from '@hcengineering/core'
import { AnySvelteComponent, Label, tooltip } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import { getAttribute, KeyedAttribute, updateAttribute } from '../attributes'
import { AttributeCategory, getAttributePresenterClass, getClient } from '../utils'
import { getAttributeEditor, getClient } from '../utils'
export let key: KeyedAttribute | string
export let object: Doc | Record<string, any>
@ -33,42 +31,10 @@
const client = getClient()
const hierarchy = client.getHierarchy()
const dispatch = createEventDispatcher()
$: attribute = typeof key === 'string' ? hierarchy.getAttribute(_class, key) : key.attr
$: attributeKey = typeof key === 'string' ? key : key.key
$: presenterClass = attribute !== undefined ? getAttributePresenterClass(hierarchy, attribute) : undefined
let editor: Promise<void | AnySvelteComponent> | undefined
function update (
attribute: AnyAttribute,
presenterClass?: { attrClass: Ref<Class<Doc>>; category: AttributeCategory }
): void {
if (presenterClass?.attrClass === undefined) {
return
}
const category = presenterClass.category
let mixinRef = view.mixin.AttributeEditor
if (category === 'collection') {
mixinRef = view.mixin.CollectionEditor
}
if (category === 'array') {
mixinRef = view.mixin.ArrayEditor
}
const typeClass = hierarchy.getClass(presenterClass.attrClass)
const editorMixin = hierarchy.as(typeClass, mixinRef)
if (category === 'array' && editorMixin.inlineEditor === undefined) {
return
}
editor = getResource(editorMixin.inlineEditor).catch((cause) => {
console.error(`failed to find editor for ${_class} ${attribute} ${presenterClass.attrClass} cause: ${cause}`)
})
}
$: update(attribute, presenterClass)
function onChange (value: any) {
const doc = object as Doc
if (draft) {
@ -78,6 +44,10 @@
updateAttribute(client, doc, _class, { key: attributeKey, attr: attribute }, value)
}
}
$: attribute = typeof key === 'string' ? hierarchy.getAttribute(_class, key) : key.attr
$: attributeKey = typeof key === 'string' ? key : key.key
$: editor = getAttributeEditor(client, _class, key)
$: isReadonly = (attribute.readonly ?? false) || readonly
</script>

View File

@ -27,6 +27,8 @@ import core, {
FindResult,
getCurrentAccount,
Hierarchy,
Mixin,
Obj,
Ref,
RefTo,
Tx,
@ -34,13 +36,14 @@ import core, {
TxResult
} from '@hcengineering/core'
import login from '@hcengineering/login'
import { getMetadata, IntlString } from '@hcengineering/platform'
import { getMetadata, getResource, IntlString } from '@hcengineering/platform'
import { LiveQuery as LQ } from '@hcengineering/query'
import { onDestroy } from 'svelte'
import { deepEqual } from 'fast-equals'
import { IconSize, DropdownIntlItem } from '@hcengineering/ui'
import { IconSize, DropdownIntlItem, AnySvelteComponent } from '@hcengineering/ui'
import view, { AttributeEditor } from '@hcengineering/view'
import contact, { AvatarType, AvatarProvider } from '@hcengineering/contact'
import presentation from '..'
import presentation, { KeyedAttribute } from '..'
let liveQuery: LQ
let client: TxOperations
@ -313,3 +316,69 @@ export function getCategorytitle (category: AssigneeCategory | undefined): IntlS
const cat: AssigneeCategory = category ?? 'Other'
return assigneeCategoryTitleMap[cat]
}
function getAttributeEditorNotFoundError (
_class: Ref<Class<Obj>>,
key: KeyedAttribute | string,
exception?: unknown
): string {
const attributeKey = typeof key === 'string' ? key : key.key
const error = exception !== undefined ? `, cause: ${exception as string}` : ''
return `attribute editor not found for class "${_class}", attribute "${attributeKey}"` + error
}
export async function getAttributeEditor (
client: Client,
_class: Ref<Class<Obj>>,
key: KeyedAttribute | string
): Promise<AnySvelteComponent | undefined> {
const hierarchy = client.getHierarchy()
const attribute = typeof key === 'string' ? hierarchy.getAttribute(_class, key) : key.attr
const presenterClass = attribute !== undefined ? getAttributePresenterClass(hierarchy, attribute) : undefined
if (presenterClass === undefined) {
return
}
const typeClass = hierarchy.getClass(presenterClass.attrClass)
let mixin: Ref<Mixin<AttributeEditor>>
switch (presenterClass.category) {
case 'collection': {
mixin = view.mixin.CollectionEditor
break
}
case 'array': {
mixin = view.mixin.ArrayEditor
break
}
default: {
mixin = view.mixin.AttributeEditor
}
}
let editorMixin = hierarchy.as(typeClass, mixin)
let parent = typeClass.extends
while (editorMixin.inlineEditor === undefined && parent !== undefined) {
const parentClass = hierarchy.getClass(parent)
editorMixin = hierarchy.as(parentClass, mixin)
parent = parentClass.extends
}
if (editorMixin.inlineEditor === undefined) {
if (presenterClass.category === 'array') {
// NOTE: Don't show error for array attributes for compatibility with previous implementation
} else {
console.error(getAttributeEditorNotFoundError(_class, key))
}
return
}
try {
return await getResource(editorMixin.inlineEditor)
} catch (ex) {
console.error(getAttributeEditorNotFoundError(_class, key, ex))
}
}