fix(editor): Properly update workflow info in main header (#9789)

This commit is contained in:
Csaba Tuncsik
2024-06-24 15:08:24 +02:00
committed by GitHub
parent 44ea4c73eb
commit 1ba656ef4a
9 changed files with 789 additions and 710 deletions

View File

@@ -1,3 +1,161 @@
<script setup lang="ts">
import { ref, computed, watch, onBeforeMount, onMounted } from 'vue';
import type { RouteLocation, RouteLocationRaw } from 'vue-router';
import { useRouter, useRoute } from 'vue-router';
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
import TabBar from '@/components/MainHeader/TabBar.vue';
import {
MAIN_HEADER_TABS,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
STICKY_NODE_TYPE,
VIEWS,
} from '@/constants';
import { useI18n } from '@/composables/useI18n';
import { useNDVStore } from '@/stores/ndv.store';
import { useSourceControlStore } from '@/stores/sourceControl.store';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useExecutionsStore } from '@/stores/executions.store';
import { usePushConnection } from '@/composables/usePushConnection';
const router = useRouter();
const route = useRoute();
const locale = useI18n();
const pushConnection = usePushConnection({ router });
const ndvStore = useNDVStore();
const uiStore = useUIStore();
const sourceControlStore = useSourceControlStore();
const workflowsStore = useWorkflowsStore();
const executionsStore = useExecutionsStore();
const activeHeaderTab = ref(MAIN_HEADER_TABS.WORKFLOW);
const workflowToReturnTo = ref('');
const executionToReturnTo = ref('');
const dirtyState = ref(false);
const tabBarItems = computed(() => [
{ value: MAIN_HEADER_TABS.WORKFLOW, label: locale.baseText('generic.editor') },
{ value: MAIN_HEADER_TABS.EXECUTIONS, label: locale.baseText('generic.executions') },
]);
const activeNode = computed(() => ndvStore.activeNode);
const hideMenuBar = computed(() =>
Boolean(activeNode.value && activeNode.value.type !== STICKY_NODE_TYPE),
);
const workflow = computed(() => workflowsStore.workflow);
const workflowId = computed(() =>
String(router.currentRoute.value.params.name || workflowsStore.workflowId),
);
const onWorkflowPage = computed(() => !!(route.meta.nodeView || route.meta.keepWorkflowAlive));
const readOnly = computed(() => sourceControlStore.preferences.branchReadOnly);
watch(route, (to, from) => {
syncTabsWithRoute(to, from);
});
onBeforeMount(() => {
pushConnection.initialize();
});
onMounted(async () => {
dirtyState.value = uiStore.stateIsDirty;
syncTabsWithRoute(route);
});
function syncTabsWithRoute(to: RouteLocation, from?: RouteLocation): void {
if (
to.name === VIEWS.EXECUTION_HOME ||
to.name === VIEWS.WORKFLOW_EXECUTIONS ||
to.name === VIEWS.EXECUTION_PREVIEW
) {
activeHeaderTab.value = MAIN_HEADER_TABS.EXECUTIONS;
} else if (
to.name === VIEWS.WORKFLOW ||
to.name === VIEWS.NEW_WORKFLOW ||
to.name === VIEWS.EXECUTION_DEBUG
) {
activeHeaderTab.value = MAIN_HEADER_TABS.WORKFLOW;
}
if (to.params.name !== 'new' && typeof to.params.name === 'string') {
workflowToReturnTo.value = to.params.name;
}
if (
from?.name === VIEWS.EXECUTION_PREVIEW &&
to.params.name === from.params.name &&
typeof from.params.executionId === 'string'
) {
executionToReturnTo.value = from.params.executionId;
}
}
function onTabSelected(tab: MAIN_HEADER_TABS, event: MouseEvent) {
const openInNewTab = event.ctrlKey || event.metaKey;
switch (tab) {
case MAIN_HEADER_TABS.WORKFLOW:
void navigateToWorkflowView(openInNewTab);
break;
case MAIN_HEADER_TABS.EXECUTIONS:
void navigateToExecutionsView(openInNewTab);
break;
default:
break;
}
}
async function navigateToWorkflowView(openInNewTab: boolean) {
let routeToNavigateTo: RouteLocationRaw;
if (!['', 'new', PLACEHOLDER_EMPTY_WORKFLOW_ID].includes(workflowToReturnTo.value)) {
routeToNavigateTo = {
name: VIEWS.WORKFLOW,
params: { name: workflowToReturnTo.value },
};
} else {
routeToNavigateTo = { name: VIEWS.NEW_WORKFLOW };
}
if (openInNewTab) {
const { href } = router.resolve(routeToNavigateTo);
window.open(href, '_blank');
} else if (route.name !== routeToNavigateTo.name) {
if (route.name === VIEWS.NEW_WORKFLOW) {
uiStore.stateIsDirty = dirtyState.value;
}
activeHeaderTab.value = MAIN_HEADER_TABS.WORKFLOW;
await router.push(routeToNavigateTo);
}
}
async function navigateToExecutionsView(openInNewTab: boolean) {
const routeWorkflowId =
workflowId.value === PLACEHOLDER_EMPTY_WORKFLOW_ID ? 'new' : workflowId.value;
const executionToReturnToValue = executionsStore.activeExecution?.id || executionToReturnTo.value;
const routeToNavigateTo: RouteLocationRaw = executionToReturnToValue
? {
name: VIEWS.EXECUTION_PREVIEW,
params: { name: routeWorkflowId, executionId: executionToReturnToValue },
}
: {
name: VIEWS.EXECUTION_HOME,
params: { name: routeWorkflowId },
};
if (openInNewTab) {
const { href } = router.resolve(routeToNavigateTo);
window.open(href, '_blank');
} else if (route.name !== routeToNavigateTo.name) {
dirtyState.value = uiStore.stateIsDirty;
workflowToReturnTo.value = workflowId.value;
activeHeaderTab.value = MAIN_HEADER_TABS.EXECUTIONS;
await router.push(routeToNavigateTo);
}
}
</script>
<template>
<div>
<div :class="{ 'main-header': true, expanded: !uiStore.sidebarMenuCollapsed }">
@@ -14,194 +172,6 @@
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import type { RouteLocation, RouteLocationRaw } from 'vue-router';
import { useRouter } from 'vue-router';
import { mapStores } from 'pinia';
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
import TabBar from '@/components/MainHeader/TabBar.vue';
import {
MAIN_HEADER_TABS,
PLACEHOLDER_EMPTY_WORKFLOW_ID,
STICKY_NODE_TYPE,
VIEWS,
} from '@/constants';
import type { INodeUi, ITabBarItem, IWorkflowDb } from '@/Interface';
import { useNDVStore } from '@/stores/ndv.store';
import { useSourceControlStore } from '@/stores/sourceControl.store';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { useExecutionsStore } from '@/stores/executions.store';
import { usePushConnection } from '@/composables/usePushConnection';
export default defineComponent({
name: 'MainHeader',
components: {
WorkflowDetails,
TabBar,
},
setup() {
const router = useRouter();
const pushConnection = usePushConnection({ router });
return {
pushConnection,
};
},
data() {
return {
activeHeaderTab: MAIN_HEADER_TABS.WORKFLOW,
workflowToReturnTo: '',
executionToReturnTo: '',
dirtyState: false,
};
},
computed: {
...mapStores(
useNDVStore,
useUIStore,
useSourceControlStore,
useWorkflowsStore,
useExecutionsStore,
),
tabBarItems(): ITabBarItem[] {
return [
{ value: MAIN_HEADER_TABS.WORKFLOW, label: this.$locale.baseText('generic.editor') },
{ value: MAIN_HEADER_TABS.EXECUTIONS, label: this.$locale.baseText('generic.executions') },
];
},
activeNode(): INodeUi | null {
return this.ndvStore.activeNode;
},
hideMenuBar(): boolean {
return Boolean(this.activeNode && this.activeNode.type !== STICKY_NODE_TYPE);
},
workflow(): IWorkflowDb {
return this.workflowsStore.workflow;
},
currentWorkflow(): string {
return String(this.$route.params.name || this.workflowsStore.workflowId);
},
onWorkflowPage(): boolean {
return !!(this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive);
},
readOnly(): boolean {
return this.sourceControlStore.preferences.branchReadOnly;
},
},
watch: {
$route(to, from) {
this.syncTabsWithRoute(to, from);
},
},
beforeMount() {
this.pushConnection.initialize();
},
mounted() {
this.dirtyState = this.uiStore.stateIsDirty;
this.syncTabsWithRoute(this.$route);
},
beforeUnmount() {
this.pushConnection.terminate();
},
methods: {
syncTabsWithRoute(to: RouteLocation, from?: RouteLocation): void {
if (
to.name === VIEWS.EXECUTION_HOME ||
to.name === VIEWS.WORKFLOW_EXECUTIONS ||
to.name === VIEWS.EXECUTION_PREVIEW
) {
this.activeHeaderTab = MAIN_HEADER_TABS.EXECUTIONS;
} else if (
to.name === VIEWS.WORKFLOW ||
to.name === VIEWS.NEW_WORKFLOW ||
to.name === VIEWS.EXECUTION_DEBUG
) {
this.activeHeaderTab = MAIN_HEADER_TABS.WORKFLOW;
}
if (to.params.name !== 'new' && typeof to.params.name === 'string') {
this.workflowToReturnTo = to.params.name;
}
if (
from?.name === VIEWS.EXECUTION_PREVIEW &&
to.params.name === from.params.name &&
typeof from.params.executionId === 'string'
) {
this.executionToReturnTo = from.params.executionId;
}
},
onTabSelected(tab: MAIN_HEADER_TABS, event: MouseEvent) {
const openInNewTab = event.ctrlKey || event.metaKey;
switch (tab) {
case MAIN_HEADER_TABS.WORKFLOW:
void this.navigateToWorkflowView(openInNewTab);
break;
case MAIN_HEADER_TABS.EXECUTIONS:
void this.navigateToExecutionsView(openInNewTab);
break;
default:
break;
}
},
async navigateToWorkflowView(openInNewTab: boolean) {
let routeToNavigateTo: RouteLocationRaw;
if (!['', 'new', PLACEHOLDER_EMPTY_WORKFLOW_ID].includes(this.workflowToReturnTo)) {
routeToNavigateTo = {
name: VIEWS.WORKFLOW,
params: { name: this.workflowToReturnTo },
};
} else {
routeToNavigateTo = { name: VIEWS.NEW_WORKFLOW };
}
if (openInNewTab) {
const { href } = this.$router.resolve(routeToNavigateTo);
window.open(href, '_blank');
} else if (this.$route.name !== routeToNavigateTo.name) {
if (this.$route.name === VIEWS.NEW_WORKFLOW) {
this.uiStore.stateIsDirty = this.dirtyState;
}
this.activeHeaderTab = MAIN_HEADER_TABS.WORKFLOW;
await this.$router.push(routeToNavigateTo);
}
},
async navigateToExecutionsView(openInNewTab: boolean) {
const routeWorkflowId =
this.currentWorkflow === PLACEHOLDER_EMPTY_WORKFLOW_ID ? 'new' : this.currentWorkflow;
const executionToReturnTo =
this.executionsStore.activeExecution?.id || this.executionToReturnTo;
const routeToNavigateTo: RouteLocationRaw = executionToReturnTo
? {
name: VIEWS.EXECUTION_PREVIEW,
params: { name: routeWorkflowId, executionId: executionToReturnTo },
}
: {
name: VIEWS.EXECUTION_HOME,
params: { name: routeWorkflowId },
};
if (openInNewTab) {
const { href } = this.$router.resolve(routeToNavigateTo);
window.open(href, '_blank');
} else if (this.$route.name !== routeToNavigateTo.name) {
this.dirtyState = this.uiStore.stateIsDirty;
this.workflowToReturnTo = this.currentWorkflow;
this.activeHeaderTab = MAIN_HEADER_TABS.EXECUTIONS;
await this.$router.push(routeToNavigateTo);
}
},
},
});
</script>
<style lang="scss">
.main-header {
background-color: var(--color-background-xlight);