Skip to content

Commit 3d2a0dd

Browse files
Merge pull request #22500 from ahmedhamidawan/workflow_editor_activity_enh
Workflow editor activity bar enhancements
2 parents 4cafd91 + 36db3bc commit 3d2a0dd

8 files changed

Lines changed: 157 additions & 80 deletions

File tree

client/src/components/ActivityBar/ActivityBar.vue

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import localize from "@/utils/localization";
1818
1919
import ChatHistoryPanel from "../ChatGXY/ChatHistoryPanel.vue";
2020
import InvocationsPanel from "../Panels/InvocationsPanel.vue";
21+
import ActivityBarHeader from "./ActivityBarHeader.vue";
22+
import ActivityBarSeparator from "./ActivityBarSeparator.vue";
2123
import ActivityItem from "./ActivityItem.vue";
2224
import InteractiveItem from "./Items/InteractiveItem.vue";
2325
import NotificationItem from "./Items/NotificationItem.vue";
@@ -39,6 +41,7 @@ const props = withDefaults(
3941
activityBarId?: string;
4042
specialActivities?: Activity[];
4143
exitActivity?: Activity;
44+
runActivity?: Activity;
4245
showAdmin?: boolean;
4346
optionsTitle?: string;
4447
optionsTooltip?: string;
@@ -47,12 +50,15 @@ const props = withDefaults(
4750
optionsSearchPlaceholder?: string;
4851
initialActivity?: string;
4952
hidePanel?: boolean;
53+
headerIcon?: IconDefinition;
54+
headerTitle?: string;
5055
}>(),
5156
{
5257
defaultActivities: undefined,
5358
activityBarId: "default",
5459
specialActivities: () => [],
5560
exitActivity: undefined,
61+
runActivity: undefined,
5662
showAdmin: true,
5763
optionsTitle: "More",
5864
optionsHeading: "Additional Activities",
@@ -61,6 +67,8 @@ const props = withDefaults(
6167
optionsTooltip: "View additional activities",
6268
initialActivity: undefined,
6369
hidePanel: false,
70+
headerIcon: undefined,
71+
headerTitle: undefined,
6472
},
6573
);
6674
@@ -252,6 +260,11 @@ defineExpose({
252260
@dragover.prevent="onDragOver"
253261
@dragenter.prevent="onDragEnter"
254262
@dragleave.prevent="onDragLeave">
263+
<ActivityBarHeader
264+
:icon="props.headerIcon"
265+
:title="props.headerTitle"
266+
:is-side-bar-open="isSideBarOpen"
267+
@close-sidebar="activityStore.closeSideBar" />
255268
<b-nav vertical class="flex-nowrap p-1 h-100 vertical-overflow">
256269
<draggable
257270
v-model="activities"
@@ -320,7 +333,8 @@ defineExpose({
320333
</div>
321334
</draggable>
322335
</b-nav>
323-
<b-nav v-if="!isAnonymous" vertical class="activity-footer flex-nowrap p-1">
336+
<ActivityBarSeparator />
337+
<b-nav v-if="!isAnonymous" vertical class="flex-nowrap p-1">
324338
<template v-for="activity in props.specialActivities">
325339
<ActivityItem
326340
v-if="activity.panel"
@@ -377,6 +391,17 @@ defineExpose({
377391
tooltip="Administer this Galaxy"
378392
variant="danger"
379393
@click="toggleSidebar('admin')" />
394+
<ActivityItem
395+
v-if="props.runActivity"
396+
:id="`${props.runActivity.id}`"
397+
:activity-bar-id="props.activityBarId"
398+
:icon="props.runActivity.icon"
399+
:indicator="props.runActivity.indicator"
400+
:indicator-variant="props.runActivity.indicatorVariant"
401+
:title="props.runActivity.title"
402+
:tooltip="props.runActivity.tooltip"
403+
:variant="props.runActivity.variant"
404+
@click="onActivityClicked(props.runActivity)" />
380405
<ActivityItem
381406
v-if="props.exitActivity"
382407
:id="`${props.exitActivity.id}`"
@@ -443,11 +468,6 @@ defineExpose({
443468
display: none;
444469
}
445470
446-
.activity-footer {
447-
border-top: $border-default;
448-
border-top-style: dotted;
449-
}
450-
451471
.activity-popper-disabled {
452472
.popper-element {
453473
display: none;
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<script setup lang="ts">
2+
import type { IconDefinition } from "@fortawesome/free-solid-svg-icons";
3+
import { faChevronLeft, faHome } from "@fortawesome/free-solid-svg-icons";
4+
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
5+
6+
import ActivityBarSeparator from "./ActivityBarSeparator.vue";
7+
8+
interface Props {
9+
/** Whether an activity's side panel is currently open. */
10+
isSideBarOpen: boolean;
11+
/** The icon to display in the header. */
12+
icon?: IconDefinition;
13+
/** The title to display in the header. */
14+
title?: string;
15+
}
16+
const props = withDefaults(defineProps<Props>(), {
17+
icon: () => faHome,
18+
title: "Activities",
19+
});
20+
21+
const emit = defineEmits<{
22+
(e: "close-sidebar"): void;
23+
}>();
24+
25+
function closeSidebar(event: KeyboardEvent | MouseEvent) {
26+
if (props.isSideBarOpen && (event instanceof MouseEvent || event.key === "Enter" || event.key === " ")) {
27+
emit("close-sidebar");
28+
}
29+
}
30+
</script>
31+
32+
<template>
33+
<div>
34+
<!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->
35+
<div
36+
class="rounded activity-bar-header-badge"
37+
:class="{ 'sidebar-opened': props.isSideBarOpen }"
38+
:role="props.isSideBarOpen ? 'button' : undefined"
39+
:tabindex="props.isSideBarOpen ? 0 : undefined"
40+
:title="props.isSideBarOpen ? 'Close panel' : 'Activity Bar'"
41+
@click="closeSidebar"
42+
@keydown="closeSidebar">
43+
<FontAwesomeIcon :icon="props.isSideBarOpen ? faChevronLeft : props.icon" size="sm" fixed-width />
44+
<span class="activity-bar-header-text">{{ props.title }}</span>
45+
</div>
46+
<ActivityBarSeparator />
47+
</div>
48+
</template>
49+
50+
<style scoped lang="scss">
51+
.activity-bar-header-badge {
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
gap: var(--spacing);
56+
margin: var(--spacing-1);
57+
padding: var(--spacing-1) 0;
58+
color: var(--color-blue-600);
59+
60+
&.sidebar-opened {
61+
background: var(--color-grey-200);
62+
&:hover {
63+
color: var(--color-blue-700);
64+
}
65+
}
66+
67+
.activity-bar-header-text {
68+
font-size: var(--font-size-small);
69+
}
70+
}
71+
</style>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<template>
2+
<div class="activity-bar-separator" />
3+
</template>
4+
5+
<style scoped lang="scss">
6+
.activity-bar-separator {
7+
border-top: 1px solid var(--color-grey-600);
8+
border-top-style: dotted;
9+
}
10+
</style>

client/src/components/Markdown/MarkdownHelp.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
22
import { computed } from "vue";
33
4+
import ExternalLink from "../ExternalLink.vue";
45
import DirectiveHelpSection from "./DirectiveHelpSection.vue";
56
67
interface MarkdownHelpProps {
@@ -24,7 +25,7 @@ const page = computed(() => props.mode == "page");
2425

2526
<p>
2627
For an overview of standard Markdown visit the
27-
<a href="https://commonmark.org/help/tutorial/">commonmark.org tutorial</a>.
28+
<ExternalLink href="https://commonmark.org/help/tutorial/">commonmark.org tutorial</ExternalLink>.
2829
</p>
2930

3031
<p>

client/src/components/Workflow/Editor/Index.vue

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@
1515
@onRefactor="onRefactor"
1616
@onShow="hideModal" />
1717
<MessagesModal :title="messageTitle" :message="messageBody" :error="messageIsError" @onHidden="resetMessage" />
18-
<SaveChangesModal :nav-url.sync="navUrl" :show-modal.sync="showSaveChangesModal" @on-proceed="onNavigate" />
18+
<SaveChangesModal
19+
:append-version="saveChangesAppendVersion"
20+
:nav-url="navUrl"
21+
:show-modal.sync="showSaveChangesModal"
22+
@on-proceed="onNavigate" />
1923
<GModal
2024
:show.sync="showSaveAsModal"
2125
confirm
@@ -39,6 +43,7 @@
3943
:default-activities="workflowActivities"
4044
:special-activities="specialWorkflowActivities"
4145
:exit-activity="exitWorkflowActivity"
46+
:run-activity="runWorkflowActivity"
4247
activity-bar-id="workflow-editor"
4348
:show-admin="false"
4449
options-title="Options"
@@ -48,6 +53,8 @@
4853
initial-activity="workflow-editor-attributes"
4954
:options-icon="faCog"
5055
:hide-panel="reportActive"
56+
:header-icon="faSitemap"
57+
header-title="Editor"
5158
@activityClicked="onActivityClicked">
5259
<template v-slot:side-panel="{ isActiveSideBar }">
5360
<ToolPanel v-if="isActiveSideBar('workflow-editor-tools')" workflow @onInsertTool="onInsertTool" />
@@ -116,7 +123,7 @@
116123
ref="markdownEditor"
117124
:markdown-text="report.markdown"
118125
mode="report"
119-
:title="'Workflow Report: ' + name"
126+
:title="'Workflow Report Template: ' + name"
120127
:labels="getLabels"
121128
:steps="steps"
122129
@insert="insertMarkdown"
@@ -181,14 +188,14 @@
181188
variant="secondary"
182189
:disabled="!undoRedoStore.hasUndo"
183190
@click="undoRedoStore.undo()">
184-
<FontAwesomeIcon :icon="faArrowLeft" />
191+
<FontAwesomeIcon :icon="faUndo" />
185192
</b-button>
186193
<b-button
187194
:title="undoRedoStore.redoText + ' (Ctrl + Shift + Z)'"
188195
variant="secondary"
189196
:disabled="!undoRedoStore.hasRedo"
190197
@click="undoRedoStore.redo()">
191-
<FontAwesomeIcon :icon="faArrowRight" />
198+
<FontAwesomeIcon :icon="faRedo" />
192199
</b-button>
193200
<b-button
194201
id="workflow-save-button"
@@ -247,7 +254,7 @@
247254
</template>
248255

249256
<script>
250-
import { faArrowLeft, faArrowRight, faCog, faKey, faSave, faTimes, faWrench } from "@fortawesome/free-solid-svg-icons";
257+
import { faCog, faKey, faRedo, faSave, faSitemap, faTimes, faUndo, faWrench } from "@fortawesome/free-solid-svg-icons";
251258
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
252259
import { until, whenever } from "@vueuse/core";
253260
import { logicAnd, logicNot, logicOr } from "@vueuse/math";
@@ -610,9 +617,8 @@ export default {
610617
const isNewTempWorkflow = computed(() => !props.workflowId);
611618
const lintData = useLintData(id, steps, datatypesMapper, annotation, readme, license, creator);
612619
613-
const { specialWorkflowActivities, exitWorkflowActivity } = useSpecialWorkflowActivities(
620+
const { specialWorkflowActivities, exitWorkflowActivity, runWorkflowActivity } = useSpecialWorkflowActivities(
614621
computed(() => ({
615-
hasInvalidConnections: hasInvalidConnections.value,
616622
lintData: lintData,
617623
})),
618624
);
@@ -716,13 +722,15 @@ export default {
716722
insertMarkdown,
717723
specialWorkflowActivities,
718724
exitWorkflowActivity,
725+
runWorkflowActivity,
719726
isNewTempWorkflow,
720727
saveWorkflowTitle,
721728
confirm,
722729
inputs,
723730
workflowActivities,
724731
faKey,
725732
faWrench,
733+
faSitemap,
726734
showDropdown: false,
727735
lintData,
728736
onHighlightRegion,
@@ -754,12 +762,13 @@ export default {
754762
graphOffset: { left: 0, top: 0, width: 0, height: 0 },
755763
debounceTimer: null,
756764
showSaveChangesModal: false,
765+
saveChangesAppendVersion: false,
757766
navUrl: "",
758-
faArrowLeft,
759-
faArrowRight,
760767
faTimes,
761768
faCog,
762769
faSave,
770+
faRedo,
771+
faUndo,
763772
};
764773
},
765774
computed: {
@@ -994,13 +1003,8 @@ export default {
9941003
}
9951004
},
9961005
async onActivityClicked(activityId) {
997-
if (activityId === "save-and-exit") {
998-
await this.saveOrCreate();
999-
this.$router.push("/workflows/list");
1000-
}
1001-
10021006
if (activityId === "exit") {
1003-
this.$router.push("/workflows/list");
1007+
this.onNavigate("/workflows/list");
10041008
}
10051009
10061010
if (activityId === "workflow-download") {
@@ -1109,6 +1113,7 @@ export default {
11091113
} else if (this.hasChanges && !forceSave && !ignoreChanges) {
11101114
// if there are changes, prompt user to save or discard or cancel
11111115
this.navUrl = url;
1116+
this.saveChangesAppendVersion = appendVersion;
11121117
this.showSaveChangesModal = true;
11131118
} else if (forceSave) {
11141119
// when forceSave is true, save the workflow before navigating

client/src/components/Workflow/Editor/SaveChangesModal.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,20 @@ interface Props {
1313
showModal: boolean;
1414
/** The URL to navigate to before saving/ignoring changes */
1515
navUrl: string;
16+
/** Whether to append the version to the URL */
17+
appendVersion: boolean;
1618
}
1719
1820
const props = withDefaults(defineProps<Props>(), {
1921
showModal: false,
22+
appendVersion: false,
2023
});
2124
2225
const busy = ref(false);
2326
2427
const emit = defineEmits<{
2528
/** Proceed with or without saving the changes */
2629
(e: "on-proceed", url: string, forceSave: boolean, ignoreChanges: boolean, appendVersion: boolean): void;
27-
/** Update the nav URL prop */
28-
(e: "update:nav-url", url: string): void;
2930
/** Update the show modal boolean prop */
3031
(e: "update:show-modal", showModal: boolean): void;
3132
}>();
@@ -43,18 +44,17 @@ const buttonTitles = {
4344
4445
function closeModal() {
4546
emit("update:show-modal", false);
46-
emit("update:nav-url", "");
4747
}
4848
4949
function dontSave() {
5050
busy.value = true;
51-
emit("on-proceed", props.navUrl, false, true, true);
51+
emit("on-proceed", props.navUrl, false, true, props.appendVersion);
5252
}
5353
5454
function saveChanges() {
5555
busy.value = true;
5656
closeModal();
57-
emit("on-proceed", props.navUrl, true, false, true);
57+
emit("on-proceed", props.navUrl, true, false, props.appendVersion);
5858
}
5959
</script>
6060

client/src/components/Workflow/Editor/modules/activities.test.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,4 @@ describe("useSpecialWorkflowActivities", () => {
111111
);
112112
});
113113
});
114-
115-
describe("exitWorkflowActivity tooltip", () => {
116-
it("shows save and exit message when connections are valid", () => {
117-
const { exitWorkflowActivity } = setUpBestPractices(false);
118-
expect(exitWorkflowActivity.value.tooltip).toBe("Save this workflow, then exit the workflow editor");
119-
});
120-
121-
it("shows invalid connections warning when hasInvalidConnections is true", () => {
122-
const { exitWorkflowActivity } = setUpBestPractices(true);
123-
expect(exitWorkflowActivity.value.tooltip).toBe(
124-
"Workflow has invalid connections, review and remove invalid connections",
125-
);
126-
});
127-
});
128114
});

0 commit comments

Comments
 (0)