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:
Mutasem Aldmour 2022-10-20 15:45:58 +02:00 committed by GitHub
parent e83b9bd983
commit 356a42a187
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 8 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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: {

View file

@ -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;