mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-23 18:15:03 +02:00
Rework todo result (#9893)
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
<div class="editor-grid">
|
||||
{#each keys as key}
|
||||
<AttributeCriteria
|
||||
{process}
|
||||
@@ -54,17 +54,3 @@
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
column-gap: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
<div class="editor-grid">
|
||||
<span
|
||||
class="labelOnPanel"
|
||||
use:tooltip={{
|
||||
@@ -118,18 +118,3 @@
|
||||
<Button label={presentation.string.Add} width={'100%'} kind={'link-bordered'} size={'large'} on:click={onAdd} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.5fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
width: calc(100% - 4rem);
|
||||
align-items: center;
|
||||
margin: 0.25rem 2rem 0.5rems;
|
||||
row-gap: 0.5rem;
|
||||
column-gap: 1rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import core, { Ref, SortingOrder } from '@hcengineering/core'
|
||||
import { Card, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Process, State, Transition, Trigger, TriggerResult } from '@hcengineering/process'
|
||||
import { Process, State, Transition, Trigger } from '@hcengineering/process'
|
||||
import { Component, Dropdown, DropdownIntlItem, DropdownLabelsIntl, Label, ListItem } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
@@ -26,7 +26,6 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
let to: Ref<State> | undefined = undefined
|
||||
let states: State[] = []
|
||||
let result: TriggerResult | null = null
|
||||
|
||||
const query = createQuery()
|
||||
query.query(
|
||||
@@ -96,7 +95,6 @@
|
||||
triggerParams: params,
|
||||
process: process._id,
|
||||
rank,
|
||||
result,
|
||||
actions: []
|
||||
})
|
||||
dispatch('close')
|
||||
@@ -106,9 +104,6 @@
|
||||
if (e.detail?.params !== undefined) {
|
||||
params = e.detail.params
|
||||
}
|
||||
if (e.detail?.result !== undefined) {
|
||||
result = e.detail.result
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -119,7 +114,7 @@
|
||||
width={'medium'}
|
||||
on:close
|
||||
>
|
||||
<div class="grid">
|
||||
<div class="editor-grid">
|
||||
<Label label={plugin.string.From} />
|
||||
{#if !withoutFrom}
|
||||
<Dropdown
|
||||
@@ -149,7 +144,6 @@
|
||||
label={plugin.string.Trigger}
|
||||
on:selected={() => {
|
||||
params = {}
|
||||
result = null
|
||||
}}
|
||||
justify={'left'}
|
||||
width={'100%'}
|
||||
@@ -157,19 +151,6 @@
|
||||
/>
|
||||
</div>
|
||||
{#if triggerValue?.editor}
|
||||
<Component is={triggerValue.editor} props={{ process, params, result }} on:change={change} />
|
||||
<Component is={triggerValue.editor} props={{ process, params }} on:change={change} />
|
||||
{/if}
|
||||
</Card>
|
||||
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
column-gap: 1rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,12 +20,11 @@
|
||||
export let transition: Transition
|
||||
|
||||
let params = transition.triggerParams ?? {}
|
||||
let result = transition.result ?? null
|
||||
|
||||
const client = getClient()
|
||||
|
||||
async function save (): Promise<void> {
|
||||
await client.update(transition, { triggerParams: params, trigger: selectedTrigger, result })
|
||||
await client.update(transition, { triggerParams: params, trigger: selectedTrigger })
|
||||
clearSettingsStore()
|
||||
}
|
||||
|
||||
@@ -38,9 +37,6 @@
|
||||
if (e.detail?.params !== undefined) {
|
||||
params = e.detail.params
|
||||
}
|
||||
if (e.detail?.result !== undefined) {
|
||||
result = e.detail.result
|
||||
}
|
||||
}
|
||||
|
||||
let selectedTrigger: Ref<Trigger> = transition.trigger
|
||||
@@ -72,7 +68,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{#if trigger !== undefined}
|
||||
<div class="grid">
|
||||
<div class="editor-grid">
|
||||
<Label label={plugin.string.Trigger} />
|
||||
<DropdownLabelsIntl
|
||||
items={triggersItems}
|
||||
@@ -80,7 +76,6 @@
|
||||
label={plugin.string.Trigger}
|
||||
on:selected={() => {
|
||||
params = {}
|
||||
result = null
|
||||
}}
|
||||
justify={'left'}
|
||||
width={'100%'}
|
||||
@@ -89,7 +84,7 @@
|
||||
</div>
|
||||
{#if trigger.editor !== undefined}
|
||||
<div class="editor">
|
||||
<Component is={trigger.editor} props={{ process, params, result, readonly }} on:change={change} />
|
||||
<Component is={trigger.editor} props={{ process, params, readonly }} on:change={change} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
@@ -105,18 +100,6 @@
|
||||
margin: 0.25rem 2rem 0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.25rem;
|
||||
column-gap: 1rem;
|
||||
margin: 0.25rem 2rem 0;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.title {
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,23 @@
|
||||
export let step: Step<Doc>
|
||||
|
||||
$: currentContext = step.context ? process.context[step.context._id] : undefined
|
||||
|
||||
$: resultContext =
|
||||
step.results != null ? step.results.map((r) => process.context[r._id]).filter((ctx) => ctx != null) : []
|
||||
</script>
|
||||
|
||||
{#if currentContext}
|
||||
<Label label={processPlugin.string.Result} />
|
||||
<div class="container">
|
||||
<ProcessContextPresenter context={currentContext} />
|
||||
</div>
|
||||
{#if currentContext || resultContext.length > 0}
|
||||
<Label label={processPlugin.string.Result} />:
|
||||
{#if currentContext}
|
||||
<div class="container">
|
||||
<ProcessContextPresenter context={currentContext} />
|
||||
</div>
|
||||
{/if}
|
||||
{#each resultContext as ctx}
|
||||
<div class="container">
|
||||
<ProcessContextPresenter context={ctx} />
|
||||
</div>
|
||||
{/each}
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -13,32 +13,20 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { Class, PropertyType, Ref, Type } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { TriggerResult } from '@hcengineering/process'
|
||||
import setting from '@hcengineering/setting-resources/src/plugin'
|
||||
import {
|
||||
AnyComponent,
|
||||
Component,
|
||||
DropdownIntlItem,
|
||||
DropdownLabelsIntl,
|
||||
EditBox,
|
||||
Label,
|
||||
Toggle
|
||||
} from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import core, { Type } from '@hcengineering/core'
|
||||
import { Process, UserResult } from '@hcengineering/process'
|
||||
import { Button, EditBox, IconClose, Label } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
import { generateContextId } from '../../utils'
|
||||
import ResultTypeSelector from './ResultTypeSelector.svelte'
|
||||
|
||||
export let result: TriggerResult | null
|
||||
export let result: UserResult | null
|
||||
export let process: Process
|
||||
|
||||
let type: Type<any> | undefined | null = result?.type
|
||||
let name: string = result?.name ?? ''
|
||||
let is: AnyComponent | undefined
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
let key: string | undefined = result?.key
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function update (): void {
|
||||
@@ -48,114 +36,34 @@
|
||||
result = {
|
||||
_id: generateContextId(),
|
||||
name,
|
||||
key,
|
||||
type
|
||||
}
|
||||
}
|
||||
dispatch('change', result)
|
||||
}
|
||||
|
||||
function getTypes (): DropdownIntlItem[] {
|
||||
const descendants = hierarchy.getDescendants(core.class.Type)
|
||||
const res: DropdownIntlItem[] = []
|
||||
for (const descendant of descendants) {
|
||||
const _class = hierarchy.getClass(descendant)
|
||||
if (_class.label !== undefined && hierarchy.hasMixin(_class, view.mixin.ObjectEditor)) {
|
||||
res.push({
|
||||
label: _class.label,
|
||||
id: _class._id
|
||||
})
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
const items = getTypes()
|
||||
let selectedType: Ref<Class<Type<PropertyType>>> | undefined = type?._class
|
||||
$: selectType(selectedType)
|
||||
function selectType (type: Ref<Class<Type<PropertyType>>> | undefined): void {
|
||||
if (type == null) 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<Class<Type<any>>> }): void => {
|
||||
selectType(e.detail)
|
||||
}
|
||||
const handleChange = (e: any): void => {
|
||||
if (e.detail?.type === undefined) return
|
||||
if (!deepEqual(e.detail.type, type)) {
|
||||
type = e.detail?.type
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
||||
function handleNameChange (e: any): void {
|
||||
function handleNameChange (): void {
|
||||
if (result != null) {
|
||||
result.name = name
|
||||
dispatch('change', result)
|
||||
}
|
||||
}
|
||||
|
||||
function changeRequired (e: boolean): void {
|
||||
if (!e) {
|
||||
type = undefined
|
||||
} else {
|
||||
type = null
|
||||
}
|
||||
update()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
<Label label={plugin.string.Result} />
|
||||
<Toggle
|
||||
on={result != null}
|
||||
on:change={(e) => {
|
||||
changeRequired(e.detail)
|
||||
}}
|
||||
/>
|
||||
{#if type !== undefined}
|
||||
<span class="label">
|
||||
<Label label={core.string.Description} />
|
||||
</span>
|
||||
<div class="editor-grid">
|
||||
<span class="label">
|
||||
<Label label={core.string.Description} />
|
||||
</span>
|
||||
<div class="flex-row-center flex-gap-2">
|
||||
<EditBox bind:value={name} placeholder={core.string.Description} on:change={handleNameChange} kind={'default'} />
|
||||
<span class="label">
|
||||
<Label label={setting.string.Type} />
|
||||
</span>
|
||||
<DropdownLabelsIntl
|
||||
label={setting.string.Type}
|
||||
{items}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
bind:selected={selectedType}
|
||||
on:selected={handleSelection}
|
||||
<Button
|
||||
icon={IconClose}
|
||||
kind="ghost"
|
||||
on:click={() => {
|
||||
dispatch('remove')
|
||||
}}
|
||||
/>
|
||||
{#if is}
|
||||
<Component
|
||||
{is}
|
||||
props={{
|
||||
type,
|
||||
width: '100%',
|
||||
isCard: true,
|
||||
kind: 'regular',
|
||||
size: 'large'
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
<ResultTypeSelector {process} bind:key bind:type on:change={update} />
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
column-gap: 1rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<!--
|
||||
// Copyright © 2025 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 { MasterTag } from '@hcengineering/card'
|
||||
import core, { AnyAttribute, Class, Ref, Type } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Process } from '@hcengineering/process'
|
||||
import { DropdownLabelsIntl, Label, tooltip } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
|
||||
export let process: Process
|
||||
export let key: string | undefined
|
||||
export let type: Type<any> | null | undefined
|
||||
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const dispatch = createEventDispatcher()
|
||||
$: setType(key)
|
||||
|
||||
function setType (key: string | undefined): void {
|
||||
const attr = key != null ? hierarchy.findAttribute(process.masterTag, key) : undefined
|
||||
if (attr != null) {
|
||||
type = attr.type
|
||||
} else {
|
||||
type = null
|
||||
}
|
||||
dispatch('change')
|
||||
}
|
||||
|
||||
function getKeys (_class: Ref<Class<MasterTag>>): AnyAttribute[] {
|
||||
const ignoreKeys = ['_class', 'content', 'parent', 'attachments', 'todos']
|
||||
const attributes = hierarchy.getAllAttributes(_class, core.class.Doc)
|
||||
const res: AnyAttribute[] = []
|
||||
for (const [key, attr] of attributes) {
|
||||
if (attr.hidden === true) continue
|
||||
if (ignoreKeys.includes(key)) continue
|
||||
res.push(attr)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
const allAttrs = getKeys(process.masterTag)
|
||||
const items = allAttrs.map((attr) => {
|
||||
return {
|
||||
id: attr.name,
|
||||
label: attr.label ?? attr.name
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<span
|
||||
class="labelOnPanel"
|
||||
use:tooltip={{
|
||||
props: { label: plugin.string.Attribute }
|
||||
}}
|
||||
>
|
||||
<Label label={plugin.string.Attribute} />
|
||||
</span>
|
||||
<DropdownLabelsIntl
|
||||
label={plugin.string.Attribute}
|
||||
{items}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
shouldUpdateUndefined={false}
|
||||
bind:selected={key}
|
||||
/>
|
||||
@@ -0,0 +1,92 @@
|
||||
<!--
|
||||
// Copyright © 2025 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, { Class, PropertyType, Ref, Type } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import setting from '@hcengineering/setting-resources/src/plugin'
|
||||
import { AnyComponent, Component, DropdownIntlItem, DropdownLabelsIntl, Label } from '@hcengineering/ui'
|
||||
import view from '@hcengineering/view'
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let type: Type<any> | null | undefined
|
||||
|
||||
let is: AnyComponent | undefined
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
function getTypes (): DropdownIntlItem[] {
|
||||
const descendants = hierarchy.getDescendants(core.class.Type)
|
||||
const res: DropdownIntlItem[] = []
|
||||
for (const descendant of descendants) {
|
||||
const _class = hierarchy.getClass(descendant)
|
||||
if (_class.label !== undefined && hierarchy.hasMixin(_class, view.mixin.ObjectEditor)) {
|
||||
res.push({
|
||||
label: _class.label,
|
||||
id: _class._id
|
||||
})
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
const items = getTypes()
|
||||
|
||||
let selectedType: Ref<Class<Type<PropertyType>>> | undefined = type?._class
|
||||
$: selectType(selectedType)
|
||||
function selectType (type: Ref<Class<Type<PropertyType>>> | undefined): void {
|
||||
if (type == null) 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<Class<Type<any>>> }): void => {
|
||||
selectType(e.detail)
|
||||
}
|
||||
const handleChange = (e: any): void => {
|
||||
if (e.detail?.type === undefined) return
|
||||
if (!deepEqual(e.detail.type, type)) {
|
||||
type = e.detail?.type
|
||||
dispatch('change', type)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<span class="label">
|
||||
<Label label={setting.string.Type} />
|
||||
</span>
|
||||
<DropdownLabelsIntl
|
||||
label={setting.string.Type}
|
||||
{items}
|
||||
size={'large'}
|
||||
width={'100%'}
|
||||
bind:selected={selectedType}
|
||||
on:selected={handleSelection}
|
||||
/>
|
||||
{#if is}
|
||||
<Component
|
||||
{is}
|
||||
props={{
|
||||
type,
|
||||
width: '100%',
|
||||
isCard: true,
|
||||
kind: 'regular',
|
||||
size: 'large'
|
||||
}}
|
||||
on:change={handleChange}
|
||||
/>
|
||||
{/if}
|
||||
@@ -0,0 +1,54 @@
|
||||
<!--
|
||||
// Copyright © 2025 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 { Type } from '@hcengineering/core'
|
||||
import { Process } from '@hcengineering/process'
|
||||
import { DropdownIntlItem, DropdownLabelsIntl, Label } from '@hcengineering/ui'
|
||||
import plugin from '../../plugin'
|
||||
import ResultFieldTypeEditor from './ResultFieldTypeEditor.svelte'
|
||||
import ResultTypeEditor from './ResultTypeEditor.svelte'
|
||||
|
||||
export let process: Process
|
||||
export let type: Type<any> | null | undefined
|
||||
export let key: string | undefined
|
||||
|
||||
enum Modes {
|
||||
Attribute = 'attribute',
|
||||
Context = 'context'
|
||||
}
|
||||
|
||||
const items: DropdownIntlItem[] = [
|
||||
{
|
||||
id: Modes.Attribute,
|
||||
label: plugin.string.Attribute
|
||||
},
|
||||
{
|
||||
id: Modes.Context,
|
||||
label: plugin.string.Context
|
||||
}
|
||||
]
|
||||
|
||||
let selected: Modes = key !== undefined || type == null ? Modes.Attribute : Modes.Context
|
||||
</script>
|
||||
|
||||
<span class="label">
|
||||
<Label label={plugin.string.For} />
|
||||
</span>
|
||||
<DropdownLabelsIntl label={plugin.string.For} {items} size={'large'} width={'100%'} bind:selected />
|
||||
{#if selected === Modes.Attribute}
|
||||
<ResultFieldTypeEditor {process} bind:key bind:type on:change />
|
||||
{:else}
|
||||
<ResultTypeEditor bind:type on:change />
|
||||
{/if}
|
||||
@@ -0,0 +1,64 @@
|
||||
<!--
|
||||
// Copyright © 2025 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 { Process, UserResult } from '@hcengineering/process'
|
||||
import { Button } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
import ResultEditor from './ResultEditor.svelte'
|
||||
|
||||
export let process: Process
|
||||
export let result: UserResult[] | undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
let items: (UserResult | null)[] = result ?? []
|
||||
|
||||
function handleChange (e: CustomEvent<UserResult>, index: number) {
|
||||
if (e.detail !== undefined) {
|
||||
items[index === -1 ? items.length : index] = e.detail
|
||||
result = items.filter((r) => r != null)
|
||||
dispatch('change', result)
|
||||
}
|
||||
}
|
||||
|
||||
function onAdd (): void {
|
||||
items.push(null)
|
||||
items = items
|
||||
}
|
||||
|
||||
function remove (index: number): void {
|
||||
items.splice(index, 1)
|
||||
items = items
|
||||
result = items.filter((r) => r != null)
|
||||
dispatch('change', result)
|
||||
}
|
||||
</script>
|
||||
|
||||
{#each items as item, i}
|
||||
<ResultEditor
|
||||
{process}
|
||||
result={item}
|
||||
on:change={(e) => {
|
||||
handleChange(e, i)
|
||||
}}
|
||||
on:remove={() => {
|
||||
remove(i)
|
||||
}}
|
||||
/>
|
||||
{/each}
|
||||
<div class="flex-center mt-4">
|
||||
<Button label={plugin.string.AddResult} width={'100%'} kind={'link-bordered'} size={'large'} on:click={onAdd} />
|
||||
</div>
|
||||
@@ -70,7 +70,7 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
<div class="editor-grid">
|
||||
<ProcessAttribute
|
||||
{process}
|
||||
masterTag={process.masterTag}
|
||||
@@ -88,17 +88,3 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
column-gap: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Process, ProcessToDo, Step } from '@hcengineering/process'
|
||||
import { Process, ProcessToDo, Step, UserResult } from '@hcengineering/process'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
import ParamsEditor from './ParamsEditor.svelte'
|
||||
import ResultEditor from './ResultEditor.svelte'
|
||||
import { Label, Toggle } from '@hcengineering/ui'
|
||||
import ResultsEditor from './ResultsEditor.svelte'
|
||||
|
||||
export let process: Process
|
||||
export let step: Step<ProcessToDo>
|
||||
@@ -35,6 +35,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function changeResults (e: CustomEvent<UserResult[]>): void {
|
||||
if (e.detail !== undefined) {
|
||||
step.results = e.detail
|
||||
dispatch('change', step)
|
||||
}
|
||||
}
|
||||
|
||||
const keys = ['title', 'user', 'dueDate']
|
||||
</script>
|
||||
|
||||
@@ -53,6 +60,8 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="divider" />
|
||||
<ResultsEditor {process} result={step.results} on:change={changeResults} />
|
||||
|
||||
<style lang="scss">
|
||||
.divider {
|
||||
|
||||
@@ -14,18 +14,16 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { Process, TriggerResult } from '@hcengineering/process'
|
||||
import { Process } from '@hcengineering/process'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
import ToDoContextSelector from '../contextEditors/ToDoContextSelector.svelte'
|
||||
import ResultEditor from './ResultEditor.svelte'
|
||||
|
||||
export let readonly: boolean
|
||||
export let process: Process
|
||||
export let params: Record<string, any>
|
||||
export let skipRollback: boolean = false
|
||||
export let result: TriggerResult | null = null
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@@ -34,39 +32,9 @@
|
||||
params._id = e.detail
|
||||
dispatch('change', { params })
|
||||
}
|
||||
|
||||
function changeResult (e: CustomEvent<any>): void {
|
||||
if (e.detail !== undefined) {
|
||||
result = e.detail
|
||||
dispatch('change', { result })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="grid">
|
||||
<div class="editor-grid">
|
||||
<Label label={plugin.string.ToDo} />
|
||||
<ToDoContextSelector {readonly} {skipRollback} {process} value={params._id} on:change={change} />
|
||||
</div>
|
||||
{#if !skipRollback}
|
||||
<div class="divider" />
|
||||
<ResultEditor {result} on:change={changeResult} />
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.divider {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 3fr;
|
||||
grid-auto-rows: minmax(2rem, max-content);
|
||||
justify-content: start;
|
||||
align-items: center;
|
||||
row-gap: 0.5rem;
|
||||
column-gap: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user