Skip to content

Commit 127e3ca

Browse files
authored
ToDo complete trigger can respect results (#10067)
1 parent aa7829b commit 127e3ca

File tree

14 files changed

+283
-60
lines changed

14 files changed

+283
-60
lines changed

packages/presentation/src/utils.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { Analytics } from '@hcengineering/analytics'
1818
import core, {
1919
type Account,
2020
AccountRole,
21+
type AnyAttribute,
2122
type ArrOf,
2223
type AttachedDoc,
2324
type Class,
@@ -737,13 +738,8 @@ export function getAttrEditor (type: Type<any>, hierarchy: Hierarchy): AnyCompon
737738
return editorMixin?.inlineEditor
738739
}
739740

740-
export function findAttributeEditor (
741-
client: Client,
742-
_class: Ref<Class<Obj>>,
743-
key: KeyedAttribute | string
744-
): AnyComponent | undefined {
741+
export function findAttributeEditorByAttribute (client: Client, attribute: AnyAttribute): AnyComponent | undefined {
745742
const hierarchy = client.getHierarchy()
746-
const attribute = typeof key === 'string' ? hierarchy.findAttribute(_class, key) : key.attr
747743
if (attribute === undefined) return
748744

749745
if (attribute.type._class === core.class.TypeAny) {
@@ -779,16 +775,22 @@ export function findAttributeEditor (
779775
const editorMixin = hierarchy.classHierarchyMixin(presenterClass.attrClass, mixin)
780776

781777
if (editorMixin?.inlineEditor === undefined) {
782-
// if (presenterClass.category === 'array') {
783-
// // NOTE: Don't show error for array attributes for compatibility with previous implementation
784-
// } else {
785-
console.error(getAttributeEditorNotFoundError(_class, key))
786-
// }
787778
return
788779
}
789780
return editorMixin.inlineEditor
790781
}
791782

783+
export function findAttributeEditor (
784+
client: Client,
785+
_class: Ref<Class<Obj>>,
786+
key: KeyedAttribute | string
787+
): AnyComponent | undefined {
788+
const hierarchy = client.getHierarchy()
789+
const attribute = typeof key === 'string' ? hierarchy.findAttribute(_class, key) : key.attr
790+
if (attribute === undefined) return
791+
return findAttributeEditorByAttribute(client, attribute)
792+
}
793+
792794
export async function getAttributeEditor (
793795
client: Client,
794796
_class: Ref<Class<Obj>>,

plugins/process-resources/src/components/criterias/AttributeCriteria.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import { Process } from '@hcengineering/process'
2020
import { Component, Label, tooltip } from '@hcengineering/ui'
2121
import { createEventDispatcher } from 'svelte'
22-
import { getCirteriaEditor, getContext } from '../../utils'
22+
import { getCriteriaEditor, getContext } from '../../utils'
2323
2424
export let _class: Ref<Class<Doc>>
2525
export let readonly: boolean
@@ -34,7 +34,7 @@
3434
$: attribute = hierarchy.getAttribute(_class, key)
3535
$: presenterClass = getAttributePresenterClass(hierarchy, attribute.type)
3636
37-
$: updateCriteria = getCirteriaEditor(presenterClass.attrClass, presenterClass.category)
37+
$: updateCriteria = getCriteriaEditor(presenterClass.attrClass, presenterClass.category)
3838
$: editor = updateCriteria?.editor
3939
4040
$: value = params[key]

plugins/process-resources/src/components/criterias/BaseCriteriaEditor.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
<script lang="ts">
1717
import { AnyAttribute } from '@hcengineering/core'
18-
import { findAttributeEditor, getAttributePresenterClass, getClient } from '@hcengineering/presentation'
18+
import { findAttributeEditorByAttribute, getAttributePresenterClass, getClient } from '@hcengineering/presentation'
1919
import { Context, createContext, parseContext, Process, SelectedContext } from '@hcengineering/process'
2020
import { Button, Component, eventToHTMLElement, IconAdd, IconClose, showPopup } from '@hcengineering/ui'
2121
import { createEventDispatcher } from 'svelte'
@@ -60,7 +60,7 @@
6060
const hierarchy = client.getHierarchy()
6161
6262
$: presenterClass = getAttributePresenterClass(hierarchy, attribute.type)
63-
$: baseEditor = findAttributeEditor(client, attribute.attributeOf, attribute.name)
63+
$: baseEditor = findAttributeEditorByAttribute(client, attribute)
6464
</script>
6565

6666
<div class="text-input" class:context={contextValue}>
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<!--
2+
// Copyright © 2025 Hardcore Engineering Inc.
3+
//
4+
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License. You may
6+
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
//
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
-->
15+
16+
<script lang="ts">
17+
import { getAttributePresenterClass, getClient } from '@hcengineering/presentation'
18+
import {
19+
Context,
20+
ContextId,
21+
Process,
22+
SelectedExecutionContext,
23+
UpdateCriteriaComponent
24+
} from '@hcengineering/process'
25+
import { AnyComponent, Component } from '@hcengineering/ui'
26+
import { createEventDispatcher } from 'svelte'
27+
import { getContext, getCriteriaEditor, getMockAttribute } from '../../utils'
28+
import ExecutionContextPresenter from '../attributeEditors/ExecutionContextPresenter.svelte'
29+
import { AnyAttribute } from '@hcengineering/core'
30+
31+
export let process: Process
32+
export let value: string | undefined
33+
export let contextId: string
34+
export let readonly: boolean = false
35+
36+
const client = getClient()
37+
const hierarchy = client.getHierarchy()
38+
const dispatch = createEventDispatcher()
39+
40+
let editor: AnyComponent | undefined
41+
let context: Context | undefined
42+
let updateCriteria: UpdateCriteriaComponent | undefined
43+
let attribute: AnyAttribute | undefined
44+
45+
$: fill(contextId)
46+
47+
function fill (contextId: string): void {
48+
const _ctx = process.context[contextId as ContextId]
49+
if (_ctx === undefined) {
50+
editor = undefined
51+
context = undefined
52+
attribute = undefined
53+
updateCriteria = undefined
54+
return
55+
}
56+
const type = _ctx.type
57+
if (type === undefined) {
58+
editor = undefined
59+
context = undefined
60+
attribute = undefined
61+
updateCriteria = undefined
62+
return
63+
}
64+
65+
const presenterClass = getAttributePresenterClass(hierarchy, type)
66+
updateCriteria = getCriteriaEditor(presenterClass.attrClass, presenterClass.category)
67+
attribute = getMockAttribute(process.masterTag, type.label, type)
68+
editor = updateCriteria?.editor
69+
context = getContext(client, process, presenterClass?.attrClass, presenterClass?.category)
70+
}
71+
72+
function onChange (e: CustomEvent<any>): void {
73+
if (e.detail !== undefined) {
74+
dispatch('change', e.detail)
75+
}
76+
}
77+
78+
let contextValue: SelectedExecutionContext = {
79+
type: 'context',
80+
id: contextId as ContextId,
81+
key: ''
82+
}
83+
84+
$: contextValue = {
85+
type: 'context',
86+
id: contextId as ContextId,
87+
key: ''
88+
}
89+
</script>
90+
91+
{#if editor}
92+
<ExecutionContextPresenter {process} {contextValue} />
93+
<Component
94+
is={editor}
95+
props={{ value, readonly, context, process, attribute, ...updateCriteria?.props }}
96+
on:change={onChange}
97+
on:delete
98+
/>
99+
{/if}

plugins/process-resources/src/components/criterias/RangeCriteria.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
<script lang="ts">
1717
import { AnyAttribute } from '@hcengineering/core'
18-
import { findAttributeEditor, getAttributePresenterClass, getClient } from '@hcengineering/presentation'
18+
import { findAttributeEditorByAttribute, getAttributePresenterClass, getClient } from '@hcengineering/presentation'
1919
import { Context, createContext, parseContext, Process, SelectedContext } from '@hcengineering/process'
2020
import { Button, Component, eventToHTMLElement, IconAdd, IconClose, showPopup } from '@hcengineering/ui'
2121
import { createEventDispatcher } from 'svelte'
@@ -81,7 +81,7 @@
8181
8282
$: presenterClass = getAttributePresenterClass(hierarchy, attribute.type)
8383
84-
$: baseEditor = findAttributeEditor(client, process.masterTag, attribute.name)
84+
$: baseEditor = findAttributeEditorByAttribute(client, attribute)
8585
</script>
8686

8787
<div class="flex-row-center flex-gap-2">

plugins/process-resources/src/components/settings/AddRelationEditor.svelte

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
// limitations under the License.
1414
-->
1515
<script lang="ts">
16-
import core, { AnyAttribute, Association, generateId, Ref, Relation } from '@hcengineering/core'
16+
import core, { AnyAttribute, Association, Ref, Relation } from '@hcengineering/core'
1717
import { getClient } from '@hcengineering/presentation'
1818
import { Process, Step } from '@hcengineering/process'
1919
import { Label, tooltip } from '@hcengineering/ui'
2020
import { createEventDispatcher } from 'svelte'
21-
import { getContext } from '../../utils'
21+
import { getContext, getMockAttribute } from '../../utils'
2222
import ProcessAttribute from '../ProcessAttribute.svelte'
2323
import AssociationSelector from './AssociationSelector.svelte'
2424
@@ -56,23 +56,15 @@
5656
}
5757
}
5858
59-
let attribute: AnyAttribute
60-
$: attribute = {
61-
attributeOf: targetClass ?? process.masterTag,
62-
name: '',
63-
type: {
64-
label: core.string.Ref,
65-
_class: core.class.RefTo,
66-
to: targetClass
67-
},
68-
_id: generateId(),
69-
space: core.space.Model,
70-
modifiedOn: 0,
71-
modifiedBy: core.account.System,
72-
_class: core.class.Attribute,
73-
label: core.string.Object
59+
$: type = {
60+
label: core.string.Ref,
61+
_class: core.class.RefTo,
62+
to: targetClass ?? process.masterTag
7463
}
7564
65+
let attribute: AnyAttribute
66+
$: attribute = getMockAttribute(targetClass ?? process.masterTag, core.string.Object, type)
67+
7668
$: context = targetClass && getContext(client, process, targetClass, 'object')
7769
</script>
7870

plugins/process-resources/src/components/settings/CardUpdateEditor.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import { Process } from '@hcengineering/process'
2121
import { Button, eventToHTMLElement, SelectPopup, showPopup } from '@hcengineering/ui'
2222
import { createEventDispatcher } from 'svelte'
23-
import { getCirteriaEditor } from '../../utils'
23+
import { getCriteriaEditor } from '../../utils'
2424
import CriteriasEditor from '../criterias/CriteriasEditor.svelte'
2525
2626
export let readonly: boolean
@@ -46,7 +46,7 @@
4646
if (attr.hidden === true) continue
4747
if (ignoreKeys.includes(key)) continue
4848
const presenterClass = getAttributePresenterClass(hierarchy, attr.type)
49-
const updateCriteria = getCirteriaEditor(presenterClass.attrClass, presenterClass.category)
49+
const updateCriteria = getCriteriaEditor(presenterClass.attrClass, presenterClass.category)
5050
const editor = updateCriteria?.editor
5151
if (editor == null) continue
5252
res.push(attr)

plugins/process-resources/src/components/settings/FieldChangesEditor.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import { Button, eventToHTMLElement, SelectPopup, showPopup } from '@hcengineering/ui'
2222
import view from '@hcengineering/view'
2323
import { createEventDispatcher } from 'svelte'
24-
import { getCirteriaEditor } from '../../utils'
24+
import { getCriteriaEditor } from '../../utils'
2525
import CriteriasEditor from '../criterias/CriteriasEditor.svelte'
2626
2727
export let readonly: boolean
@@ -47,7 +47,7 @@
4747
if (attr.hidden === true) continue
4848
if (ignoreKeys.includes(key)) continue
4949
const presenterClass = getAttributePresenterClass(hierarchy, attr.type)
50-
const updateCriteria = getCirteriaEditor(presenterClass.attrClass, presenterClass.category)
50+
const updateCriteria = getCriteriaEditor(presenterClass.attrClass, presenterClass.category)
5151
const editor = updateCriteria?.editor
5252
if (editor == null) continue
5353
res.push(attr)
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<!--
2+
// Copyright © 2025 Hardcore Engineering Inc.
3+
//
4+
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License. You may
6+
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
//
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
-->
15+
16+
<script lang="ts">
17+
import presentation, { getClient } from '@hcengineering/presentation'
18+
import { ContextId, parseContext, Process, SelectedExecutionContext, UserResult } from '@hcengineering/process'
19+
import { Button, eventToHTMLElement, SelectPopup, showPopup } from '@hcengineering/ui'
20+
import { createEventDispatcher } from 'svelte'
21+
import ContextCriteria from '../criterias/ContextCriteria.svelte'
22+
23+
export let process: Process
24+
export let result: Record<ContextId, any> = {}
25+
export let value: string | undefined
26+
export let readonly: boolean
27+
28+
const client = getClient()
29+
const dispatch = createEventDispatcher()
30+
31+
let results: UserResult[] = []
32+
33+
let keys = Object.keys(result) as ContextId[]
34+
35+
function getResults (_id: string | undefined): void {
36+
results = []
37+
if (_id == null) return
38+
const ctx = parseContext(_id)
39+
if (ctx?.type !== 'context') return
40+
const context = process.context[ctx.id]
41+
if (context === undefined) return
42+
const transition = client.getModel().findObject(context.producer)
43+
if (transition == null) return
44+
results = transition.actions.find((a) => a._id === context.action)?.results ?? []
45+
}
46+
47+
$: getResults(value)
48+
49+
$: availableResults = results.filter((r) => !keys.includes(r._id))
50+
51+
function addKey (key: ContextId): void {
52+
keys = [...keys, key]
53+
}
54+
55+
function onAdd (e: MouseEvent): void {
56+
showPopup(
57+
SelectPopup,
58+
{
59+
value: availableResults.map((p) => {
60+
return { id: p._id, text: p.name }
61+
})
62+
},
63+
eventToHTMLElement(e),
64+
(res) => {
65+
if (res != null) {
66+
addKey(res)
67+
}
68+
}
69+
)
70+
}
71+
72+
function change (e: CustomEvent<any>, key: string): void {
73+
if (e.detail !== undefined) {
74+
;(result as any)[key] = e.detail
75+
dispatch('change', result)
76+
}
77+
}
78+
79+
function remove (key: string): void {
80+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
81+
delete (result as any)[key]
82+
keys = keys.filter((k) => k !== key)
83+
dispatch('change', result)
84+
}
85+
</script>
86+
87+
{#each keys as key}
88+
<ContextCriteria
89+
{process}
90+
value={result[key]}
91+
contextId={key}
92+
on:change={(e) => {
93+
change(e, key)
94+
}}
95+
on:delete={() => {
96+
remove(key)
97+
}}
98+
/>
99+
{/each}
100+
{#if !readonly && availableResults.length > 0}
101+
<div class="flex-center mt-4">
102+
<Button label={presentation.string.Add} width={'100%'} kind={'link-bordered'} size={'large'} on:click={onAdd} />
103+
</div>
104+
{/if}

0 commit comments

Comments
 (0)