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

Simplified Workflow Centric UI (Attempt 3) #18445

Draft
wants to merge 2 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 13 additions & 3 deletions client/src/components/ActivityBar/ActivityBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,27 @@
userStore.toggleSideBar(toggle);
}

const syncActivities = () => {
activityStore.sync();
if (config.value && ["workflow_centric", "workflow_runner"].indexOf(config.value.client_mode) >= 0) {
userStore.untoggleToolbarIfNeeded();
}
};

watch(
() => hashedUserId.value,
() => {
activityStore.sync();
}
syncActivities,
);

watch(
isConfigLoaded,
syncActivities,
);
</script>

<template>
<div class="d-flex">
<div

Check warning on line 155 in client/src/components/ActivityBar/ActivityBar.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Visible, non-interactive elements should not have an interactive handler
class="activity-bar d-flex flex-column no-highlight"
data-description="activity bar"
@dragover.prevent="onDragOver"
Expand Down
7 changes: 5 additions & 2 deletions client/src/components/Workflow/List/WorkflowCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ interface Props {
workflow: any;
gridView?: boolean;
publishedView?: boolean;
allowWorkflowManagement?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
gridView: false,
publishedView: false,
allowWorkflowManagement: true,
});

const emit = defineEmits<{
Expand Down Expand Up @@ -134,6 +136,7 @@ async function onTagClick(tag: string) {
<WorkflowActions
:workflow="workflow"
:published="publishedView"
:allow-workflow-management="allowWorkflowManagement"
@refreshList="emit('refreshList', true)"
@toggleShowPreview="toggleShowPreview" />
</div>
Expand Down Expand Up @@ -185,7 +188,7 @@ async function onTagClick(tag: string) {

<div class="workflow-edit-run-buttons">
<BButton
v-if="!isAnonymous && !shared"
v-if="!isAnonymous && !shared && allowWorkflowManagement"
v-b-tooltip.hover.noninteractive
:disabled="workflow.deleted"
size="sm"
Expand All @@ -198,7 +201,7 @@ async function onTagClick(tag: string) {
</BButton>

<AsyncButton
v-else
v-else-if="allowWorkflowManagement"
v-b-tooltip.hover.noninteractive
size="sm"
:disabled="isAnonymous"
Expand Down
22 changes: 19 additions & 3 deletions client/src/components/Workflow/List/WorkflowList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@

interface Props {
activeList?: "my" | "shared_with_me" | "published";
clientMode?: "full" | "workflow_centric" | "workflow_runner";
initialFilterText?: string;
}

const props = withDefaults(defineProps<Props>(), {
activeList: "my",
clientMode: "full",
initialFilterText: "",
});

const router = useRouter();
Expand Down Expand Up @@ -85,6 +89,7 @@
const invalidFilters = computed(() => workflowFilters.value.getValidFilters(rawFilters.value, true).invalidFilters);
const isSurroundedByQuotes = computed(() => /^["'].*["']$/.test(filterText.value));
const hasInvalidFilters = computed(() => !isSurroundedByQuotes.value && Object.keys(invalidFilters.value).length > 0);
const allowWorkflowManagement = computed(() => props.clientMode == "full");

function updateFilterValue(filterKey: string, newValue: any) {
const currentFilterText = filterText.value;
Expand Down Expand Up @@ -194,6 +199,16 @@
await load(true);
});

watch(
props,
() => {
if(props.initialFilterText && filterText.value == "") {
filterText.value = props.initialFilterText;
}
},
{ immediate: true },
);

onMounted(() => {
if (router.currentRoute.query.owner) {
updateFilterValue("user", `'${router.currentRoute.query.owner}'`);
Expand All @@ -208,10 +223,10 @@
<div class="d-flex flex-gapx-1">
<Heading h1 separator inline size="xl" class="flex-grow-1 mb-2">Workflows</Heading>

<WorkflowListActions />
<WorkflowListActions v-if="allowWorkflowManagement" />
</div>

<BNav pills justified class="mb-2">
<BNav pills justified class="mb-2" v-if="allowWorkflowManagement">

Check failure on line 229 in client/src/components/Workflow/List/WorkflowList.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Attribute "v-if" should go before "class"
<BNavItem id="my" :active="activeList === 'my'" :disabled="userStore.isAnonymous" to="/workflows/list">
My workflows
<LoginRequired v-if="userStore.isAnonymous" target="my" title="Manage your workflows" />
Expand Down Expand Up @@ -247,7 +262,7 @@
</template>
</FilterMenu>

<ListHeader ref="listHeader" show-view-toggle>
<ListHeader ref="listHeader" :show-view-toggle="allowWorkflowManagement">
<template v-slot:extra-filter>
<div v-if="activeList === 'my'">
Filter:
Expand Down Expand Up @@ -331,6 +346,7 @@
:published-view="published"
:grid-view="view === 'grid'"
:class="view === 'grid' ? 'grid-view' : 'list-view'"
:allow-workflow-management="allowWorkflowManagement"
@refreshList="load"
@tagClick="(tag) => updateFilterValue('tag', `'${tag}'`)"
@update-filter="updateFilterValue" />
Expand Down
7 changes: 7 additions & 0 deletions client/src/components/Workflow/List/WorkflowListActions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@

const { isAnonymous } = storeToRefs(userStore);

interface Props {
advancedOptions: boolean;
}

const props = defineProps<Props>();

Check failure on line 24 in client/src/components/Workflow/List/WorkflowListActions.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

'props' is assigned a value but never used. Allowed unused vars must match /_.+/u

const createButtonTitle = computed(() => {
if (isAnonymous.value) {
return "Log in to create workflow";
Expand Down Expand Up @@ -47,6 +53,7 @@
<BButton
id="workflow-create"
v-b-tooltip.hover.noninteractive
v-if="advancedOptions"

Check failure on line 56 in client/src/components/Workflow/List/WorkflowListActions.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Attribute "v-if" should go before "v-b-tooltip.hover.noninteractive"
size="sm"
:title="createButtonTitle"
variant="outline-primary"
Expand Down
11 changes: 9 additions & 2 deletions client/src/entry/analysis/modules/Analysis.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
<script setup>
import { onMounted, onUnmounted, ref } from "vue";
import { computed, onMounted, onUnmounted, ref } from "vue";

Check failure on line 2 in client/src/entry/analysis/modules/Analysis.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Run autofix to sort these imports!
import { useRouter } from "vue-router/composables";

import { usePanels } from "@/composables/usePanels";
import { useConfig } from "@/composables/config";

import CenterFrame from "./CenterFrame.vue";
import WorkflowLanding from "./WorkflowLanding.vue";

Check failure on line 9 in client/src/entry/analysis/modules/Analysis.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

'WorkflowLanding' is defined but never used. Allowed unused vars must match /_.+/u
import ActivityBar from "@/components/ActivityBar/ActivityBar.vue";
import HistoryIndex from "@/components/History/Index.vue";
import FlexPanel from "@/components/Panels/FlexPanel.vue";
Expand All @@ -13,6 +15,11 @@
const router = useRouter();
const showCenter = ref(false);
const { showPanels } = usePanels();
const { config, isConfigLoaded } = useConfig();

Check failure on line 18 in client/src/entry/analysis/modules/Analysis.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

'isConfigLoaded' is assigned a value but never used. Allowed unused vars must match /_.+/u

const showHistoryPanel = computed(() => {
return showPanels.value && config.value && config.value.client_mode == "full";
});

// methods
function hideCenter() {
Expand Down Expand Up @@ -44,7 +51,7 @@
<router-view :key="$route.fullPath" class="h-100" />
</div>
</div>
<FlexPanel v-if="showPanels" side="right">
<FlexPanel v-if="showHistoryPanel" side="right">
<HistoryIndex />
</FlexPanel>
<DragAndDropModal />
Expand Down
8 changes: 8 additions & 0 deletions client/src/entry/analysis/modules/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@
<ToolForm v-if="isTool && !isUpload" v-bind="toolParams" />
<WorkflowRun v-else-if="isWorkflow" v-bind="workflowParams" />
<div v-else-if="isController" :src="controllerParams" />
<div v-else-if="isWorkflowCentric">
<WorkflowLanding :client-mode="config.client_mode" :initial-filter-text="config.simplified_workflow_landing_initial_filter_text" />
</div>
<CenterFrame v-else src="/welcome" />
</div>
</template>

<script>
import ToolForm from "components/Tool/ToolForm";

Check failure on line 14 in client/src/entry/analysis/modules/Home.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Run autofix to sort these imports!
import WorkflowRun from "components/Workflow/Run/WorkflowRun";
import WorkflowLanding from "./WorkflowLanding";
import decodeUriComponent from "decode-uri-component";
import CenterFrame from "entry/analysis/modules/CenterFrame";

Expand All @@ -18,6 +22,7 @@
CenterFrame,
ToolForm,
WorkflowRun,
WorkflowLanding,
},
props: {
config: {
Expand All @@ -30,6 +35,9 @@
},
},
computed: {
isWorkflowCentric() {
return ["workflow_centric", "workflow_runner"].indexOf(this.config.client_mode) >= 0;
},
isController() {
return this.query.m_c && this.query.m_a;
},
Expand Down
16 changes: 16 additions & 0 deletions client/src/entry/analysis/modules/WorkflowLanding.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script setup lang="ts">
interface Props {
initialFilterText: string;
clientMode: string;
}

defineProps<Props>()

import WorkflowList from "@/components/Workflow/WorkflowList.vue";

Check failure on line 9 in client/src/entry/analysis/modules/WorkflowLanding.vue

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Import in body of module; reorder to top
</script>

<template>
<div>
<WorkflowList active-list="published" :client-mode="clientMode" :initial-filter-text="initialFilterText" />
</div>
</template>
67 changes: 53 additions & 14 deletions client/src/stores/activitySetup.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,68 @@
/**
* List of built-in activities
*/
import { type Activity } from "@/stores/activityStore";
import { type ClientMode, type Activity, type RawActivity } from "@/stores/activityStore";

Check failure on line 4 in client/src/stores/activitySetup.ts

View workflow job for this annotation

GitHub Actions / client-unit-test (18)

Run autofix to sort these imports!
import { type EventData } from "@/stores/eventStore";

export const Activities = [
function isWorkflowCentric(clientMode: ClientMode) : boolean {
return ["workflow_centric", "workflow_runner"].indexOf(clientMode) >= 0;
}

function unlessWorkflowCentric(clientMode: ClientMode): boolean {
if (isWorkflowCentric(clientMode)) {
return false;
} else {
return true;
}
}

function ifWorkflowCentric(clientMode: ClientMode): boolean {
if (isWorkflowCentric(clientMode)) {
return true;
} else {
return false;
}
}

export const ActivitiesRaw: RawActivity[] = [
{
anonymous: false,
description: "Displays currently running interactive tools (ITs), if these are enabled by the administrator.",
icon: "fa-laptop",
id: "interactivetools",
mutable: false,
optional: false,
optional: ifWorkflowCentric,
panel: false,
title: "Interactive Tools",
tooltip: "Show active interactive tools",
to: "/interactivetool_entry_points/list",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: true,
description: "Opens a data dialog, allowing uploads from URL, pasted content or disk.",
icon: "upload",
id: "upload",
mutable: false,
optional: false,
optional: ifWorkflowCentric,
panel: false,
title: "Upload",
to: null,
tooltip: "Download from URL or upload files from disk",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: true,
description: "Displays the tool panel to search and access all available tools.",
icon: "wrench",
id: "tools",
mutable: false,
optional: false,
optional: ifWorkflowCentric,
panel: true,
title: "Tools",
to: null,
to: "/tools",
tooltip: "Search and run tools",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: true,
Expand Down Expand Up @@ -81,7 +101,7 @@
title: "Visualization",
to: null,
tooltip: "Visualize datasets",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: true,
Expand All @@ -94,7 +114,7 @@
title: "Histories",
tooltip: "Show all histories",
to: "/histories/list",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: false,
Expand All @@ -107,7 +127,7 @@
title: "History Multiview",
tooltip: "Select histories to show in History Multiview",
to: "/histories/view_multiple",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: false,
Expand All @@ -120,7 +140,7 @@
title: "Datasets",
tooltip: "Show all datasets",
to: "/datasets/list",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: true,
Expand All @@ -133,7 +153,7 @@
title: "Pages",
tooltip: "Show all pages",
to: "/pages/list",
visible: true,
visible: unlessWorkflowCentric,
},
{
anonymous: false,
Expand All @@ -150,6 +170,25 @@
},
];

function resolveActivity(activity: RawActivity, clientMode: ClientMode) : Activity {
let optional = activity.optional;
let visible = activity.visible;
if (typeof optional === 'function') {
optional = optional(clientMode);
}
if (typeof visible === 'function') {
visible = visible(clientMode);
}
return { ...activity, optional, visible};
}

export function getActivities(clientMode: ClientMode) {
const resolve = (activity: RawActivity) => {
return resolveActivity(activity, clientMode);
}
return ActivitiesRaw.map(resolve);
}

export function convertDropData(data: EventData): Activity | null {
if (data.history_content_type === "dataset") {
return {
Expand Down
Loading
Loading