mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 12:35:02 +02:00
Process result and context (#9782)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
+26
-11
@@ -19,7 +19,7 @@
|
||||
import {
|
||||
Context,
|
||||
Process,
|
||||
ProcessContext,
|
||||
ProcessExecutionContext,
|
||||
ProcessFunction,
|
||||
RelatedContext,
|
||||
SelectedContext
|
||||
@@ -83,7 +83,7 @@
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
function onProcessContext (ctx: ProcessContext): void {
|
||||
function onProcessContext (ctx: ProcessExecutionContext): void {
|
||||
onSelect(ctx.value)
|
||||
dispatch('close')
|
||||
}
|
||||
@@ -155,15 +155,30 @@
|
||||
<div class="menu-separator" />
|
||||
{/if}
|
||||
{#if processContext.length > 0}
|
||||
{#each processContext as f}
|
||||
<button
|
||||
on:click={() => {
|
||||
onProcessContext(f)
|
||||
}}
|
||||
class="menu-item"
|
||||
>
|
||||
<ExecutionContextPresenter {process} contextValue={f.value} />
|
||||
</button>
|
||||
{#each processContext as pc}
|
||||
{#if pc.attributes.length > 0}
|
||||
<Submenu
|
||||
component={ExecutionContextPresenter}
|
||||
props={{
|
||||
context: pc,
|
||||
target: attribute,
|
||||
contextValue: pc.value,
|
||||
process,
|
||||
onSelect: onClick
|
||||
}}
|
||||
options={{ component: plugin.component.ExecutionContextSelector }}
|
||||
withHover
|
||||
/>
|
||||
{:else}
|
||||
<button
|
||||
on:click={() => {
|
||||
onProcessContext(pc)
|
||||
}}
|
||||
class="menu-item"
|
||||
>
|
||||
<ExecutionContextPresenter {process} contextValue={pc.value} />
|
||||
</button>
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="menu-separator" />
|
||||
{/if}
|
||||
|
||||
+12
-2
@@ -13,18 +13,28 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Process, SelectedExecutonContext } from '@hcengineering/process'
|
||||
import { Context, Process, SelectedExecutionContext } from '@hcengineering/process'
|
||||
import ui, { Label } from '@hcengineering/ui'
|
||||
import ProcessContextPresenter from '../contextEditors/ProcessContextPresenter.svelte'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
|
||||
export let contextValue: SelectedExecutonContext
|
||||
export let contextValue: SelectedExecutionContext
|
||||
export let process: Process
|
||||
|
||||
const client = getClient()
|
||||
|
||||
$: ctx = process.context[contextValue.id]
|
||||
|
||||
$: attr = contextValue.key !== '' ? client.getHierarchy().findAttribute(ctx._class, contextValue.key) : undefined
|
||||
</script>
|
||||
|
||||
{#if ctx !== undefined}
|
||||
<ProcessContextPresenter context={ctx} />
|
||||
{#if attr !== undefined}
|
||||
<span class="attr">
|
||||
<Label label={attr.label} />
|
||||
</span>
|
||||
{/if}
|
||||
{:else}
|
||||
<Label label={ui.string.NotSelected} />
|
||||
{/if}
|
||||
|
||||
+80
@@ -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 { AnyAttribute } from '@hcengineering/core'
|
||||
import { ProcessExecutionContext, SelectedContext } from '@hcengineering/process'
|
||||
import { Label, resizeObserver, Scroller } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { getValueReduceFunc } from '../../utils'
|
||||
|
||||
export let context: ProcessExecutionContext
|
||||
export let target: AnyAttribute
|
||||
export let onSelect: (val: SelectedContext) => void
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const elements: HTMLButtonElement[] = []
|
||||
|
||||
const keyDown = (event: KeyboardEvent, index: number): void => {
|
||||
if (event.key === 'ArrowDown') {
|
||||
elements[(index + 1) % elements.length].focus()
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowUp') {
|
||||
elements[(elements.length + index - 1) % elements.length].focus()
|
||||
}
|
||||
|
||||
if (event.key === 'ArrowLeft') {
|
||||
dispatch('close')
|
||||
}
|
||||
}
|
||||
|
||||
function onAttribute (attr: AnyAttribute): void {
|
||||
const valueFunc = getValueReduceFunc(attr, target)
|
||||
onSelect({
|
||||
type: 'context',
|
||||
key: attr.name,
|
||||
id: context.context,
|
||||
functions: valueFunc !== undefined ? [{ func: valueFunc, props: {} }] : []
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="selectPopup" use:resizeObserver={() => dispatch('changeContent')}>
|
||||
<div class="menu-space" />
|
||||
<Scroller>
|
||||
{#each context.attributes as attr, i}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<button
|
||||
bind:this={elements[i]}
|
||||
on:keydown={(event) => {
|
||||
keyDown(event, i)
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
elements[i]?.focus()
|
||||
}}
|
||||
on:click={() => {
|
||||
onAttribute(attr)
|
||||
}}
|
||||
class="menu-item"
|
||||
>
|
||||
<span class="overflow-label pr-1">
|
||||
<Label label={attr.label} />
|
||||
</span>
|
||||
</button>
|
||||
{/each}
|
||||
</Scroller>
|
||||
<div class="menu-space" />
|
||||
</div>
|
||||
-1
@@ -16,7 +16,6 @@
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { ProcessContext } from '@hcengineering/process'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import process from '../../plugin'
|
||||
|
||||
export let context: ProcessContext
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
Process,
|
||||
ProcessToDo,
|
||||
SelectedContext,
|
||||
SelectedExecutonContext
|
||||
SelectedExecutionContext
|
||||
} from '@hcengineering/process'
|
||||
import ui, {
|
||||
Button,
|
||||
@@ -52,14 +52,14 @@
|
||||
|
||||
const client = getClient()
|
||||
|
||||
function getContext (value: string): SelectedExecutonContext | undefined {
|
||||
function getContext (value: string): SelectedExecutionContext | undefined {
|
||||
const context = parseContext(value)
|
||||
if (context !== undefined && isExecutionContext(context)) {
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
||||
function isExecutionContext (context: SelectedContext): context is SelectedExecutonContext {
|
||||
function isExecutionContext (context: SelectedContext): context is SelectedExecutionContext {
|
||||
return context.type === 'context'
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<script lang="ts">
|
||||
import core, { Ref } from '@hcengineering/core'
|
||||
import { Card, createQuery, getClient } from '@hcengineering/presentation'
|
||||
import { Process, State, Trigger } from '@hcengineering/process'
|
||||
import { Process, State, Trigger, TriggerResult } from '@hcengineering/process'
|
||||
import { Component, Dropdown, DropdownIntlItem, DropdownLabelsIntl, Label, ListItem } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import plugin from '../../plugin'
|
||||
@@ -25,6 +25,7 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
let to: Ref<State> | undefined = undefined
|
||||
let states: State[] = []
|
||||
let result: TriggerResult | null = null
|
||||
|
||||
const query = createQuery()
|
||||
query.query(plugin.class.State, { process: process._id }, (res) => {
|
||||
@@ -66,13 +67,19 @@
|
||||
trigger,
|
||||
triggerParams: params,
|
||||
process: process._id,
|
||||
result,
|
||||
actions: []
|
||||
})
|
||||
dispatch('close')
|
||||
}
|
||||
|
||||
function change (e: CustomEvent<Record<string, any>>): void {
|
||||
params = e.detail
|
||||
if (e.detail?.params !== undefined) {
|
||||
params = e.detail.params
|
||||
}
|
||||
if (e.detail?.result !== undefined) {
|
||||
result = e.detail.result
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -111,13 +118,17 @@
|
||||
items={triggersItems}
|
||||
bind:selected={trigger}
|
||||
label={plugin.string.Trigger}
|
||||
on:selected={() => {
|
||||
params = {}
|
||||
result = null
|
||||
}}
|
||||
justify={'left'}
|
||||
width={'100%'}
|
||||
kind={'no-border'}
|
||||
/>
|
||||
</div>
|
||||
{#if triggerValue?.editor}
|
||||
<Component is={triggerValue.editor} props={{ process, params }} on:change={change} />
|
||||
<Component is={triggerValue.editor} props={{ process, params, result }} on:change={change} />
|
||||
{/if}
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -20,11 +20,12 @@
|
||||
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 })
|
||||
await client.update(transition, { triggerParams: params, trigger: selectedTrigger, result })
|
||||
clearSettingsStore()
|
||||
}
|
||||
|
||||
@@ -34,7 +35,12 @@
|
||||
}
|
||||
|
||||
function change (e: CustomEvent<Record<string, any>>): void {
|
||||
params = e.detail
|
||||
if (e.detail?.params !== undefined) {
|
||||
params = e.detail.params
|
||||
}
|
||||
if (e.detail?.result !== undefined) {
|
||||
result = e.detail.result
|
||||
}
|
||||
}
|
||||
|
||||
let selectedTrigger: Ref<Trigger> = transition.trigger
|
||||
@@ -79,7 +85,7 @@
|
||||
</div>
|
||||
{#if trigger.editor !== undefined}
|
||||
<div class="editor">
|
||||
<Component is={trigger.editor} props={{ process, params, readonly }} on:change={change} />
|
||||
<Component is={trigger.editor} props={{ process, params, result, readonly }} on:change={change} />
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
function change (e: CustomEvent<any>): void {
|
||||
if (readonly || e.detail == null) return
|
||||
params = e.detail
|
||||
dispatch('change', params)
|
||||
dispatch('change', { params })
|
||||
}
|
||||
|
||||
function getKeys (_class: Ref<Class<MasterTag>>): AnyAttribute[] {
|
||||
@@ -87,7 +87,7 @@
|
||||
keys = keys.filter((k) => k !== key)
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete (params as any)[key]
|
||||
dispatch('change', params)
|
||||
dispatch('change', { params })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -16,33 +16,23 @@
|
||||
<script lang="ts">
|
||||
import { Doc } from '@hcengineering/core'
|
||||
import { Process, Step } from '@hcengineering/process'
|
||||
import ProcessContextPresenter from '../contextEditors/ProcessContextPresenter.svelte'
|
||||
import { Label } from '@hcengineering/ui'
|
||||
import processPlugin from '../../plugin'
|
||||
import ProcessContextPresenter from '../contextEditors/ProcessContextPresenter.svelte'
|
||||
|
||||
export let process: Process
|
||||
export let step: Step<Doc>
|
||||
|
||||
$: currentContext = step.context ? process.context[step.context._id] : undefined
|
||||
|
||||
$: currentResultContext = step.result ? process.context[step.result._id] : undefined
|
||||
</script>
|
||||
|
||||
{#if currentContext || currentResultContext}
|
||||
<Label label={processPlugin.string.Result} />
|
||||
{/if}
|
||||
{#if currentContext}
|
||||
<Label label={processPlugin.string.Result} />
|
||||
<div class="container">
|
||||
<ProcessContextPresenter context={currentContext} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if currentResultContext}
|
||||
<div class="container">
|
||||
<ProcessContextPresenter context={currentResultContext} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.container {
|
||||
padding: 0.25rem 0.5rem;
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import core, { Class, Doc, PropertyType, Ref, Type } from '@hcengineering/core'
|
||||
import core, { Class, PropertyType, Ref, Type } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import { Step } from '@hcengineering/process'
|
||||
import { TriggerResult } from '@hcengineering/process'
|
||||
import setting from '@hcengineering/setting-resources/src/plugin'
|
||||
import {
|
||||
AnyComponent,
|
||||
@@ -32,10 +32,10 @@
|
||||
import plugin from '../../plugin'
|
||||
import { generateContextId } from '../../utils'
|
||||
|
||||
export let step: Step<Doc>
|
||||
export let result: TriggerResult | null
|
||||
|
||||
let type: Type<any> | undefined | null = step.result?.type
|
||||
let name: string = step.result?.name ?? ''
|
||||
let type: Type<any> | undefined | null = result?.type
|
||||
let name: string = result?.name ?? ''
|
||||
let is: AnyComponent | undefined
|
||||
const client = getClient()
|
||||
const hierarchy = client.getHierarchy()
|
||||
@@ -43,15 +43,15 @@
|
||||
|
||||
function update (): void {
|
||||
if (type == null) {
|
||||
step.result = undefined
|
||||
result = null
|
||||
} else {
|
||||
step.result = {
|
||||
result = {
|
||||
_id: generateContextId(),
|
||||
name,
|
||||
type
|
||||
}
|
||||
}
|
||||
dispatch('change', step)
|
||||
dispatch('change', result)
|
||||
}
|
||||
|
||||
function getTypes (): DropdownIntlItem[] {
|
||||
@@ -91,9 +91,9 @@
|
||||
}
|
||||
|
||||
function handleNameChange (e: any): void {
|
||||
if (step.result != null) {
|
||||
step.result.name = name
|
||||
dispatch('change', step)
|
||||
if (result != null) {
|
||||
result.name = name
|
||||
dispatch('change', result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
<div class="grid">
|
||||
<Label label={plugin.string.Result} />
|
||||
<Toggle
|
||||
on={step.result !== undefined}
|
||||
on={result != null}
|
||||
on:change={(e) => {
|
||||
changeRequired(e.detail)
|
||||
}}
|
||||
@@ -150,14 +150,12 @@
|
||||
<style lang="scss">
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1.5fr;
|
||||
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: 0.25rem 2rem 0;
|
||||
width: calc(100% - 4rem);
|
||||
height: min-content;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -36,13 +36,6 @@
|
||||
}
|
||||
|
||||
const keys = ['title', 'user', 'dueDate']
|
||||
|
||||
function changeResult (e: CustomEvent<any>): void {
|
||||
if (e.detail !== undefined) {
|
||||
step = e.detail
|
||||
dispatch('change', step)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ParamsEditor _class={plugin.class.ProcessToDo} {process} {keys} {params} on:change={changeParams} />
|
||||
@@ -60,10 +53,6 @@
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="divider" />
|
||||
{#key step._id}
|
||||
<ResultEditor {step} on:change={changeResult} />
|
||||
{/key}
|
||||
|
||||
<style lang="scss">
|
||||
.divider {
|
||||
|
||||
@@ -14,23 +14,32 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { Process } from '@hcengineering/process'
|
||||
import { Process, TriggerResult } 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()
|
||||
|
||||
function change (e: CustomEvent<string>): void {
|
||||
if (readonly || e.detail == null) return
|
||||
params._id = e.detail
|
||||
dispatch('change', params)
|
||||
dispatch('change', { params })
|
||||
}
|
||||
|
||||
function changeResult (e: CustomEvent<any>): void {
|
||||
if (e.detail !== undefined) {
|
||||
result = e.detail
|
||||
dispatch('change', { result })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -38,8 +47,17 @@
|
||||
<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;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import { parseContext, Process, SelectedContext, SelectedExecutonContext } from '@hcengineering/process'
|
||||
import { parseContext, Process, SelectedContext, SelectedExecutionContext } from '@hcengineering/process'
|
||||
import ui, { Label } from '@hcengineering/ui'
|
||||
import ExecutionContextPresenter from '../attributeEditors/ExecutionContextPresenter.svelte'
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
$: context = getContext(params._id)
|
||||
|
||||
function getContext (value: string | undefined): SelectedExecutonContext | undefined {
|
||||
function getContext (value: string | undefined): SelectedExecutionContext | undefined {
|
||||
if (value === undefined) return
|
||||
const context = parseContext(value)
|
||||
if (context !== undefined && isExecutionContext(context)) {
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function isExecutionContext (context: SelectedContext): context is SelectedExecutonContext {
|
||||
function isExecutionContext (context: SelectedContext): context is SelectedExecutionContext {
|
||||
return context.type === 'context'
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user