mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(editor): Workflow history [WIP] - Remove pinned data from workflow history version preview (no-changelog) (#7406)
This commit is contained in:
@@ -8,202 +8,194 @@
|
||||
</div>
|
||||
<iframe
|
||||
:class="{
|
||||
[$style.workflow]: !this.nodeViewDetailsOpened,
|
||||
[$style.workflow]: !nodeViewDetailsOpened,
|
||||
[$style.executionPreview]: mode === 'execution',
|
||||
[$style.openNDV]: this.nodeViewDetailsOpened,
|
||||
[$style.show]: this.showPreview,
|
||||
[$style.openNDV]: nodeViewDetailsOpened,
|
||||
[$style.show]: showPreview,
|
||||
}"
|
||||
ref="preview_iframe"
|
||||
ref="iframeRef"
|
||||
:src="`${rootStore.baseUrl}workflows/demo`"
|
||||
@mouseenter="onMouseEnter"
|
||||
@mouseleave="onMouseLeave"
|
||||
></iframe>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { useToast } from '@/composables';
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onBeforeUnmount, ref, computed, watch } from 'vue';
|
||||
import { useI18n, useToast } from '@/composables';
|
||||
import type { IWorkflowDb } from '@/Interface';
|
||||
import { mapStores } from 'pinia';
|
||||
import { useRootStore } from '@/stores/n8nRoot.store';
|
||||
import { useWorkflowsStore } from '@/stores';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'WorkflowPreview',
|
||||
props: {
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'workflow',
|
||||
validator: (value: string): boolean => ['workflow', 'execution'].includes(value),
|
||||
},
|
||||
workflow: {
|
||||
type: Object as () => IWorkflowDb,
|
||||
required: false,
|
||||
},
|
||||
executionId: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
executionMode: {
|
||||
type: String,
|
||||
required: false,
|
||||
},
|
||||
loaderType: {
|
||||
type: String,
|
||||
default: 'image',
|
||||
validator: (value: string): boolean => ['image', 'spinner'].includes(value),
|
||||
},
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
loading?: boolean;
|
||||
mode?: 'workflow' | 'execution';
|
||||
workflow?: IWorkflowDb;
|
||||
executionId?: string;
|
||||
executionMode?: string;
|
||||
loaderType?: 'image' | 'spinner';
|
||||
}>(),
|
||||
{
|
||||
loading: false,
|
||||
mode: 'workflow',
|
||||
loaderType: 'image',
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
...useToast(),
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nodeViewDetailsOpened: false,
|
||||
ready: false,
|
||||
insideIframe: false,
|
||||
scrollX: 0,
|
||||
scrollY: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapStores(useRootStore, useWorkflowsStore),
|
||||
showPreview(): boolean {
|
||||
return (
|
||||
!this.loading &&
|
||||
((this.mode === 'workflow' && !!this.workflow) ||
|
||||
(this.mode === 'execution' && !!this.executionId)) &&
|
||||
this.ready
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onMouseEnter() {
|
||||
this.insideIframe = true;
|
||||
this.scrollX = window.scrollX;
|
||||
this.scrollY = window.scrollY;
|
||||
},
|
||||
onMouseLeave() {
|
||||
this.insideIframe = false;
|
||||
},
|
||||
loadWorkflow() {
|
||||
try {
|
||||
if (!this.workflow) {
|
||||
throw new Error(this.$locale.baseText('workflowPreview.showError.missingWorkflow'));
|
||||
}
|
||||
if (!this.workflow.nodes || !Array.isArray(this.workflow.nodes)) {
|
||||
throw new Error(this.$locale.baseText('workflowPreview.showError.arrayEmpty'));
|
||||
}
|
||||
);
|
||||
|
||||
const iframeRef = this.$refs.preview_iframe as HTMLIFrameElement | undefined;
|
||||
if (iframeRef?.contentWindow) {
|
||||
iframeRef.contentWindow.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openWorkflow',
|
||||
workflow: this.workflow,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('workflowPreview.showError.previewError.title'),
|
||||
this.$locale.baseText('workflowPreview.showError.previewError.message'),
|
||||
);
|
||||
}
|
||||
},
|
||||
loadExecution() {
|
||||
try {
|
||||
if (!this.executionId) {
|
||||
throw new Error(this.$locale.baseText('workflowPreview.showError.missingExecution'));
|
||||
}
|
||||
const iframeRef = this.$refs.preview_iframe as HTMLIFrameElement | undefined;
|
||||
if (iframeRef?.contentWindow) {
|
||||
iframeRef.contentWindow.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'openExecution',
|
||||
executionId: this.executionId,
|
||||
executionMode: this.executionMode || '',
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
const emit = defineEmits<{
|
||||
(event: 'close'): void;
|
||||
}>();
|
||||
|
||||
if (this.workflowsStore.activeWorkflowExecution) {
|
||||
iframeRef.contentWindow.postMessage(
|
||||
JSON.stringify({
|
||||
command: 'setActiveExecution',
|
||||
execution: this.workflowsStore.activeWorkflowExecution,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.showError(
|
||||
error,
|
||||
this.$locale.baseText('workflowPreview.showError.previewError.title'),
|
||||
this.$locale.baseText('workflowPreview.executionMode.showError.previewError.message'),
|
||||
);
|
||||
}
|
||||
},
|
||||
receiveMessage({ data }: MessageEvent) {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
if (json.command === 'n8nReady') {
|
||||
this.ready = true;
|
||||
} else if (json.command === 'openNDV') {
|
||||
this.nodeViewDetailsOpened = true;
|
||||
} else if (json.command === 'closeNDV') {
|
||||
this.nodeViewDetailsOpened = false;
|
||||
} else if (json.command === 'error') {
|
||||
this.$emit('close');
|
||||
}
|
||||
} catch (e) {}
|
||||
},
|
||||
onDocumentScroll() {
|
||||
if (this.insideIframe) {
|
||||
window.scrollTo(this.scrollX, this.scrollY);
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
showPreview(show) {
|
||||
if (show) {
|
||||
if (this.mode === 'workflow') {
|
||||
this.loadWorkflow();
|
||||
} else if (this.mode === 'execution') {
|
||||
this.loadExecution();
|
||||
}
|
||||
}
|
||||
},
|
||||
executionId(value) {
|
||||
if (this.mode === 'execution' && this.executionId) {
|
||||
this.loadExecution();
|
||||
}
|
||||
},
|
||||
workflow() {
|
||||
if (this.mode === 'workflow' && this.workflow) {
|
||||
this.loadWorkflow();
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('message', this.receiveMessage);
|
||||
document.addEventListener('scroll', this.onDocumentScroll);
|
||||
},
|
||||
beforeUnmount() {
|
||||
window.removeEventListener('message', this.receiveMessage);
|
||||
document.removeEventListener('scroll', this.onDocumentScroll);
|
||||
},
|
||||
const i18n = useI18n();
|
||||
const toast = useToast();
|
||||
const rootStore = useRootStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
|
||||
const iframeRef = ref<HTMLIFrameElement | null>(null);
|
||||
const nodeViewDetailsOpened = ref(false);
|
||||
const ready = ref(false);
|
||||
const insideIframe = ref(false);
|
||||
const scrollX = ref(0);
|
||||
const scrollY = ref(0);
|
||||
|
||||
const showPreview = computed(() => {
|
||||
return (
|
||||
!props.loading &&
|
||||
((props.mode === 'workflow' && props.workflow) ||
|
||||
(props.mode === 'execution' && props.executionId)) &&
|
||||
ready.value
|
||||
);
|
||||
});
|
||||
|
||||
const loadWorkflow = () => {
|
||||
try {
|
||||
if (!props.workflow) {
|
||||
throw new Error(i18n.baseText('workflowPreview.showError.missingWorkflow'));
|
||||
}
|
||||
if (!props.workflow.nodes || !Array.isArray(props.workflow.nodes)) {
|
||||
throw new Error(i18n.baseText('workflowPreview.showError.arrayEmpty'));
|
||||
}
|
||||
iframeRef.value?.contentWindow?.postMessage?.(
|
||||
JSON.stringify({
|
||||
command: 'openWorkflow',
|
||||
workflow: props.workflow,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
} catch (error) {
|
||||
toast.showError(
|
||||
error,
|
||||
i18n.baseText('workflowPreview.showError.previewError.title'),
|
||||
i18n.baseText('workflowPreview.showError.previewError.message'),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const loadExecution = () => {
|
||||
try {
|
||||
if (!props.executionId) {
|
||||
throw new Error(i18n.baseText('workflowPreview.showError.missingExecution'));
|
||||
}
|
||||
iframeRef.value?.contentWindow?.postMessage?.(
|
||||
JSON.stringify({
|
||||
command: 'openExecution',
|
||||
executionId: props.executionId,
|
||||
executionMode: props.executionMode || '',
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
|
||||
if (workflowsStore.activeWorkflowExecution) {
|
||||
iframeRef.value?.contentWindow?.postMessage?.(
|
||||
JSON.stringify({
|
||||
command: 'setActiveExecution',
|
||||
execution: workflowsStore.activeWorkflowExecution,
|
||||
}),
|
||||
'*',
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
toast.showError(
|
||||
error,
|
||||
i18n.baseText('workflowPreview.showError.previewError.title'),
|
||||
i18n.baseText('workflowPreview.executionMode.showError.previewError.message'),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseEnter = () => {
|
||||
insideIframe.value = true;
|
||||
scrollX.value = window.scrollX;
|
||||
scrollY.value = window.scrollY;
|
||||
};
|
||||
const onMouseLeave = () => {
|
||||
insideIframe.value = false;
|
||||
};
|
||||
|
||||
const receiveMessage = ({ data }: MessageEvent) => {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
if (json.command === 'n8nReady') {
|
||||
ready.value = true;
|
||||
} else if (json.command === 'openNDV') {
|
||||
nodeViewDetailsOpened.value = true;
|
||||
} else if (json.command === 'closeNDV') {
|
||||
nodeViewDetailsOpened.value = false;
|
||||
} else if (json.command === 'error') {
|
||||
emit('close');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
const onDocumentScroll = () => {
|
||||
if (insideIframe.value) {
|
||||
window.scrollTo(scrollX.value, scrollY.value);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('message', receiveMessage);
|
||||
document.addEventListener('scroll', onDocumentScroll);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('message', receiveMessage);
|
||||
document.removeEventListener('scroll', onDocumentScroll);
|
||||
});
|
||||
|
||||
watch(
|
||||
() => showPreview.value,
|
||||
() => {
|
||||
if (showPreview.value) {
|
||||
if (props.mode === 'workflow') {
|
||||
loadWorkflow();
|
||||
} else if (props.mode === 'execution') {
|
||||
loadExecution();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.executionId,
|
||||
() => {
|
||||
if (props.mode === 'execution' && props.executionId) {
|
||||
loadExecution();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.workflow,
|
||||
() => {
|
||||
if (props.mode === 'workflow' && props.workflow) {
|
||||
loadWorkflow();
|
||||
}
|
||||
},
|
||||
);
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
||||
Reference in New Issue
Block a user