Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workflow Editor Activity Bar #18729

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
59f7846
generalize activity bar
ElectronicBlueberry Aug 20, 2024
dfb9970
add activity bar to workflow editor
ElectronicBlueberry Aug 20, 2024
9777bde
add activities to activity bar
ElectronicBlueberry Aug 21, 2024
56946f9
add save and exit activity
ElectronicBlueberry Aug 22, 2024
b73905b
route to workflow list on exit
ElectronicBlueberry Aug 22, 2024
3283d6a
move best practices to activity bar
ElectronicBlueberry Aug 22, 2024
a14191c
use ActivityPanel component for Lint
ElectronicBlueberry Aug 23, 2024
a3226ae
move UndoRedoStack to activity bar
ElectronicBlueberry Aug 23, 2024
306ef42
add placeholder activities
ElectronicBlueberry Aug 23, 2024
30df771
fix delayed input
ElectronicBlueberry Aug 28, 2024
d35a330
make favorites button reusable
ElectronicBlueberry Aug 28, 2024
e8ed57d
refactor WorkflowCard
ElectronicBlueberry Aug 29, 2024
2b58286
improve performance of workflow card
ElectronicBlueberry Aug 29, 2024
1a55ad8
add workflows panel
ElectronicBlueberry Sep 5, 2024
c460dd7
fix z-indexing for dropdown
ElectronicBlueberry Sep 6, 2024
859ff83
connect insert and insert steps events
ElectronicBlueberry Sep 6, 2024
c642f03
move breakpoints to partial
ElectronicBlueberry Sep 6, 2024
0f4eb0f
only occupy vertical space if invocations count is present
ElectronicBlueberry Sep 9, 2024
bd36e02
rename Attributes to WorkflowAttributes
ElectronicBlueberry Sep 9, 2024
2f9f9c2
make attributes an activity
ElectronicBlueberry Sep 9, 2024
6c1b64c
move MarkdownEditor to activity bar
ElectronicBlueberry Sep 9, 2024
8391148
move all options to activity bar
ElectronicBlueberry Sep 10, 2024
7592958
add save button
ElectronicBlueberry Sep 23, 2024
4dd15a8
remove unused attribute and unreachable code
ElectronicBlueberry Sep 23, 2024
5806bcf
enable run and save
ElectronicBlueberry Sep 23, 2024
859c80d
fix activity text centering on chrome
ElectronicBlueberry Sep 23, 2024
8df1987
fix text short property collision
ElectronicBlueberry Sep 24, 2024
049f9db
decouple node inspector from right hand panel
ElectronicBlueberry Sep 27, 2024
71e8c7f
modularize drag handle
ElectronicBlueberry Oct 8, 2024
9d77fc8
correct appearance of drag handle
ElectronicBlueberry Oct 8, 2024
df3cbbf
show collapse button
ElectronicBlueberry Oct 8, 2024
92096c7
add tool form to node inspector
ElectronicBlueberry Oct 14, 2024
bc1248b
add inspector heading
ElectronicBlueberry Oct 16, 2024
b519f99
allow for saving default sizes for tools / steps
ElectronicBlueberry Oct 17, 2024
3dbe6f8
make double click maximize node inspector
ElectronicBlueberry Oct 18, 2024
3f83f53
fix scroll height
ElectronicBlueberry Oct 18, 2024
4f8727a
add form default to inspector
ElectronicBlueberry Oct 18, 2024
8efcc27
make form default full width
ElectronicBlueberry Oct 21, 2024
e2c1558
remove ability to sub-workflow own workflow
ElectronicBlueberry Oct 21, 2024
a3c702c
connect refresh list signal
ElectronicBlueberry Oct 21, 2024
bd723ef
fix workflow creation
ElectronicBlueberry Oct 21, 2024
dcc65a9
make current workflow immutable from card
ElectronicBlueberry Oct 22, 2024
1ce4376
replace save with save and exit
ElectronicBlueberry Oct 22, 2024
410be18
add save button to title bar
ElectronicBlueberry Oct 22, 2024
205e6d3
move initial position to not interfere with toolbar
ElectronicBlueberry Oct 24, 2024
60a0df4
make step annotation resizable
ElectronicBlueberry Oct 24, 2024
f02441e
fix activity item test
ElectronicBlueberry Oct 28, 2024
255a2d9
fix workflow attributes test
ElectronicBlueberry Oct 28, 2024
033f86f
fxi activity store test
ElectronicBlueberry Oct 28, 2024
81a4b95
fix empty divs rendered
ElectronicBlueberry Oct 28, 2024
cd5ef66
fix activity settings test
ElectronicBlueberry Oct 28, 2024
7b96c14
fix lint test
ElectronicBlueberry Oct 28, 2024
b761aa4
fix filter conversion test
ElectronicBlueberry Oct 28, 2024
02be147
fix workflow filters import
ElectronicBlueberry Oct 28, 2024
f4c31c1
remove broken test case
ElectronicBlueberry Oct 28, 2024
5dbe5e8
remove workflows section in tool box
ElectronicBlueberry Oct 29, 2024
1abe124
add back activity item id
ElectronicBlueberry Oct 30, 2024
b2e0051
make workflow editor default to attributes
ElectronicBlueberry Oct 31, 2024
c06c0a3
add class for editor save button
ElectronicBlueberry Nov 4, 2024
33f4c38
move selector to id
ElectronicBlueberry Nov 4, 2024
daad64d
fix auto layout
ElectronicBlueberry Nov 4, 2024
98baca5
add button titles to node inspector
ElectronicBlueberry Nov 4, 2024
70391a9
fix maximize center pane function
ElectronicBlueberry Nov 4, 2024
a5aeaa7
make auto layout respect grid and snapping
ElectronicBlueberry Nov 5, 2024
4346f2d
make auto layout an action
ElectronicBlueberry Nov 7, 2024
75e9b2d
make activity panel scrollable
ElectronicBlueberry Nov 7, 2024
46aff8e
close inspector instead of showing attributes
ElectronicBlueberry Nov 11, 2024
3ff1116
open nodes from lint panel
ElectronicBlueberry Nov 11, 2024
7f5bebb
auto layout frame comments
ElectronicBlueberry Nov 11, 2024
ab1e8d9
undo comment auto layout
ElectronicBlueberry Nov 11, 2024
45966ea
consider comments in layout
ElectronicBlueberry Nov 11, 2024
628379e
move freehand comments with their closest comment preserving large dr…
ElectronicBlueberry Nov 11, 2024
4a9ecc5
fix edge crossing
ElectronicBlueberry Nov 11, 2024
1e3a68a
associate comments to their closest node
ElectronicBlueberry Nov 12, 2024
af0d8fa
make auto layout a toolbar tool
ElectronicBlueberry Nov 12, 2024
797bbb4
pass step position for more accurate comment positioning
ElectronicBlueberry Nov 12, 2024
9fbfdc8
disable run button on new workflow
ElectronicBlueberry Nov 13, 2024
23ac659
Update client/src/components/ActivityBar/ActivityBar.vue
itisAliRH Nov 15, 2024
3d1761a
Updates bookmark toggle function parameters
itisAliRH Nov 15, 2024
efddffb
Removes non-existent config property usage
itisAliRH Nov 15, 2024
30deee4
Adds workflowId to useStores return object
itisAliRH Nov 15, 2024
882237a
Adds computed property for tools favorites toggle
itisAliRH Nov 15, 2024
a64c221
Fixes FontAwesome icon usage in ToolPanel
itisAliRH Nov 15, 2024
3974dc5
Fix the test to check the shared indicator tooltip text
itisAliRH Nov 15, 2024
ff090af
Adds Pinia testing support to ActivityItem tests and add required pro…
itisAliRH Nov 15, 2024
12bb376
Updates workflow type to StoredWorkflowDetailed
itisAliRH Nov 15, 2024
479da19
Fixes import path and adds activity bar ID to NotificationItem
itisAliRH Nov 15, 2024
dc5fb05
Adds activity-bar-id prop to ActivityItem components
itisAliRH Nov 15, 2024
6d8c7e7
Adds favorites filter functionality to WorkflowPanel
itisAliRH Nov 15, 2024
31b6e71
Refactors icon imports and usage
itisAliRH Nov 15, 2024
e84ab9c
Updates icon handling in tests
itisAliRH Nov 15, 2024
0d791b9
Updates filter keyword for workflow bookmarks
itisAliRH Nov 15, 2024
3e1ff48
Simplifies activity item IDs
itisAliRH Nov 17, 2024
08572c2
Fix activity item upload progress background
itisAliRH Nov 17, 2024
2bdcb24
Adds ID to toolbox panel
itisAliRH Nov 17, 2024
2fad3b5
Adds auto-layout button ID in workflow toolbar
itisAliRH Nov 17, 2024
68d88ae
Adds hidePanel prop to ActivityBar and integrates MarkdownToolBox in …
itisAliRH Nov 18, 2024
cb322e5
remove wait for absent element
ElectronicBlueberry Nov 18, 2024
9979a13
fix add_input
ElectronicBlueberry Nov 18, 2024
0af713c
fix inserting steps
ElectronicBlueberry Nov 18, 2024
0cab266
fix tool menu container occurrences
ElectronicBlueberry Nov 18, 2024
4f38eca
Migrates WorkflowAttributes test to TypeScript and updates dependencies
itisAliRH Nov 18, 2024
9524aab
fix workflows activity id
ElectronicBlueberry Nov 19, 2024
8f1508b
Migrates ToolPanel test to TypeScript
itisAliRH Nov 19, 2024
afee2e7
Updates toolbox panel selectors and workflow editor logic
itisAliRH Nov 19, 2024
257d2cb
Adds 'Save As' functionality to workflow editor
itisAliRH Nov 19, 2024
f2a173f
Adds 'Save As' option to workflow editor toolbar
itisAliRH Nov 19, 2024
d25f9eb
fix basics test
ElectronicBlueberry Nov 20, 2024
1f61116
revert shortening of ids
ElectronicBlueberry Nov 20, 2024
d4f1ceb
fix test save as
ElectronicBlueberry Nov 20, 2024
866b2df
add more wait time for search
ElectronicBlueberry Nov 20, 2024
80ac0c1
re-add confirm dialog
ElectronicBlueberry Nov 20, 2024
5855a2f
remove double id prepending
ElectronicBlueberry Nov 20, 2024
802c6da
redo add subworkflow
ElectronicBlueberry Nov 20, 2024
a472750
fix save as selector
ElectronicBlueberry Nov 20, 2024
530be00
move selection options to the left, so they do not interfere with the…
ElectronicBlueberry Nov 20, 2024
7596e6a
remove collapse buttons from basics test
ElectronicBlueberry Nov 20, 2024
4f7dd00
wait for save to complete
ElectronicBlueberry Nov 21, 2024
6c3b2ce
remove test for removed feature
ElectronicBlueberry Nov 21, 2024
0873c1b
remove invalid check in insert steps
ElectronicBlueberry Nov 21, 2024
61fef86
remove test for removed component
ElectronicBlueberry Nov 21, 2024
8b0d78b
make search selector more specific
ElectronicBlueberry Nov 25, 2024
c11cba1
fix selection test
ElectronicBlueberry Nov 25, 2024
477546e
clear search before searching for other tool
ElectronicBlueberry Nov 25, 2024
8979126
use confirm dialog composable
ElectronicBlueberry Nov 25, 2024
a7ea379
exclude node buttons from node selection targets
ElectronicBlueberry Nov 25, 2024
127893f
use latest id on insert
ElectronicBlueberry Nov 25, 2024
8d26e19
save latest id to dict
ElectronicBlueberry Nov 25, 2024
8a2edfc
fix test_non_data_connections test
ElectronicBlueberry Nov 25, 2024
d894082
fix test_editor_duplicate_node test
ElectronicBlueberry Nov 25, 2024
3fc286d
fix event name for markdown update in PageEditorMarkdown component
davelopez Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/src/components/ActivityBar/ActivityBar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe("ActivityBar", () => {

beforeEach(async () => {
const pinia = createTestingPinia({ stubActions: false });
activityStore = useActivityStore();
activityStore = useActivityStore("default");
eventStore = useEventStore();
wrapper = shallowMount(mountTarget, {
localVue,
Expand Down
182 changes: 138 additions & 44 deletions client/src/components/ActivityBar/ActivityBar.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<script setup lang="ts">
import { type IconDefinition } from "@fortawesome/fontawesome-svg-core";
import { faBell, faEllipsisH, faUserCog } from "@fortawesome/free-solid-svg-icons";
import { watchImmediate } from "@vueuse/core";
import { storeToRefs } from "pinia";
import { computed, type Ref, ref, watch } from "vue";
import { computed, type Ref, ref } from "vue";
import { useRoute } from "vue-router/composables";
import draggable from "vuedraggable";

import { useConfig } from "@/composables/config";
import { useHashedUserId } from "@/composables/hashedUserId";
import { convertDropData } from "@/stores/activitySetup";
import { type Activity, useActivityStore } from "@/stores/activityStore";
import { useEventStore } from "@/stores/eventStore";
Expand All @@ -24,6 +26,35 @@ import NotificationsPanel from "@/components/Panels/NotificationsPanel.vue";
import SettingsPanel from "@/components/Panels/SettingsPanel.vue";
import ToolPanel from "@/components/Panels/ToolPanel.vue";

const props = withDefaults(
defineProps<{
defaultActivities?: Activity[];
activityBarId?: string;
specialActivities?: Activity[];
showAdmin?: boolean;
optionsTitle?: string;
optionsTooltip?: string;
optionsHeading?: string;
optionsIcon?: IconDefinition;
optionsSearchPlaceholder?: string;
initialActivity?: string;
hidePanel?: boolean;
}>(),
{
defaultActivities: undefined,
activityBarId: "default",
specialActivities: () => [],
showAdmin: true,
optionsTitle: "More",
optionsHeading: "Additional Activities",
optionsIcon: () => faEllipsisH,
optionsSearchPlaceholder: "Search Activities",
optionsTooltip: "View additional activities",
initialActivity: undefined,
hidePanel: false,
}
);

// require user to long click before dragging
const DRAG_DELAY = 50;

Expand All @@ -32,13 +63,30 @@ const { config, isConfigLoaded } = useConfig();
const route = useRoute();
const userStore = useUserStore();

const { hashedUserId } = useHashedUserId();

const eventStore = useEventStore();
const activityStore = useActivityStore();
const activityStore = useActivityStore(props.activityBarId);

if (props.initialActivity) {
activityStore.toggledSideBar = props.initialActivity;
}

watchImmediate(
() => props.defaultActivities,
(defaults) => {
if (defaults) {
activityStore.overrideDefaultActivities(defaults);
} else {
activityStore.resetDefaultActivities();
}
}
);

const { isAdmin, isAnonymous } = storeToRefs(userStore);

const emit = defineEmits(["dragstart"]);
const emit = defineEmits<{
(e: "dragstart", dragItem: Activity | null): void;
(e: "activityClicked", activityId: string): void;
}>();

// activities from store
const { activities } = storeToRefs(activityStore);
Expand All @@ -50,30 +98,27 @@ const dragItem: Ref<Activity | null> = ref(null);
// drag state
const isDragging = ref(false);

// sync built-in activities with cached activities
activityStore.sync();

/**
* Checks if the route of an activity is currently being visited and panels are collapsed
*/
function isActiveRoute(activityTo: string) {
function isActiveRoute(activityTo?: string | null) {
return route.path === activityTo && isActiveSideBar("");
}

/**
* Checks if a panel has been expanded
*/
function isActiveSideBar(menuKey: string) {
return userStore.toggledSideBar === menuKey;
return activityStore.toggledSideBar === menuKey;
}

const isSideBarOpen = computed(() => userStore.toggledSideBar !== "");
const isSideBarOpen = computed(() => activityStore.toggledSideBar !== "");

/**
* Checks if an activity that has a panel should have the `is-active` prop
*/
function panelActivityIsActive(activity: Activity) {
return isActiveSideBar(activity.id) || (activity.to !== null && isActiveRoute(activity.to));
return isActiveSideBar(activity.id) || isActiveRoute(activity.to);
}

/**
Expand Down Expand Up @@ -123,25 +168,37 @@ function onDragOver(evt: MouseEvent) {
/**
* Tracks the state of activities which expand or collapse the sidepanel
*/
function onToggleSidebar(toggle: string = "", to: string | null = null) {
function toggleSidebar(toggle: string = "", to: string | null = null) {
// if an activity's dedicated panel/sideBar is already active
// but the route is different, don't collapse
if (toggle && to && !(route.path === to) && isActiveSideBar(toggle)) {
return;
}
userStore.toggleSideBar(toggle);
activityStore.toggleSideBar(toggle);
}

watch(
() => hashedUserId.value,
() => {
activityStore.sync();
function onActivityClicked(activity: Activity) {
if (activity.click) {
emit("activityClicked", activity.id);
} else {
toggleSidebar();
}
);
}

function setActiveSideBar(key: string) {
activityStore.toggledSideBar = key;
}

defineExpose({
isActiveSideBar,
setActiveSideBar,
});
</script>

<template>
<div class="d-flex">
<!-- while this warning is correct, it is hiding too many other errors -->
<!-- eslint-disable-next-line vuejs-accessibility/no-static-element-interactions -->
<div
class="activity-bar d-flex flex-column no-highlight"
data-description="activity bar"
Expand All @@ -163,79 +220,116 @@ watch(
<div v-if="activity.visible && (activity.anonymous || !isAnonymous)">
<UploadItem
v-if="activity.id === 'upload'"
:id="`activity-${activity.id}`"
:id="`${activity.id}`"
:key="activity.id"
:icon="activity.icon"
:title="activity.title"
:tooltip="activity.tooltip" />
<InteractiveItem
v-else-if="activity.to && activity.id === 'interactivetools'"
:id="`activity-${activity.id}`"
:id="`${activity.id}`"
:key="activity.id"
:icon="activity.icon"
:is-active="isActiveRoute(activity.to)"
:title="activity.title"
:tooltip="activity.tooltip"
:to="activity.to"
@click="onToggleSidebar()" />
@click="toggleSidebar()" />
<ActivityItem
v-else-if="activity.id === 'admin' || activity.panel"
:id="`activity-${activity.id}`"
:id="`${activity.id}`"
:key="activity.id"
:activity-bar-id="props.activityBarId"
:icon="activity.icon"
:is-active="panelActivityIsActive(activity)"
:title="activity.title"
:tooltip="activity.tooltip"
:to="activity.to || ''"
@click="onToggleSidebar(activity.id, activity.to)" />
@click="toggleSidebar(activity.id, activity.to)" />
<ActivityItem
v-else-if="activity.to"
:id="`activity-${activity.id}`"
v-else
:id="`${activity.id}`"
:key="activity.id"
:activity-bar-id="props.activityBarId"
:icon="activity.icon"
:is-active="isActiveRoute(activity.to)"
:title="activity.title"
:tooltip="activity.tooltip"
:to="activity.to"
@click="onToggleSidebar()" />
:to="activity.to ?? undefined"
:variant="activity.variant"
@click="onActivityClicked(activity)" />
</div>
</div>
</draggable>
</b-nav>
<b-nav v-if="!isAnonymous" vertical class="activity-footer flex-nowrap p-1">
<NotificationItem
v-if="isConfigLoaded && config.enable_notification_system"
id="activity-notifications"
icon="bell"
id="notifications"
:icon="faBell"
:is-active="isActiveSideBar('notifications') || isActiveRoute('/user/notifications')"
title="Notifications"
@click="onToggleSidebar('notifications')" />
@click="toggleSidebar('notifications')" />
<ActivityItem
id="activity-settings"
icon="ellipsis-h"
id="settings"
:activity-bar-id="props.activityBarId"
:icon="props.optionsIcon"
:is-active="isActiveSideBar('settings')"
title="More"
tooltip="View additional activities"
@click="onToggleSidebar('settings')" />
:title="props.optionsTitle"
:tooltip="props.optionsTooltip"
@click="toggleSidebar('settings')" />
<ActivityItem
v-if="isAdmin"
id="activity-admin"
icon="user-cog"
v-if="isAdmin && showAdmin"
id="admin"
:activity-bar-id="props.activityBarId"
:icon="faUserCog"
:is-active="isActiveSideBar('admin')"
title="Admin"
tooltip="Administer this Galaxy"
variant="danger"
@click="onToggleSidebar('admin')" />
@click="toggleSidebar('admin')" />
<template v-for="activity in props.specialActivities">
<ActivityItem
v-if="activity.panel"
:id="`${activity.id}`"
:key="activity.id"
:activity-bar-id="props.activityBarId"
:icon="activity.icon"
:is-active="panelActivityIsActive(activity)"
:title="activity.title"
:tooltip="activity.tooltip"
:to="activity.to || ''"
:variant="activity.variant"
@click="toggleSidebar(activity.id, activity.to)" />
<ActivityItem
v-else
:id="`${activity.id}`"
:key="activity.id"
:activity-bar-id="props.activityBarId"
:icon="activity.icon"
:is-active="isActiveRoute(activity.to)"
:title="activity.title"
:tooltip="activity.tooltip"
:to="activity.to ?? undefined"
:variant="activity.variant"
@click="onActivityClicked(activity)" />
</template>
</b-nav>
</div>
<FlexPanel v-if="isSideBarOpen" side="left" :collapsible="false">
<FlexPanel v-if="isSideBarOpen && !hidePanel" side="left" :collapsible="false">
<ToolPanel v-if="isActiveSideBar('tools')" />
<InvocationsPanel v-else-if="isActiveSideBar('invocation')" />
<InvocationsPanel v-else-if="isActiveSideBar('invocation')" :activity-bar-id="props.activityBarId" />
<VisualizationPanel v-else-if="isActiveSideBar('visualizations')" />
<MultiviewPanel v-else-if="isActiveSideBar('multiview')" />
<NotificationsPanel v-else-if="isActiveSideBar('notifications')" />
<SettingsPanel v-else-if="isActiveSideBar('settings')" />
<SettingsPanel
v-else-if="isActiveSideBar('settings')"
:activity-bar-id="props.activityBarId"
:heading="props.optionsHeading"
:search-placeholder="props.optionsSearchPlaceholder"
@activityClicked="(id) => emit('activityClicked', id)" />
<AdminPanel v-else-if="isActiveSideBar('admin')" />
<slot name="side-panel" :is-active-side-bar="isActiveSideBar"></slot>
</FlexPanel>
</div>
</template>
Expand Down
8 changes: 5 additions & 3 deletions client/src/components/ActivityBar/ActivityItem.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createTestingPinia } from "@pinia/testing";
import { mount } from "@vue/test-utils";
import { getLocalVue } from "tests/jest/helpers";

Expand All @@ -12,6 +13,7 @@ describe("ActivityItem", () => {
wrapper = mount(mountTarget, {
propsData: {
id: "activity-test-id",
activityBarId: "activity-bar-test-id",
icon: "activity-test-icon",
indicator: 0,
progressPercentage: 0,
Expand All @@ -20,6 +22,7 @@ describe("ActivityItem", () => {
to: null,
tooltip: "activity-test-tooltip",
},
pinia: createTestingPinia(),
localVue,
stubs: {
FontAwesomeIcon: true,
Expand All @@ -28,8 +31,7 @@ describe("ActivityItem", () => {
});

it("rendering", async () => {
const reference = wrapper.find("[id='activity-test-id']");
expect(reference.attributes().id).toBe("activity-test-id");
const reference = wrapper.find(".activity-item");
expect(reference.text()).toBe("activity-test-title");
expect(reference.find("[icon='activity-test-icon']").exists()).toBeTruthy();
expect(reference.find(".progress").exists()).toBeFalsy();
Expand All @@ -45,7 +47,7 @@ describe("ActivityItem", () => {
});

it("rendering indicator", async () => {
const reference = wrapper.find("[id='activity-test-id']");
const reference = wrapper.find(".activity-item");
const indicatorSelector = "[data-description='activity indicator']";
const noindicator = reference.find(indicatorSelector);
expect(noindicator.exists()).toBeFalsy();
Expand Down
Loading
Loading