Skip to content

Commit

Permalink
refactor(editor): Enable collaboration features only in NodeView v2 (…
Browse files Browse the repository at this point in the history
…no-changelog)
  • Loading branch information
netroy committed Sep 10, 2024
1 parent 14580da commit f40d82f
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ function showCreateWorkflowSuccessToast(id?: string) {
</span>
<EnterpriseEdition :features="[EnterpriseEditionFeature.Sharing]">
<div :class="$style.group">
<CollaborationPane />
<CollaborationPane v-if="nodeViewVersion === '2'" />
<N8nButton
type="secondary"
data-test-id="workflow-share-button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,17 @@ describe('useBeforeUnload', () => {
});
});

describe('addBeforeUnloadHandler', () => {
it('should add additional handlers', () => {
const { addBeforeUnloadHandler, onBeforeUnload } = useBeforeUnload({ route: defaultRoute });
const event = new Event('beforeunload');
const handler = vi.fn();
addBeforeUnloadHandler(handler);
onBeforeUnload(event);
expect(handler).toHaveBeenCalled();
});
});

describe('addBeforeUnloadEventBindings', () => {
it('should add beforeunload event listener', () => {
const { addBeforeUnloadEventBindings } = useBeforeUnload({ route: defaultRoute });
Expand Down
29 changes: 13 additions & 16 deletions packages/editor-ui/src/composables/useBeforeUnload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ import { useCanvasStore } from '@/stores/canvas.store';
import { useUIStore } from '@/stores/ui.store';
import { useI18n } from '@/composables/useI18n';
import { computed, ref } from 'vue';
import { TIME, VIEWS } from '@/constants';
import { VIEWS } from '@/constants';
import type { useRoute } from 'vue-router';
import { useCollaborationStore } from '@/stores/collaboration.store';
import { useWorkflowsStore } from '@/stores/workflows.store';

/**
* Composable to handle the beforeunload event in canvas views.
Expand All @@ -17,42 +15,40 @@ import { useWorkflowsStore } from '@/stores/workflows.store';
export function useBeforeUnload({ route }: { route: ReturnType<typeof useRoute> }) {
const uiStore = useUIStore();
const canvasStore = useCanvasStore();
const collaborationStore = useCollaborationStore();
const workflowsStore = useWorkflowsStore();

const i18n = useI18n();

const unloadTimeout = ref<NodeJS.Timeout | null>(null);
const isDemoRoute = computed(() => route.name === VIEWS.DEMO);

type Handler = () => void;
const handlers: Handler[] = [];

function onBeforeUnload(e: BeforeUnloadEvent) {
if (isDemoRoute.value || window.preventNodeViewBeforeUnload) {
return;
} else if (uiStore.stateIsDirty) {
// A bit hacky solution to detecting users leaving the page after prompt:
// 1. Notify that workflow is closed straight away
collaborationStore.notifyWorkflowClosed(workflowsStore.workflowId);
// 2. If user decided to stay on the page we notify that the workflow is opened again
unloadTimeout.value = setTimeout(() => {
collaborationStore.notifyWorkflowOpened(workflowsStore.workflowId);
}, 5 * TIME.SECOND);
}

handlers.forEach((handler) => handler());

if (uiStore.stateIsDirty) {
e.returnValue = true; //Gecko + IE
return true; //Gecko + Webkit, Safari, Chrome etc.
} else {
canvasStore.startLoading(i18n.baseText('nodeView.redirecting'));
collaborationStore.notifyWorkflowClosed(workflowsStore.workflowId);
return;
}
}

function addBeforeUnloadHandler(handler: () => void) {
handlers.push(handler);
}

function addBeforeUnloadEventBindings() {
window.addEventListener('beforeunload', onBeforeUnload);
}

function removeBeforeUnloadEventBindings() {
collaborationStore.notifyWorkflowClosed(workflowsStore.workflowId);

if (unloadTimeout.value) {
clearTimeout(unloadTimeout.value);
}
Expand All @@ -64,5 +60,6 @@ export function useBeforeUnload({ route }: { route: ReturnType<typeof useRoute>
onBeforeUnload,
addBeforeUnloadEventBindings,
removeBeforeUnloadEventBindings,
addBeforeUnloadHandler,
};
}
25 changes: 22 additions & 3 deletions packages/editor-ui/src/views/NodeView.v2.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
PLACEHOLDER_EMPTY_WORKFLOW_ID,
START_NODE_TYPE,
STICKY_NODE_TYPE,
TIME,
VALID_WORKFLOW_IMPORT_URL_REGEX,
VIEWS,
WORKFLOW_LM_CHAT_MODAL_KEY,
Expand Down Expand Up @@ -151,9 +152,10 @@ const templatesStore = useTemplatesStore();
const canvasEventBus = createEventBus<CanvasEventBusEvents>();
const { addBeforeUnloadEventBindings, removeBeforeUnloadEventBindings } = useBeforeUnload({
route,
});
const { addBeforeUnloadEventBindings, removeBeforeUnloadEventBindings, addBeforeUnloadHandler } =
useBeforeUnload({
route,
});
const { registerCustomAction, unregisterCustomAction } = useGlobalLinkActions();
const { runWorkflow, stopCurrentExecution, stopWaitingForWebhook } = useRunWorkflow({ router });
const {
Expand Down Expand Up @@ -1486,6 +1488,8 @@ onBeforeMount(() => {
}
});
const unloadTimeout = ref<NodeJS.Timeout | null>(null);
onMounted(() => {
canvasStore.startLoading();
Expand Down Expand Up @@ -1518,6 +1522,18 @@ onMounted(() => {
addImportEventBindings();
addExecutionOpenedEventBindings();
registerCustomActions();
addBeforeUnloadHandler(() => {
const { workflowId } = workflowsStore;
// Notify that workflow is closed straight away
collaborationStore.notifyWorkflowClosed(workflowId);
if (uiStore.stateIsDirty) {
// If user decided to stay on the page we notify that the workflow is opened again
unloadTimeout.value = setTimeout(() => {
collaborationStore.notifyWorkflowOpened(workflowId);
}, 5 * TIME.SECOND);
}
});
});
onActivated(async () => {
Expand All @@ -1537,6 +1553,9 @@ onBeforeUnmount(() => {
removeExecutionOpenedEventBindings();
unregisterCustomActions();
collaborationStore.terminate();
if (unloadTimeout.value) {
clearTimeout(unloadTimeout.value);
}
});
</script>

Expand Down

0 comments on commit f40d82f

Please sign in to comment.