11<script setup lang="ts">
22import { faTimesCircle } from " @fortawesome/free-regular-svg-icons" ;
3- import { faInfoCircle } from " @fortawesome/free-solid-svg-icons" ;
3+ import { faInfoCircle , faWrench } from " @fortawesome/free-solid-svg-icons" ;
44import { FontAwesomeIcon } from " @fortawesome/vue-fontawesome" ;
5+ import axios from " axios" ;
56import { BAlert } from " bootstrap-vue" ;
67import { computed , onUnmounted , ref , watch } from " vue" ;
78
89import type { WorkflowInvocationElementView } from " @/api/invocations" ;
910import type { WorkflowStepTyped } from " @/api/workflows" ;
11+ import { useDatatypesMapper } from " @/composables/datatypesMapper" ;
1012import type { GraphStep } from " @/composables/useInvocationGraph" ;
13+ import { getAppRoot } from " @/onload/loadConfig" ;
1114import { useInvocationStore } from " @/stores/invocationStore" ;
1215
1316import Heading from " ../Common/Heading.vue" ;
@@ -20,6 +23,8 @@ import GTab from "@/components/BaseComponents/GTab.vue";
2023import GTabs from " @/components/BaseComponents/GTabs.vue" ;
2124import GenericHistoryItem from " @/components/History/Content/GenericItem.vue" ;
2225import LoadingSpan from " @/components/LoadingSpan.vue" ;
26+ import FormDefault from " @/components/Workflow/Editor/Forms/FormDefault.vue" ;
27+ import FormTool from " @/components/Workflow/Editor/Forms/FormTool.vue" ;
2328
2429const TERMINAL_JOB_STATES = [" ok" , " error" , " deleted" , " paused" ];
2530
@@ -41,8 +46,11 @@ const emit = defineEmits<{
4146}>();
4247
4348const invocationStore = useInvocationStore ();
49+ const { datatypes } = useDatatypesMapper ();
4450
4551const localExpanded = ref (Boolean (props .expanded ));
52+ const stepConfigData = ref <Record <string , any > | null >(null );
53+ const loadingStepConfig = ref (false );
4654const stepFetchInterval = ref <any >(undefined );
4755
4856const computedExpanded = computed ({
@@ -143,6 +151,43 @@ const jobsTabTitle = computed(() => {
143151 return " No jobs" ;
144152});
145153
154+ const activeStepWithConfig = computed (() => {
155+ // graphStep is the full editor-format step (already has config_form with correct values)
156+ if (props .graphStep ?.config_form ) {
157+ return props .graphStep as any ;
158+ }
159+ // If the graphStep doesn't have config_form, we may be able to get it from stepConfigData (fetched when user clicks on Step Config tab)
160+ if (! stepConfigData .value ) {
161+ return null ;
162+ }
163+ const step = props .graphStep ?? (props .workflowStep as any );
164+ return {
165+ ... step ,
166+ config_form: stepConfigData .value .config_form ,
167+ inputs: stepConfigData .value .inputs ?? step .inputs ,
168+ outputs: stepConfigData .value .outputs ?? step .outputs ,
169+ } as any ;
170+ });
171+
172+ async function fetchStepConfig() {
173+ // graphStep already has config_form — no fetch needed
174+ if (props .graphStep ?.config_form || stepConfigData .value || loadingStepConfig .value ) {
175+ return ;
176+ }
177+ loadingStepConfig .value = true ;
178+ try {
179+ const step = props .graphStep ?? props .workflowStep ;
180+ const { data } = await axios .post (` ${getAppRoot ()}api/workflows/build_module ` , {
181+ type: step .type ,
182+ content_id: " content_id" in step ? step .content_id : step .tool_id ,
183+ tool_state: " tool_state" in step ? step .tool_state : {},
184+ });
185+ stepConfigData .value = data ;
186+ } finally {
187+ loadingStepConfig .value = false ;
188+ }
189+ }
190+
146191function toggleStep() {
147192 computedExpanded .value = ! computedExpanded .value ;
148193}
@@ -174,6 +219,13 @@ onUnmounted(() => {
174219 </div >
175220
176221 <div v-if =" computedExpanded" class =" portlet-content" >
222+ <div
223+ v-if =" props.workflowStep.annotation"
224+ class =" mb-2 bg-light rounded p-2"
225+ :class =" { 'mt-2': !props.inGraphView }" >
226+ {{ props.workflowStep.annotation }}
227+ </div >
228+
177229 <div v-if =" isReady && invocationStepId !== undefined" >
178230 <div style =" min-width : 1 " >
179231 <BAlert v-if =" loading" variant =" info" show >
@@ -278,6 +330,26 @@ onUnmounted(() => {
278330 </div >
279331 </div >
280332 </GTab >
333+
334+ <GTab
335+ :class =" { 'invocation-view-step-config': props.inGraphView }"
336+ lazy
337+ @click =" fetchStepConfig" >
338+ <template v-slot :title >
339+ <FontAwesomeIcon :icon =" faWrench" />
340+ <span v-localize >Step Config</span >
341+ </template >
342+ <BAlert v-if =" loadingStepConfig" show >
343+ <LoadingSpan message =" Loading step configuration" />
344+ </BAlert >
345+ <fieldset v-else-if =" activeStepWithConfig" disabled >
346+ <FormTool
347+ v-if =" workflowStepType === 'tool'"
348+ :step =" activeStepWithConfig"
349+ :datatypes =" datatypes" />
350+ <FormDefault v-else :step =" activeStepWithConfig" :datatypes =" datatypes" />
351+ </fieldset >
352+ </GTab >
281353 </GTabs >
282354 </div >
283355 </div >
@@ -302,4 +374,13 @@ onUnmounted(() => {
302374 opacity : 0.8 ;
303375 }
304376}
377+
378+ .invocation-view-step-config {
379+ :deep (.tool-header ) {
380+ position : unset ;
381+ }
382+ :deep(.ui-form-header-underlay ) {
383+ display : none ;
384+ }
385+ }
305386 </style >
0 commit comments