Skip to content

Commit

Permalink
add a topDown version of workflow run graph
Browse files Browse the repository at this point in the history
and improve styling and positioning of the side by side graph view
  • Loading branch information
ahmedhamidawan committed Jan 22, 2025
1 parent 4e81cb8 commit 6f36c54
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 122 deletions.
9 changes: 8 additions & 1 deletion client/src/components/Form/FormDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:workflow-run="workflowRun"
:active-node-id="activeNodeId"
:sync-with-graph="syncWithGraph"
:top-down="topDown"
@update:active-node-id="updateActiveNode" />
</template>

Expand Down Expand Up @@ -106,6 +107,10 @@ export default {
type: Boolean,
default: false,
},
topDown: {
type: Boolean,
default: false,
},
},
data() {
return {
Expand All @@ -121,7 +126,9 @@ export default {
},
watch: {
activeNodeId() {
this.scrollToElement(this.activeNodeId);
if (!this.topDown) {
this.scrollToElement(this.activeNodeId);
}
},
id() {
this.onCloneInputs();
Expand Down
25 changes: 13 additions & 12 deletions client/src/components/Form/FormElement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -344,19 +344,20 @@ function onAlert(value: string | undefined) {
- optional
</span>
</div>
<component
:is="isBadge ? BBadge : 'div'"
v-if="props.workflowRun"
class="flex-gapx-1 workflow-run-element-title"
:class="isBadge ? populatedClass : ''">
<i>{{ workflowRunFormTitleItems.message }}</i>
<FontAwesomeIcon
v-if="workflowRunFormTitleItems?.icon"
:icon="workflowRunFormTitleItems.icon"
:class="workflowRunFormTitleItems.class"
fixed-width />
<div v-if="props.workflowRun" class="d-flex align-items-center">
<component
:is="isBadge ? BBadge : 'div'"
class="flex-gapx-1 workflow-run-element-title"
:class="isBadge ? populatedClass : ''">
<i>{{ workflowRunFormTitleItems.message }}</i>
<FontAwesomeIcon
v-if="workflowRunFormTitleItems?.icon"
:icon="workflowRunFormTitleItems.icon"
:class="workflowRunFormTitleItems.class"
fixed-width />
</component>
<slot name="workflow-run-form-title-items" />
</component>
</div>
</div>

<FormError v-if="props.workflowRun && hasAlert && !unPopulatedError" :alerts="alerts" has-alert-class />
Expand Down
175 changes: 101 additions & 74 deletions client/src/components/Form/FormInputs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,84 +3,107 @@
<div
v-for="(input, index) in inputs"
:key="index"
:class="{ 'bordered-input': syncWithGraph && activeNodeId === index }">
<div v-if="input.type == 'conditional'" class="ui-portlet-section mt-3">
<div class="portlet-header">
<b>{{ input.test_param.label || input.test_param.name }}</b>
</div>
<div class="portlet-content">
<FormElement
:id="conditionalPrefix(input, input.test_param.name)"
v-model="input.test_param.value"
:type="input.test_param.type"
:help="input.test_param.help"
:help-format="input.test_param.help_format"
:refresh-on-change="false"
:disabled="sustainConditionals"
:attributes="input.test_param"
@change="onChange" />
<div v-for="(caseDetails, caseId) in input.cases" :key="caseId">
<FormNode
v-if="conditionalMatch(input, caseId)"
v-bind="$props"
:inputs="caseDetails.inputs"
:prefix="getPrefix(input.name)" />
:class="{ 'bordered-input': syncWithGraph && !topDown && activeNodeId === index }">
<div v-if="!syncWithGraph || !topDown || activeNodeId === index">
<div v-if="input.type == 'conditional'" class="ui-portlet-section mt-3">
<div class="portlet-header">
<b>{{ input.test_param.label || input.test_param.name }}</b>
</div>
<div class="portlet-content">
<FormElement
:id="conditionalPrefix(input, input.test_param.name)"
v-model="input.test_param.value"
:type="input.test_param.type"
:help="input.test_param.help"
:help-format="input.test_param.help_format"
:refresh-on-change="false"
:disabled="sustainConditionals"
:attributes="input.test_param"
@change="onChange" />
<div v-for="(caseDetails, caseId) in input.cases" :key="caseId">
<FormNode
v-if="conditionalMatch(input, caseId)"
v-bind="$props"
:inputs="caseDetails.inputs"
:prefix="getPrefix(input.name)" />
</div>
</div>
</div>
</div>
<div v-else-if="input.type == 'repeat'">
<FormRepeat
:input="input"
:sustain-repeats="sustainRepeats"
:passthrough-props="$props"
:prefix="prefix"
@insert="() => repeatInsert(input)"
@delete="(id) => repeatDelete(input, id)"
@swap="(a, b) => repeatSwap(input, a, b)" />
</div>
<div v-else-if="input.type == 'section'">
<FormCard :title="input.title || input.name" :expanded.sync="input.expanded" :collapsible="true">
<template v-slot:body>
<div v-if="input.help" class="my-2" data-description="section help">{{ input.help }}</div>
<FormNode v-bind="$props" :inputs="input.inputs" :prefix="getPrefix(input.name)" />
<div v-else-if="input.type == 'repeat'">
<FormRepeat
:input="input"
:sustain-repeats="sustainRepeats"
:passthrough-props="$props"
:prefix="prefix"
@insert="() => repeatInsert(input)"
@delete="(id) => repeatDelete(input, id)"
@swap="(a, b) => repeatSwap(input, a, b)" />
</div>
<div v-else-if="input.type == 'section'">
<FormCard :title="input.title || input.name" :expanded.sync="input.expanded" :collapsible="true">
<template v-slot:body>
<div v-if="input.help" class="my-2" data-description="section help">{{ input.help }}</div>
<FormNode v-bind="$props" :inputs="input.inputs" :prefix="getPrefix(input.name)" />
</template>
</FormCard>
</div>
<FormElement
v-else
:id="getPrefix(input.name)"
v-model="input.value"
:title="input.label || input.name"
:type="input.type"
:error="input.error"
:warning="input.warning"
:help="input.help"
:help-format="input.help_format"
:refresh-on-change="input.refresh_on_change"
:attributes="input.attributes || input"
:collapsed-enable-text="collapsedEnableText"
:collapsed-enable-icon="collapsedEnableIcon"
:collapsed-disable-text="collapsedDisableText"
:collapsed-disable-icon="collapsedDisableIcon"
:loading="loading"
:workflow-building-mode="workflowBuildingMode"
:workflow-run="workflowRun"
@change="onChange">
<template v-slot:workflow-run-form-title-items>
<template v-if="syncWithGraph">
<b-button
v-if="!topDown"
class="text-decoration-none"
size="sm"
variant="link"
:title="activeNodeId === index ? 'Active' : 'View in Graph'"
:disabled="activeNodeId === index"
@click="$emit('update:active-node-id', index)">
<span class="fas fa-sitemap" />
<span class="fas fa-arrow-right" />
</b-button>
<b-button-group v-else class="ml-2">
<b-button
v-b-tooltip.hover.noninteractive
title="Previous Input"
:disabled="activeNodeId === 0"
@click="$emit('update:active-node-id', index - 1)">
<span class="fas fa-arrow-left" />
</b-button>
<b-button
v-b-tooltip.hover.noninteractive
title="Next Input"
:disabled="activeNodeId === inputs.length - 1"
@click="$emit('update:active-node-id', index + 1)">
<span class="fas fa-arrow-right" />
</b-button>
</b-button-group>
</template>
</template>
</FormCard>
</FormElement>
</div>
<FormElement
v-else
:id="getPrefix(input.name)"
v-model="input.value"
:title="input.label || input.name"
:type="input.type"
:error="input.error"
:warning="input.warning"
:help="input.help"
:help-format="input.help_format"
:refresh-on-change="input.refresh_on_change"
:attributes="input.attributes || input"
:collapsed-enable-text="collapsedEnableText"
:collapsed-enable-icon="collapsedEnableIcon"
:collapsed-disable-text="collapsedDisableText"
:collapsed-disable-icon="collapsedDisableIcon"
:loading="loading"
:workflow-building-mode="workflowBuildingMode"
:workflow-run="workflowRun"
@change="onChange">
<template v-slot:workflow-run-form-title-items>
<b-button
v-if="syncWithGraph"
class="text-decoration-none"
:style="{ 'z-index': 100, right: 0 }"
size="sm"
variant="link"
:title="activeNodeId === index ? 'Active' : 'View in Graph'"
:disabled="activeNodeId === index"
@click="$emit('update:active-node-id', index)">
<span class="fas fa-sitemap" />
<span class="fas fa-arrow-right" />
</b-button>
</template>
</FormElement>
<!-- TODO:
Here, need `v-else-if="syncWithGraph && topDown && activeNodeId && activeNodeId >= inputs.length"`
for when syncing with graph in top-down, and user activates a node that isn't an input
-->
</div>
</div>
</template>
Expand Down Expand Up @@ -162,6 +185,10 @@ export default {
type: Boolean,
default: false,
},
topDown: {
type: Boolean,
default: false,
},
},
watch: {
activeNodeId() {
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/Workflow/Run/WorkflowRun.vue
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ defineExpose({
v-else-if="invocations.length > 0"
:invocations="invocations"
:workflow-name="workflowName" />
<div v-else>
<div v-else class="h-100">
<BAlert
v-if="hasUpgradeMessages || hasStepVersionChanges"
class="mb-4"
Expand All @@ -194,7 +194,7 @@ defineExpose({
<BLink v-else @click="onImport">click here to import the workflow and review the issues</BLink>
<span>before running this workflow.</span>
</BAlert>
<div v-else>
<div v-else class="h-100">
<BAlert
v-if="submissionError"
class="mb-4"
Expand Down
Loading

0 comments on commit 6f36c54

Please sign in to comment.