Editable presenters (#2594)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2023-02-07 11:52:34 +07:00
committed by GitHub
parent 61fbb4b78b
commit 0bee06e8a7
16 changed files with 167 additions and 36 deletions
@@ -18,7 +18,12 @@
import { DateRangePresenter } from '@hcengineering/ui'
export let value: number | null | undefined
export let onChange: ((value: number | null) => void) | undefined = undefined
export let noShift: boolean = false
</script>
<DateRangePresenter {value} {noShift} />
{#if onChange !== undefined}
<DateRangePresenter {value} {noShift} editable on:change={(e) => onChange?.(e.detail)} />
{:else}
<DateRangePresenter {value} {noShift} />
{/if}
@@ -0,0 +1,60 @@
<!--
// Copyright © 2022 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import core, { EnumOf } from '@hcengineering/core'
import { createQuery } from '@hcengineering/presentation'
import { DropdownLabels, DropdownTextItem } from '@hcengineering/ui'
import StringPresenter from './StringPresenter.svelte'
export let value: string
export let type: EnumOf | undefined = undefined
export let onChange: ((value: string) => void) | undefined = undefined
let items: DropdownTextItem[] = []
const query = createQuery()
$: type &&
query.query(
core.class.Enum,
{
_id: type.of
},
(res) => {
items = res[0]?.enumValues?.map((p) => {
return { id: p, label: p }
})
},
{ limit: 1 }
)
</script>
{#if onChange !== undefined && type !== undefined}
<DropdownLabels
bind:selected={value}
{items}
useFlexGrow={true}
justify={'left'}
size={'large'}
kind={'link'}
width={'100%'}
autoSelect={false}
on:selected={(e) => {
onChange?.(e.detail)
}}
/>
{:else}
<StringPresenter {value} />
{/if}
@@ -14,10 +14,10 @@
// limitations under the License.
-->
<script lang="ts">
import type { Class, Doc, DocumentQuery, FindOptions, Lookup, Ref } from '@hcengineering/core'
import core, { AnyAttribute, Class, Doc, DocumentQuery, FindOptions, Lookup, Ref } from '@hcengineering/core'
import { getObjectValue, SortingOrder } from '@hcengineering/core'
import notification from '@hcengineering/notification'
import { createQuery, getClient } from '@hcengineering/presentation'
import { createQuery, getClient, updateAttribute } from '@hcengineering/presentation'
import {
CheckBox,
Component,
@@ -31,9 +31,9 @@
} from '@hcengineering/ui'
import { AttributeModel, BuildModelKey } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
import view from '../plugin'
import { buildConfigLookup, buildModel, LoadingProps } from '../utils'
import Menu from './Menu.svelte'
import view from '../plugin'
export let _class: Ref<Class<Doc>>
export let query: DocumentQuery<Doc>
@@ -180,11 +180,14 @@
}
}
const joinProps = (collectionAttr: boolean, object: Doc, props: any) => {
if (collectionAttr) {
return { object, ...props }
const joinProps = (attribute: AttributeModel, object: Doc) => {
if (attribute.collectionAttr) {
return { object, ...attribute.props }
}
return props
if (attribute.attribute?.type._class === core.class.EnumOf) {
return { ...attribute.props, type: attribute.attribute.type }
}
return attribute.props
}
function getValue (attribute: AttributeModel, object: Doc): any {
if (attribute.castRequest) {
@@ -195,6 +198,19 @@
}
return getObjectValue(attribute.key, object)
}
function onChange (value: any, doc: Doc, key: string, attribute: AnyAttribute) {
updateAttribute(client, doc, _class, { key, attr: attribute }, value)
}
function getOnChange (doc: Doc, attribute: AttributeModel) {
const attr = attribute.attribute
if (attr === undefined) return
if (attribute.collectionAttr) return
if (attribute.isLookup) return
const key = attribute.castRequest ? attribute.key.substring(attribute.castRequest.length + 1) : attribute.key
return (value: any) => onChange(value, doc, key, attr)
}
</script>
{#await buildModel({ client, _class, keys: config, lookup })}
@@ -295,10 +311,12 @@
{#each model as attribute, cell}
<td>
<div class:antiTable-cells__firstCell={!cell}>
<!-- {getOnChange(object, attribute) !== undefined} -->
<svelte:component
this={attribute.presenter}
value={getValue(attribute, object)}
{...joinProps(attribute.collectionAttr, object, attribute.props)}
onChange={getOnChange(object, attribute)}
{...joinProps(attribute, object)}
/>
</div>
</td>
@@ -121,6 +121,7 @@
if (viewlet.hiddenKeys?.includes(attribute.name)) return
if (hierarchy.isDerived(attribute.type._class, core.class.Collection)) return
const value = getValue(attribute.name, attribute.type)
if (result.findIndex((p) => p.value === attribute.name) !== -1) return
if (result.findIndex((p) => p.value === value) !== -1) return
const { attrClass, category } = getAttributePresenterClass(hierarchy, attribute)
const typeClass = hierarchy.getClass(attrClass)
@@ -13,8 +13,9 @@
// limitations under the License.
-->
<script lang="ts">
import { Doc, getObjectValue, Ref } from '@hcengineering/core'
import { AnyAttribute, Doc, getObjectValue, Ref } from '@hcengineering/core'
import notification from '@hcengineering/notification'
import { getClient, updateAttribute } from '@hcengineering/presentation'
import { CheckBox, Component, deviceOptionsStore as deviceInfo, tooltip } from '@hcengineering/ui'
import { AttributeModel } from '@hcengineering/view'
import { createEventDispatcher } from 'svelte'
@@ -50,6 +51,20 @@
$: elem && elementByIndex.set(index, elem)
$: indexById.set(docObject._id, index)
$: docByIndex.set(index, docObject)
const client = getClient()
function onChange (value: any, doc: Doc, key: string, attribute: AnyAttribute) {
updateAttribute(client, doc, doc._class, { key, attr: attribute }, value)
}
function getOnChange (docObject: Doc, attribute: AttributeModel) {
const attr = attribute.attribute
if (attr === undefined) return
if (attribute.collectionAttr) return
if (attribute.isLookup) return
return (value: any) => onChange(value, docObject, attribute.key, attr)
}
</script>
<div
@@ -90,6 +105,7 @@
{...props}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
object={docObject}
onChange={getOnChange(docObject, attributeModel)}
kind={'list'}
{...attributeModel.props}
/>
@@ -100,6 +116,7 @@
{...props}
value={getObjectValue(attributeModel.key, docObject) ?? ''}
object={docObject}
onChange={getOnChange(docObject, attributeModel)}
kind={'list'}
{...attributeModel.props}
/>
@@ -127,6 +144,7 @@
{...props}
value={value ?? ''}
objectId={docObject._id}
onChange={getOnChange(docObject, attributeModel)}
groupBy={groupByKey}
{...attributeModel.props}
/>