mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 04:34:06 -08:00
fix(editor): fix performance issues when opening node or editing code node with a lot of data (#4388)
* debounce clicks * debounce correctly * debounce resize * if initialized avoid * set watcher fixes * add deboucne for setting values * increase debounce * reset workspace for memory issues * address comment * decrease debounce time * decrease debounce time * clean up * revert back to trailing * support dbl
This commit is contained in:
parent
e83b9bd983
commit
356a42a187
|
@ -12,7 +12,7 @@
|
|||
:width="relativeWidthToPx(mainPanelDimensions.relativeWidth)"
|
||||
:minWidth="MIN_PANEL_WIDTH"
|
||||
:gridSize="20"
|
||||
@resize="onResize"
|
||||
@resize="onResizeDebounced"
|
||||
@resizestart="onResizeStart"
|
||||
@resizeend="onResizeEnd"
|
||||
:supportedDirections="supportedResizeDirections"
|
||||
|
@ -47,6 +47,8 @@ import {
|
|||
LOCAL_STORAGE_MAIN_PANEL_RELATIVE_WIDTH,
|
||||
MAIN_NODE_PANEL_WIDTH,
|
||||
} from '@/constants';
|
||||
import mixins from 'vue-typed-mixins';
|
||||
import { debounceHelper } from './mixins/debounce';
|
||||
|
||||
|
||||
const SIDE_MARGIN = 24;
|
||||
|
@ -63,7 +65,7 @@ const initialMainPanelWidth:{ [key: string]: number } = {
|
|||
wide: MAIN_NODE_PANEL_WIDTH * 2,
|
||||
};
|
||||
|
||||
export default Vue.extend({
|
||||
export default mixins(debounceHelper).extend({
|
||||
name: 'NDVDraggablePanels',
|
||||
components: {
|
||||
PanelDragButton,
|
||||
|
@ -83,11 +85,12 @@ export default Vue.extend({
|
|||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data(): { windowWidth: number, isDragging: boolean, MIN_PANEL_WIDTH: number} {
|
||||
data(): { windowWidth: number, isDragging: boolean, MIN_PANEL_WIDTH: number, initialized: boolean} {
|
||||
return {
|
||||
windowWidth: 1,
|
||||
isDragging: false,
|
||||
MIN_PANEL_WIDTH,
|
||||
initialized: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
@ -105,6 +108,9 @@ export default Vue.extend({
|
|||
|
||||
window.addEventListener('resize', this.setTotalWidth);
|
||||
this.$emit('init', { position: this.mainPanelDimensions.relativeLeft });
|
||||
setTimeout(() => {
|
||||
this.initialized = true;
|
||||
}, 0);
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener('resize', this.setTotalWidth);
|
||||
|
@ -295,6 +301,11 @@ export default Vue.extend({
|
|||
onResizeEnd() {
|
||||
this.storePositionData();
|
||||
},
|
||||
onResizeDebounced(data: { direction: string, x: number, width: number}) {
|
||||
if (this.initialized) {
|
||||
this.callDebounced('onResize', { debounceTime: 10, trailing: true }, data);
|
||||
}
|
||||
},
|
||||
onResize({ direction, x, width }: { direction: string, x: number, width: number}) {
|
||||
const relativeDistance = this.pxToRelativeWidth(x);
|
||||
const relativeWidth = this.pxToRelativeWidth(width);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="node-wrapper" :style="nodePosition" :id="nodeId">
|
||||
<div class="select-background" v-show="isSelected"></div>
|
||||
<div :class="{'node-default': true, 'touch-active': isTouchActive, 'is-touch-device': isTouchDevice}" :data-name="data.name" :ref="data.name">
|
||||
<div :class="nodeClass" :style="nodeStyle" @dblclick="setNodeActive" @click.left="mouseLeftClick" v-touch:start="touchStart" v-touch:end="touchEnd">
|
||||
<div :class="nodeClass" :style="nodeStyle" @click.left="onClick" v-touch:start="touchStart" v-touch:end="touchEnd">
|
||||
<div v-if="!data.disabled" :class="{'node-info-icon': true, 'shift-icon': shiftOutputCount}">
|
||||
<div v-if="hasIssues" class="node-issues">
|
||||
<n8n-tooltip placement="bottom" >
|
||||
|
@ -112,6 +112,7 @@ import mixins from 'vue-typed-mixins';
|
|||
import { get } from 'lodash';
|
||||
import { getStyleTokenValue, getTriggerNodeServiceName } from './helpers';
|
||||
import { INodeUi, XYPosition } from '@/Interface';
|
||||
import { debounceHelper } from './mixins/debounce';
|
||||
|
||||
export default mixins(
|
||||
externalHooks,
|
||||
|
@ -119,6 +120,7 @@ export default mixins(
|
|||
nodeHelpers,
|
||||
workflowHelpers,
|
||||
pinData,
|
||||
debounceHelper,
|
||||
).extend({
|
||||
name: 'Node',
|
||||
components: {
|
||||
|
@ -426,6 +428,19 @@ export default mixins(
|
|||
});
|
||||
},
|
||||
|
||||
onClick(event: MouseEvent) {
|
||||
this.callDebounced('onClickDebounced', { debounceTime: 300, trailing: true }, event);
|
||||
},
|
||||
|
||||
onClickDebounced(event: MouseEvent) {
|
||||
const isDoubleClick = event.detail >= 2;
|
||||
if (isDoubleClick) {
|
||||
this.setNodeActive();
|
||||
} else {
|
||||
this.mouseLeftClick(event);
|
||||
}
|
||||
},
|
||||
|
||||
setNodeActive () {
|
||||
this.$store.commit('setActiveNode', this.data.name);
|
||||
this.pinDataDiscoveryTooltipVisible = false;
|
||||
|
|
|
@ -352,7 +352,9 @@ export default mixins(
|
|||
this.avgOutputRowHeight = 0;
|
||||
this.avgInputRowHeight = 0;
|
||||
|
||||
this.$store.commit('ui/setNDVSessionId');
|
||||
setTimeout(() => {
|
||||
this.$store.commit('ui/setNDVSessionId');
|
||||
}, 0);
|
||||
this.$externalHooks().run('dataDisplay.nodeTypeChanged', {
|
||||
nodeSubtitle: this.getNodeSubtitle(node, this.activeNodeType, this.getCurrentWorkflow()),
|
||||
});
|
||||
|
@ -397,10 +399,14 @@ export default mixins(
|
|||
this.runInputIndex = -1;
|
||||
},
|
||||
inputNodeName(nodeName: string | undefined) {
|
||||
this.$store.commit('ui/setInputNodeName', nodeName);
|
||||
setTimeout(() => {
|
||||
this.$store.commit('ui/setInputNodeName', nodeName);
|
||||
}, 0);
|
||||
},
|
||||
inputRun() {
|
||||
this.$store.commit('ui/setInputRunIndex', this.inputRun);
|
||||
setTimeout(() => {
|
||||
this.$store.commit('ui/setInputRunIndex', this.inputRun);
|
||||
}, 0);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -73,7 +73,7 @@
|
|||
:mode="node.parameters.mode"
|
||||
:jsCode="node.parameters.jsCode"
|
||||
:isReadOnly="isReadOnly"
|
||||
@valueChanged="valueChanged"
|
||||
@valueChanged="valueChangedDebounced"
|
||||
/>
|
||||
|
||||
<div v-else-if="isEditor === true" class="code-edit clickable ph-no-capture" @click="displayEditDialog()">
|
||||
|
@ -336,12 +336,14 @@ import { CUSTOM_API_CALL_KEY } from '@/constants';
|
|||
import { mapGetters } from 'vuex';
|
||||
import { CODE_NODE_TYPE } from '@/constants';
|
||||
import { PropType } from 'vue';
|
||||
import { debounceHelper } from './mixins/debounce';
|
||||
|
||||
export default mixins(
|
||||
externalHooks,
|
||||
nodeHelpers,
|
||||
showMessage,
|
||||
workflowHelpers,
|
||||
debounceHelper,
|
||||
)
|
||||
.extend({
|
||||
name: 'parameter-input',
|
||||
|
@ -922,6 +924,9 @@ export default mixins(
|
|||
|
||||
this.$emit('textInput', parameterData);
|
||||
},
|
||||
valueChangedDebounced (value: NodeParameterValueType | {} | Date) {
|
||||
this.callDebounced('valueChanged', { debounceTime: 100 }, value);
|
||||
},
|
||||
valueChanged (value: NodeParameterValueType | {} | Date) {
|
||||
if (this.parameter.name === 'nodeCredentialType') {
|
||||
this.activeCredentialType = value as string;
|
||||
|
|
Loading…
Reference in a new issue