Support for draft attrubutes ()

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2022-12-01 14:48:07 +07:00 committed by GitHub
parent e83e0ee622
commit e87b7fd27f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 59 additions and 9 deletions
packages
plugins/view-resources/src

View File

@ -1,4 +1,6 @@
import { PlatformError, Severity, Status } from '@hcengineering/platform'
import { Doc } from './classes'
import core from './component'
/**
* @public
@ -27,6 +29,40 @@ export function getObjectValue (key: string, doc: Doc): any {
return value
}
/**
* @public
*/
export function setObjectValue (key: string, doc: Doc, newValue: any): void {
// Check dot notation
if (key.length === 0) {
return
}
key = key.split('\\$').join('$')
let dots = key.split('.')
// Replace escapting, since memdb is not escape keys
const last = dots[dots.length - 1]
dots = dots.slice(0, -1)
// We have dots, so iterate in depth
let value = doc as any
for (const d of dots) {
if (Array.isArray(value) && isNestedArrayQuery(value, d)) {
// Arrays are not supported
throw new PlatformError(new Status(Severity.ERROR, core.status.ObjectNotFound, { _id: 'dots' }))
}
const lvalue = value?.[d]
if (lvalue === undefined) {
value[d] = {}
value = value?.[d]
} else {
value = lvalue
}
}
value[last] = newValue
return value
}
function isNestedArrayQuery (value: any, d: string): boolean {
return Number.isNaN(Number.parseInt(d)) && value?.[d as any] === undefined
}

View File

@ -16,6 +16,7 @@
import type { KeysByType } from 'simplytyped'
import type { Account, Arr, AttachedDoc, Class, Data, Doc, Domain, Mixin, PropertyType, Ref, Space } from './classes'
import core from './component'
import { setObjectValue } from './objvalue'
import { _getOperator } from './operator'
import { _toDoc } from './proxy'
import type { DocumentQuery, TxResult } from './storage'
@ -295,7 +296,7 @@ export abstract class TxProcessor implements WithTx {
const operator = _getOperator(key)
operator(doc, ops[key])
} else {
;(doc as any)[key] = ops[key]
setObjectValue(key, doc, ops[key])
}
}
doc.modifiedBy = tx.modifiedBy
@ -312,7 +313,7 @@ export abstract class TxProcessor implements WithTx {
const operator = _getOperator(key)
operator(mixin, ops[key])
} else {
mixin[key] = ops[key]
setObjectValue(key, mixin, ops[key])
}
}
rawDoc.modifiedBy = tx.modifiedBy

View File

@ -18,20 +18,24 @@
import { getResource } from '@hcengineering/platform'
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'
export let key: KeyedAttribute | string
export let object: Doc
export let object: Doc | Record<string, any>
export let _class: Ref<Class<Doc>>
export let maxWidth: string | undefined = undefined
export let focus: boolean = false
export let showHeader: boolean = true
export let readonly = false
export let draft = false
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
@ -67,7 +71,12 @@
function onChange (value: any) {
const doc = object as Doc
updateAttribute(client, doc, _class, { key: attributeKey, attr: attribute }, value)
if (draft) {
;(doc as any)[attributeKey] = value
dispatch('update', { key, value })
} else {
updateAttribute(client, doc, _class, { key: attributeKey, attr: attribute }, value)
}
}
$: isReadonly = (attribute.readonly ?? false) || readonly
</script>

View File

@ -18,16 +18,17 @@
import { KeyedAttribute } from '../attributes'
import AttributeBarEditor from './AttributeBarEditor.svelte'
export let object: Doc
export let object: Doc | Record<string, any>
export let _class: Ref<Class<Doc>>
export let keys: (string | KeyedAttribute)[]
export let showHeader: boolean = true
export let readonly = false
export let draft = false
</script>
<div class="attributes-bar-container vertical">
{#each keys as key (typeof key === 'string' ? key : key.key)}
<AttributeBarEditor {key} {_class} {object} {showHeader} {readonly} />
<AttributeBarEditor {key} {_class} {object} {showHeader} {readonly} {draft} on:update />
{/each}
</div>

View File

@ -20,7 +20,7 @@
import { Button, getCurrentLocation, Label, navigate } from '@hcengineering/ui'
import { getFiltredKeys, isCollectionAttr } from '../utils'
export let object: Doc
export let object: Doc | Record<string, any>
export let _class: Ref<Class<Doc>>
export let to: Ref<Class<Doc>> | undefined = core.class.Doc
export let ignoreKeys: string[] = []
@ -28,6 +28,7 @@
export let readonly = false
export let showLabel: IntlString | undefined = undefined
export let defaultCollapsed = false
export let draft = false
const client = getClient()
const hierarchy = client.getHierarchy()
@ -84,7 +85,7 @@
</div>
{#if keys.length}
<div class="collapsed-container" class:collapsed>
<AttributesBar {_class} {object} keys={keys.map((p) => p.key)} {readonly} />
<AttributesBar {_class} {object} keys={keys.map((p) => p.key)} {readonly} {draft} on:update />
</div>
{/if}

View File

@ -93,7 +93,9 @@ export {
getObjectPresenter,
LoadingProps,
setActiveViewletId,
getActiveViewletId
getActiveViewletId,
getFiltredKeys,
isCollectionAttr
} from './utils'
export {
HTMLPresenter,