diff --git a/client/package.json b/client/package.json index b2a751ff3d94..de12b9f71852 100644 --- a/client/package.json +++ b/client/package.json @@ -66,6 +66,7 @@ "elkjs": "^0.8.2", "file-saver": "^2.0.5", "flush-promises": "^1.0.2", + "font-awesome-6": "npm:@fortawesome/free-solid-svg-icons@6", "glob": "^10.3.10", "handsontable": "^4.0.0", "hsluv": "^1.0.1", diff --git a/client/src/components/Panels/ActivityPanel.vue b/client/src/components/Panels/ActivityPanel.vue index 20fb01d0d4ca..d97512c24cc5 100644 --- a/client/src/components/Panels/ActivityPanel.vue +++ b/client/src/components/Panels/ActivityPanel.vue @@ -79,17 +79,6 @@ const hasGoToAll = computed(() => props.goToAllTitle && props.href); flex-grow: 1; overflow-y: auto; position: relative; - button:first-child { - background: none; - border: none; - text-align: left; - transition: none; - width: 100%; - border-color: transparent; - } - button:first-child:hover { - background: $gray-200; - } } .activity-panel-footer { diff --git a/client/src/components/Panels/InputPanel.vue b/client/src/components/Panels/InputPanel.vue new file mode 100644 index 000000000000..2150d969050a --- /dev/null +++ b/client/src/components/Panels/InputPanel.vue @@ -0,0 +1,83 @@ + + + + + + + + {{ input.title }} + {{ input.description }} + + + + + + diff --git a/client/src/components/Panels/ToolBox.vue b/client/src/components/Panels/ToolBox.vue index 50e5aeb10ac7..7bc882468056 100644 --- a/client/src/components/Panels/ToolBox.vue +++ b/client/src/components/Panels/ToolBox.vue @@ -33,7 +33,6 @@ const props = defineProps({ panelView: { type: String, required: true }, showAdvanced: { type: Boolean, default: false, required: true }, panelQuery: { type: String, required: true }, - editorWorkflows: { type: Array, default: null }, dataManagers: { type: Array, default: null }, moduleSections: { type: Array as PropType>, default: null }, }); diff --git a/client/src/components/Panels/ToolPanel.vue b/client/src/components/Panels/ToolPanel.vue index fc9b9db2aa60..55bc38f28694 100644 --- a/client/src/components/Panels/ToolPanel.vue +++ b/client/src/components/Panels/ToolPanel.vue @@ -17,7 +17,6 @@ import Heading from "@/components/Common/Heading.vue"; const props = defineProps({ workflow: { type: Boolean, default: false }, - editorWorkflows: { type: Array, default: null }, dataManagers: { type: Array, default: null }, moduleSections: { type: Array, default: null }, }); @@ -198,7 +197,6 @@ watch( :panel-query.sync="query" :panel-view="currentPanelView" :show-advanced.sync="showAdvanced" - :editor-workflows="editorWorkflows" :data-managers="dataManagers" :module-sections="moduleSections" @updatePanelView="updatePanelView" diff --git a/client/src/components/Workflow/Editor/Forms/FormDefault.test.js b/client/src/components/Workflow/Editor/Forms/FormDefault.test.js index 2a09dc0d7963..7fb84f507636 100644 --- a/client/src/components/Workflow/Editor/Forms/FormDefault.test.js +++ b/client/src/components/Workflow/Editor/Forms/FormDefault.test.js @@ -24,6 +24,7 @@ describe("FormDefault", () => { contentId: "id", annotation: "annotation", label: "label", + name: "name", type: "subworkflow", configForm: { inputs: [], @@ -42,7 +43,7 @@ describe("FormDefault", () => { it("check initial value and value change", async () => { const title = wrapper.find(".portlet-title-text").text(); - expect(title).toBe("label"); + expect(title).toBe("name"); const inputCount = wrapper.findAll("input").length; expect(inputCount).toBe(4); const outputLabelCount = wrapper.findAll("#__label__output-name").length; diff --git a/client/src/components/Workflow/Editor/Forms/FormDefault.vue b/client/src/components/Workflow/Editor/Forms/FormDefault.vue index 8ac56fd941da..3a0f82c0a9d6 100644 --- a/client/src/components/Workflow/Editor/Forms/FormDefault.vue +++ b/client/src/components/Workflow/Editor/Forms/FormDefault.vue @@ -97,9 +97,6 @@ const { stepId, contentId, annotation, label, name, type, configForm } = useStep const { stepStore } = useWorkflowStores(); const uniqueErrorLabel = useUniqueLabelError(stepStore, label.value); const stepTitle = computed(() => { - if (label.value) { - return label.value; - } if (isSubworkflow.value) { return name.value; } else { diff --git a/client/src/components/Workflow/Editor/Index.vue b/client/src/components/Workflow/Editor/Index.vue index 31365fa3d4f6..99480764c098 100644 --- a/client/src/components/Workflow/Editor/Index.vue +++ b/client/src/components/Workflow/Editor/Index.vue @@ -47,11 +47,14 @@ workflow :module-sections="moduleSections" :data-managers="dataManagers" - :editor-workflows="workflows" @onInsertTool="onInsertTool" @onInsertModule="onInsertModule" @onInsertWorkflow="onInsertWorkflow" @onInsertWorkflowSteps="onInsertWorkflowSteps" /> + { - const updatedStep = { - ...stepData, - tool_state: response.tool_state, - inputs: response.inputs, - outputs: response.outputs, - config_form: response.config_form, - }; + const response = await getModule( + { name, type, content_id: contentId, tool_state: state }, + stepData.id, + this.stateStore.setLoadingState + ); - this.stepStore.updateStep(updatedStep); - action.updateStepData = updatedStep; + const updatedStep = { + ...stepData, + tool_state: response.tool_state, + inputs: response.inputs, + outputs: response.outputs, + config_form: response.config_form, + }; - this.stateStore.activeNodeId = stepData.id; - } - ); + this.stepStore.updateStep(updatedStep); + action.updateStepData = updatedStep; + + this.stateStore.activeNodeId = stepData.id; }, async _loadEditorData(data) { if (data.name !== undefined) { diff --git a/client/src/components/Workflow/Editor/modules/activities.ts b/client/src/components/Workflow/Editor/modules/activities.ts index aed37909dea2..5a5534a4af0e 100644 --- a/client/src/components/Workflow/Editor/modules/activities.ts +++ b/client/src/components/Workflow/Editor/modules/activities.ts @@ -13,6 +13,7 @@ import { faWrench, } from "@fortawesome/free-solid-svg-icons"; import { watchImmediate } from "@vueuse/core"; +import { faDiagramNext } from "font-awesome-6"; import { computed, type Ref } from "vue"; import { type Activity, useActivityStore } from "@/stores/activityStore"; @@ -27,6 +28,15 @@ export const workflowEditorActivities = [ icon: faPencilAlt, visible: true, }, + { + title: "Inputs", + id: "workflow-editor-inputs", + tooltip: "Add input steps to your workflow", + description: "Add input steps to your workflow.", + icon: faDiagramNext, + panel: true, + visible: true, + }, { title: "Tools", id: "workflow-editor-tools", diff --git a/client/src/components/Workflow/Editor/modules/inputs.ts b/client/src/components/Workflow/Editor/modules/inputs.ts new file mode 100644 index 000000000000..c152058d4360 --- /dev/null +++ b/client/src/components/Workflow/Editor/modules/inputs.ts @@ -0,0 +1,90 @@ +import { faFile, faFolder } from "@fortawesome/free-regular-svg-icons"; +import { faPencilAlt } from "@fortawesome/free-solid-svg-icons"; +import { type IconDefinition } from "font-awesome-6"; + +export interface WorkflowInput { + id?: string; // unique ID. defaults to module ID + moduleId: string; + title: string; + description: string; + stateOverwrites?: { + parameter_type?: "text" | "integer" | "boolean" | "color" | "float" | "directory_uri"; + }; + icon: IconDefinition; +} + +export function getWorkflowInputs(): WorkflowInput[] { + return [ + { + moduleId: "data_input", + title: "Input Dataset", + description: "Single dataset input", + icon: faFile, + }, + { + moduleId: "data_collection_input", + title: "Input Dataset Collection", + description: "Input for a collection of datasets", + icon: faFolder, + }, + { + moduleId: "parameter_input", + title: "Text Input", + description: "Text parameter used for workflow logic", + icon: faPencilAlt, + stateOverwrites: { + parameter_type: "text", + }, + }, + { + id: "parameter_input_integer", + moduleId: "parameter_input", + title: "Integer Input", + description: "Whole number parameter used for workflow logic", + icon: faPencilAlt, + stateOverwrites: { + parameter_type: "integer", + }, + }, + { + id: "parameter_input_float", + moduleId: "parameter_input", + title: "Float Input", + description: "Imprecise decimal number parameter used for workflow logic", + icon: faPencilAlt, + stateOverwrites: { + parameter_type: "float", + }, + }, + { + id: "parameter_input_boolean", + moduleId: "parameter_input", + title: "Boolean Input", + description: "True / False parameter used for workflow logic", + icon: faPencilAlt, + stateOverwrites: { + parameter_type: "boolean", + }, + }, + { + id: "parameter_input_color", + moduleId: "parameter_input", + title: "Color Input", + description: "Color parameter used for workflow logic", + icon: faPencilAlt, + stateOverwrites: { + parameter_type: "color", + }, + }, + { + id: "parameter_input_directory_uri", + moduleId: "parameter_input", + title: "Directory Input", + description: "Directory parameter used for workflow logic", + icon: faPencilAlt, + stateOverwrites: { + parameter_type: "directory_uri", + }, + }, + ]; +} diff --git a/client/src/entry/analysis/modules/WorkflowEditor.vue b/client/src/entry/analysis/modules/WorkflowEditor.vue index fb8ed6eea9d5..67634f4a3842 100644 --- a/client/src/entry/analysis/modules/WorkflowEditor.vue +++ b/client/src/entry/analysis/modules/WorkflowEditor.vue @@ -7,7 +7,6 @@ :initial-version="editorConfig.initialVersion" :module-sections="editorConfig.moduleSections" :workflow-tags="editorConfig.tags" - :workflows="editorConfig.workflows" @update:confirmation="$emit('update:confirmation', $event)" />