mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
* refactor(editor): Fix ElementUI tooltip memory leak * fix(editor): Remove patch console.logs and revert node-creator test
247 lines
5.7 KiB
Vue
247 lines
5.7 KiB
Vue
<template>
|
|
<div
|
|
draggable
|
|
@dragstart="onDragStart"
|
|
@dragend="onDragEnd"
|
|
:class="{[$style['node-item']]: true}"
|
|
>
|
|
<node-icon :class="$style['node-icon']" :nodeType="nodeType" />
|
|
<div>
|
|
<div :class="$style.details">
|
|
<span :class="$style.name" data-test-id="node-item-name">
|
|
{{ $locale.headerText({
|
|
key: `headers.${shortNodeType}.displayName`,
|
|
fallback: nodeType.displayName,
|
|
})
|
|
}}
|
|
</span>
|
|
<span v-if="isTrigger" :class="$style['trigger-icon']">
|
|
<trigger-icon />
|
|
</span>
|
|
<n8n-tooltip v-if="isCommunityNode" placement="top" data-test-id="node-item-community-tooltip">
|
|
<template #content>
|
|
<div
|
|
:class="$style['community-node-icon']"
|
|
v-html="$locale.baseText('generic.communityNode.tooltip', { interpolate: { packageName: nodeType.name.split('.')[0], docURL: COMMUNITY_NODES_INSTALLATION_DOCS_URL } })"
|
|
@click="onCommunityNodeTooltipClick"
|
|
>
|
|
</div>
|
|
</template>
|
|
<n8n-icon icon="cube" />
|
|
</n8n-tooltip>
|
|
</div>
|
|
<div :class="$style.description">
|
|
{{ $locale.headerText({
|
|
key: `headers.${shortNodeType}.description`,
|
|
fallback: nodeType.description,
|
|
})
|
|
}}
|
|
</div>
|
|
|
|
<div :class="$style['draggable-data-transfer']" ref="draggableDataTransfer" />
|
|
<transition name="node-item-transition">
|
|
<div
|
|
:class="$style.draggable"
|
|
:style="draggableStyle"
|
|
ref="draggable"
|
|
v-show="dragging"
|
|
>
|
|
<node-icon class="node-icon" :nodeType="nodeType" :size="40" :shrink="false" />
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
|
|
import Vue, { PropType } from 'vue';
|
|
import { INodeTypeDescription } from 'n8n-workflow';
|
|
|
|
import { isCommunityPackageName } from '@/utils';
|
|
import { getNewNodePosition, NODE_SIZE } from '@/utils/nodeViewUtils';
|
|
import { COMMUNITY_NODES_INSTALLATION_DOCS_URL } from '@/constants';
|
|
|
|
import NodeIcon from '@/components/NodeIcon.vue';
|
|
import TriggerIcon from '@/components/TriggerIcon.vue';
|
|
|
|
Vue.component('node-icon', NodeIcon);
|
|
Vue.component('trigger-icon', TriggerIcon);
|
|
|
|
export default Vue.extend({
|
|
name: 'NodeItem',
|
|
props: {
|
|
nodeType: {
|
|
type: Object as PropType<INodeTypeDescription>,
|
|
},
|
|
active: {
|
|
type: Boolean,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
dragging: false,
|
|
draggablePosition: {
|
|
x: -100,
|
|
y: -100,
|
|
},
|
|
COMMUNITY_NODES_INSTALLATION_DOCS_URL,
|
|
};
|
|
},
|
|
computed: {
|
|
shortNodeType(): string {
|
|
return this.$locale.shortNodeType(this.nodeType.name);
|
|
},
|
|
isTrigger (): boolean {
|
|
return this.nodeType.group.includes('trigger');
|
|
},
|
|
draggableStyle(): { top: string; left: string; } {
|
|
return {
|
|
top: `${this.draggablePosition.y}px`,
|
|
left: `${this.draggablePosition.x}px`,
|
|
};
|
|
},
|
|
isCommunityNode(): boolean {
|
|
return isCommunityPackageName(this.nodeType.name);
|
|
},
|
|
},
|
|
methods: {
|
|
onDragStart(event: DragEvent): void {
|
|
/**
|
|
* Workaround for firefox, that doesn't attach the pageX and pageY coordinates to "ondrag" event.
|
|
* All browsers attach the correct page coordinates to the "dragover" event.
|
|
* @bug https://bugzilla.mozilla.org/show_bug.cgi?id=505521
|
|
*/
|
|
document.body.addEventListener("dragover", this.onDragOver);
|
|
const { pageX: x, pageY: y } = event;
|
|
|
|
this.$emit('dragstart', event);
|
|
|
|
if (event.dataTransfer) {
|
|
event.dataTransfer.effectAllowed = "copy";
|
|
event.dataTransfer.dropEffect = "copy";
|
|
event.dataTransfer.setData('nodeTypeName', this.nodeType.name);
|
|
event.dataTransfer.setDragImage(this.$refs.draggableDataTransfer as Element, 0, 0);
|
|
}
|
|
|
|
this.dragging = true;
|
|
this.draggablePosition = { x, y };
|
|
},
|
|
onDragOver(event: DragEvent): void {
|
|
if (!this.dragging || event.pageX === 0 && event.pageY === 0) {
|
|
return;
|
|
}
|
|
|
|
const [x,y] = getNewNodePosition([], [event.pageX - NODE_SIZE / 2, event.pageY - NODE_SIZE / 2]);
|
|
|
|
this.draggablePosition = { x, y };
|
|
},
|
|
onDragEnd(event: DragEvent): void {
|
|
document.body.removeEventListener("dragover", this.onDragOver);
|
|
this.$emit('dragend', event);
|
|
|
|
this.dragging = false;
|
|
setTimeout(() => {
|
|
this.draggablePosition = { x: -100, y: -100 };
|
|
}, 300);
|
|
},
|
|
onCommunityNodeTooltipClick(event: MouseEvent) {
|
|
if ((event.target as Element).localName === 'a') {
|
|
this.$telemetry.track('user clicked cnr docs link', { source: 'nodes panel node' });
|
|
}
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" module>
|
|
.node-item {
|
|
padding: 11px 8px 11px 0;
|
|
margin-left: 15px;
|
|
margin-right: 12px;
|
|
display: flex;
|
|
cursor: grab;
|
|
}
|
|
|
|
.details {
|
|
align-items: center;
|
|
}
|
|
|
|
.node-icon {
|
|
min-width: 26px;
|
|
max-width: 26px;
|
|
margin-right: 15px;
|
|
}
|
|
|
|
.name {
|
|
font-weight: var(--font-weight-bold);
|
|
font-size: 14px;
|
|
line-height: 18px;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.packageName {
|
|
margin-right: 5px;
|
|
}
|
|
|
|
.description {
|
|
margin-top: 2px;
|
|
font-size: var(--font-size-2xs);
|
|
line-height: 16px;
|
|
font-weight: 400;
|
|
color: $node-creator-description-color;
|
|
}
|
|
|
|
.trigger-icon {
|
|
height: 16px;
|
|
width: 16px;
|
|
display: inline-block;
|
|
margin-right: var(--spacing-3xs);
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.community-node-icon {
|
|
vertical-align: top;
|
|
}
|
|
|
|
.draggable {
|
|
width: 100px;
|
|
height: 100px;
|
|
position: fixed;
|
|
z-index: 1;
|
|
opacity: 0.66;
|
|
border: 2px solid var(--color-foreground-xdark);
|
|
border-radius: var(--border-radius-large);
|
|
background-color: var(--color-background-xlight);
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.draggable-data-transfer {
|
|
width: 1px;
|
|
height: 1px;
|
|
}
|
|
</style>
|
|
|
|
<style lang="scss" scoped>
|
|
.node-item-transition {
|
|
&-enter-active,
|
|
&-leave-active {
|
|
transition-property: opacity, transform;
|
|
transition-duration: 300ms;
|
|
transition-timing-function: ease;
|
|
}
|
|
|
|
&-enter,
|
|
&-leave-to {
|
|
opacity: 0;
|
|
transform: scale(0);
|
|
}
|
|
}
|
|
|
|
.el-tooltip svg {
|
|
color: var(--color-foreground-xdark);
|
|
}
|
|
</style>
|