Skip to content

Commit

Permalink
Added reusability & consistency for Workflow headers on: Workflow Inv…
Browse files Browse the repository at this point in the history
…ocations Page and Workflow Run Form Page
  • Loading branch information
hujambo-dunia committed Nov 4, 2024
1 parent aedbb73 commit 41d3143
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 229 deletions.
75 changes: 71 additions & 4 deletions client/src/components/Workflow/Run/WorkflowRunFormSimple.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@
</WorkflowStorageConfiguration>
</b-dropdown-form>
</b-dropdown>
<!-- waitingForRequest:{{ waitingForRequest }}<br> -->
<!-- hasValidationErrors:{{ hasValidationErrors }}<br> -->
<!-- !canRunOnHistory:{{ !canRunOnHistory }}<br> -->
<ButtonSpinner
id="run-workflow"
:wait="waitingForRequest"
Expand All @@ -65,7 +68,47 @@
</div>
</div>
</div>
<WorkflowRunName v-if="isConfigLoaded" :model="this.model" :embedded="false" />




<div class="ui-portlet-section w-100">
<div
class="portlet-header cursor-pointer"
role="button"
:tabindex="0"
@keyup.enter="expandAnnotations = !expandAnnotations"
@click="expandAnnotations = !expandAnnotations">
<b class="portlet-operations portlet-title-text">
<span v-localize class="font-weight-bold">About This Workflow</span>
</b>
<span v-b-tooltip.hover.bottom title="Collapse/Expand" variant="link" size="sm" class="float-right">
<FontAwesomeIcon :icon="expandAnnotations ? 'fa fa-chevron-up' : 'fa fa-chevron-up'" fixed-width />
</span>
</div>
<div class="portlet-content" :style="expandAnnotations ? 'display: none;' : ''">
<!-- TODO confirm timezone consistency -->
<!-- <UtcDate :date="model.runData.annotation.update_time" mode="elapsed" /> -->
<!-- <UtcDate :date="invocation.update_time" mode="elapsed" /> -->
<WorkflowAnnotation
v-if="true"
:workflow-id="model.workflowId"
:update-time="model.runData.annotation.update_time"
:history-id="model.historyId"
:from-panel="false"
:target-history="'current'" />
{{ model.runData.annotation.annotation }}
<br>
<StatelessTags
:value="workflowTags"
:disabled="true" />
</div>
</div>





<FormDisplay
:inputs="formInputs"
:allow-empty-value-on-required-input="true"
Expand All @@ -77,27 +120,34 @@
</template>

<script>
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import ButtonSpinner from "components/Common/ButtonSpinner";
import FormDisplay from "components/Form/FormDisplay";
import { allowCachedJobs } from "components/Tool/utilities";
import { isWorkflowInput } from "components/Workflow/constants";
import { storeToRefs } from "pinia";
import { mapActions,storeToRefs } from "pinia";
import { errorMessageAsString } from "utils/simple-error";
import Vue from "vue";
import { useConfig } from "@/composables/config";
import { useUserStore } from "@/stores/userStore";
import { useWorkflowStore } from "@/stores/workflowStore";
import { invokeWorkflow } from "./services";
import WorkflowRunName from "./WorkflowRunName";
import WorkflowStorageConfiguration from "./WorkflowStorageConfiguration";
import WorkflowAnnotation from "../../Workflow/WorkflowAnnotation.vue";
import StatelessTags from "@/components/TagsMultiselect/StatelessTags.vue";
export default {
components: {
ButtonSpinner,
FormDisplay,
WorkflowStorageConfiguration,
WorkflowRunName,
FontAwesomeIcon,
WorkflowAnnotation,
StatelessTags,
},
props: {
model: {
Expand Down Expand Up @@ -138,6 +188,7 @@ export default {
preferredObjectStoreId: null,
preferredIntermediateObjectStoreId: null,
waitingForRequest: false,
expandAnnotations: true,
};
},
computed: {
Expand Down Expand Up @@ -182,6 +233,21 @@ export default {
canRunOnHistory() {
return this.canMutateCurrentHistory || this.sendToNewHistory;
},
// workflowVersions() {
// return this.getStoredWorkflowByInstanceId(this.workflowID);
// },
workflowTags() {
return this.model.runData.annotation.tags.map((t) => t.user_tname);
//TODO remove after confirming new structure:
// return {
// id: props.model.runData.id,
// name: props.model.runData.name,
// owner: props.model.runData.owner,
// tags: props.model.runData.annotation.tags.map((t: { user_tname: string }) => t.user_tname),
// annotations: [props.model.runData.annotation.annotation],
// update_time: props.model.runData.annotation.update_time,
// };
},
},
methods: {
onValidation(validation) {
Expand Down Expand Up @@ -255,6 +321,7 @@ export default {
})
.finally(() => (this.waitingForRequest = false));
},
...mapActions(useWorkflowStore, ["getStoredWorkflowByInstanceId", "fetchWorkflowForInstanceId"]),
},
};
</script>
56 changes: 0 additions & 56 deletions client/src/components/Workflow/Run/WorkflowRunName.vue

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getLocalVue } from "tests/jest/helpers";
import sampleInvocation from "@/components/Workflow/test/json/invocation.json";
import { useUserStore } from "@/stores/userStore";

import WorkflowInvocationHeader from "./WorkflowInvocationHeader.vue";
import WorkflowNavigationTitle from "../Workflow/WorkflowNavigationTitle.vue";

// Constants
const WORKFLOW_OWNER = "test-user";
Expand Down Expand Up @@ -62,14 +62,14 @@ jest.mock("@/stores/workflowStore", () => {
const localVue = getLocalVue();

/**
* Mounts the WorkflowInvocationHeader component with props/stores adjusted given the parameters
* Mounts the WorkflowNavigationTitle component with props/stores adjusted given the parameters
* @param ownsWorkflow Whether the user owns the workflow associated with the invocation
* @param hasReturnBtn Whether the component should have a return to invocations list button
* @param unimportableWorkflow Whether the workflow import should fail
* @returns The wrapper object
*/
async function mountWorkflowInvocationHeader(ownsWorkflow = true, hasReturnBtn = false, unimportableWorkflow = false) {
const wrapper = shallowMount(WorkflowInvocationHeader as object, {
async function mountWorkflowNavigationTitle(ownsWorkflow = true, hasReturnBtn = false, unimportableWorkflow = false) {
const wrapper = shallowMount(WorkflowNavigationTitle as object, {
propsData: {
invocation: {
...sampleInvocation,
Expand All @@ -89,10 +89,10 @@ async function mountWorkflowInvocationHeader(ownsWorkflow = true, hasReturnBtn =
return { wrapper };
}

describe("WorkflowInvocationHeader renders", () => {
describe("WorkflowNavigationTitle renders", () => {
// Included both cases in one test because these are always constant
it("(always) the workflow name in header and run button in actions", async () => {
const { wrapper } = await mountWorkflowInvocationHeader();
const { wrapper } = await mountWorkflowNavigationTitle();

const heading = wrapper.find(SELECTORS.INVOKED_WORKFLOW_HEADING);
expect(heading.text()).toBe(`Invoked Workflow: "${SAMPLE_WORKFLOW.name}"`);
Expand All @@ -103,13 +103,13 @@ describe("WorkflowInvocationHeader renders", () => {
});

it("return to invocations list button if not from panel", async () => {
const { wrapper } = await mountWorkflowInvocationHeader(false, true);
const { wrapper } = await mountWorkflowNavigationTitle(false, true);
const returnButton = wrapper.find(SELECTORS.RETURN_TO_INVOCATIONS_LIST_BUTTON);
expect(returnButton.text()).toBe("Invocations List");
});

it("edit button if user owns the workflow", async () => {
const { wrapper } = await mountWorkflowInvocationHeader();
const { wrapper } = await mountWorkflowNavigationTitle();
const actionsGroup = wrapper.find(SELECTORS.ACTIONS_BUTTON_GROUP);
const editButton = actionsGroup.find(SELECTORS.EDIT_WORKFLOW_BUTTON);
expect(editButton.attributes("to")).toBe(
Expand All @@ -118,16 +118,16 @@ describe("WorkflowInvocationHeader renders", () => {
});

it("import button instead if user does not own the workflow", async () => {
const { wrapper } = await mountWorkflowInvocationHeader(false);
const { wrapper } = await mountWorkflowNavigationTitle(false);
const actionsGroup = wrapper.find(SELECTORS.ACTIONS_BUTTON_GROUP);
const importButton = actionsGroup.find(SELECTORS.IMPORT_WORKFLOW_BUTTON);
expect(importButton.exists()).toBe(true);
});
});

describe("Importing a workflow in WorkflowInvocationHeader", () => {
describe("Importing a workflow in WorkflowNavigationTitle", () => {
it("should show a confirmation dialog when the import is successful", async () => {
const { wrapper } = await mountWorkflowInvocationHeader(false);
const { wrapper } = await mountWorkflowNavigationTitle(false);
const actionsGroup = wrapper.find(SELECTORS.ACTIONS_BUTTON_GROUP);
const importButton = actionsGroup.find(SELECTORS.IMPORT_WORKFLOW_BUTTON);

Expand All @@ -141,7 +141,7 @@ describe("Importing a workflow in WorkflowInvocationHeader", () => {
});

it("should show an error dialog when the import fails", async () => {
const { wrapper } = await mountWorkflowInvocationHeader(false, false, true);
const { wrapper } = await mountWorkflowNavigationTitle(false, false, true);
const actionsGroup = wrapper.find(SELECTORS.ACTIONS_BUTTON_GROUP);
const importButton = actionsGroup.find(SELECTORS.IMPORT_WORKFLOW_BUTTON);

Expand Down
Loading

0 comments on commit 41d3143

Please sign in to comment.