n8n/packages/editor-ui/src/components/Draggable.vue
Csaba Tuncsik 4528f34462
feat(editor): Schema view (#4615)
* feat(editor): Generate custom schema from data (#4562)

* feat(core): adding a type package to n8n

* feat(editor): adding custom schema generator

* fix: add new types package to lock file

* fix: remove n8n_io/types package

* fix: adding path to generated schema

* fix: handling nested lists in schema generation

* fix: add date support to schema generation

* fix: define dates in ISO format

* fix: using test instead of it in repeated tests

* fix(editor): JSON schema treat nested lists as object to allow mapping each level

* fix(editor): rename JSON schema type

* fix(editor): make JSON schema path required

* fix(editor): using JSON schema bracket notation for object props to handle exceptional keys

* fix(editor): reorder JSON schema generator function args

* feat(editor): Add date recognizer util function (#4620)

*  Implemented date recogniser fuction
*  Added unit tests for date recogniser
* ✔️ Fixing linting errors
* 👌 Updating test cases

* feat(editor): Implement JSON Schema view UI functionalities (#4601)

* feat(core): adding a type package to n8n

* feat(editor): adding custom schema generator

* fix: add new types package to lock file

* fix: remove n8n_io/types package

* fix: adding path to generated schema

* fix: handling nested lists in schema generation

* fix: add date support to schema generation

* fix: define dates in ISO format

* fix: using test instead of it in repeated tests

* fix(editor): JSON schema treat nested lists as object to allow mapping each level

* fix(editor): rename JSON schema type

* fix(editor): make JSON schema path required

* fix(editor): using JSON schema bracket notation for object props to handle exceptional keys

* fix(editor): reorder JSON schema generator function args

* fix(editor): WIP json schema view

* fix(editor): formatting fix

* fix(editor): WIP json schema viewer

* fix(editor): fix schema generator and add deep merge

* fix(editor): WIP update json schema view components

* fix(editor): extend valid date checking

* fix(editor): WIP improving JSON schema view

* chore(editor): code formatting

* feat(editor): WIP Json schema view mapping + animations

* feat(editor): WIP update mergeDeep

* feat(editor): adding first item of json data to the end once more to get sample data from the first item

* feat(editor): adding first item of json data to the end once more to get sample data from the first item

* fix(editor): improving draggable design

* fix(editor): move util functions to their correct place after merge conflict

* fix(editor): move some type guards

* fix(editor): move some type guards

* fix(editor): change import path in unit test

* fix(editor): import missing interface

* fix(editor): remove unused functions and parts from json schema generation

* feat(editor): Add telemetry calls to JSON schema mapping (#4695)

* feat(editor): WIP JSON schema telemetry call

* feat(editor): make telemetry usable outside of Vue component context

* chore(editor): remove unused variable

* Merge branch 'feature/json-schema-view' of github.com:n8n-io/n8n into n8n-5410-add-telemetry-calls

# Conflicts:
#	packages/editor-ui/src/components/RunDataJsonSchema.vue

* fix(editor): VUE typing for telemetry

* fix(editor): enable PostHog feature flag

* fix(editor): Schema design review (#4740)

* refactor(editor): rename JsonSchema to Schema

* fix(editor): schema component name

* fix(editor): schema pill style

* fix(editor): schema type date as string

* fix(editor): schema styles (support long text + firefox)

* fix(editor): schema truncate text if it's too long

* fix(editor): schema types

* fix(editor): droppable styles

* fix(editor): schema component props

* fix(editor): fix draggable pill styles

* fix(editor): schema view styles

* fix(editor): schema mapping tooltip

* fix(editor): schema mapping styles

* fix(editor): mapping styles

* fix(editor): empty schema case

* fix(editor): delay mapping tooltip

* test(editor): add schema view snapshot test

* fix(editor): schema empty string

* fix(editor): schema string without space

* fix(editor): update schema test snapshot

* fix(editor): applying review comments

* fix(editor): make n8nExternalHooks optional

* fix(editor): remove TODO comment

Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2022-12-06 12:50:06 +01:00

178 lines
3.7 KiB
Vue

<template>
<component :is="tag"
:class="{[$style.dragging]: isDragging }"
@mousedown="onDragStart"
ref="wrapper"
>
<slot :isDragging="isDragging"></slot>
<Teleport to="body">
<div
ref="draggable"
:class="$style.draggable"
:style="draggableStyle"
v-show="isDragging"
>
<slot name="preview" :canDrop="canDrop" :el="draggingEl"></slot>
</div>
</Teleport>
</component>
</template>
<script lang="ts">
import { XYPosition } from '@/Interface';
import { useNDVStore } from '@/stores/ndv';
import { mapStores } from 'pinia';
import Vue from 'vue';
// @ts-ignore
import Teleport from 'vue2-teleport';
export default Vue.extend({
name: 'draggable',
components: {
Teleport,
},
props: {
disabled: {
type: Boolean,
},
type: {
type: String,
},
data: {
type: String,
},
tag: {
type: String,
default: 'div',
},
targetDataKey: {
type: String,
},
},
data() {
const draggablePosition = {
x: -100,
y: -100,
};
return {
isDragging: false,
draggablePosition,
draggingEl: null as null | HTMLElement,
draggableStyle: {
transform: `translate(${draggablePosition.x}px, ${draggablePosition.y}px)`,
},
animationFrameId: 0,
};
},
computed: {
...mapStores(
useNDVStore,
),
canDrop(): boolean {
return this.ndvStore.canDraggableDrop;
},
stickyPosition(): XYPosition | null {
return this.ndvStore.draggableStickyPos;
},
},
methods: {
setDraggableStyle() {
this.draggableStyle = {
transform: `translate(${this.draggablePosition.x}px, ${this.draggablePosition.y}px)`,
};
},
onDragStart(e: MouseEvent) {
if (this.disabled) {
return;
}
this.draggingEl = e.target as HTMLElement;
if (this.targetDataKey && this.draggingEl.dataset?.target !== this.targetDataKey) {
this.draggingEl = this.draggingEl.closest(`[data-target="${this.targetDataKey}"]`) as HTMLElement;
}
if (this.targetDataKey && this.draggingEl?.dataset?.target !== this.targetDataKey) {
return;
}
e.preventDefault();
e.stopPropagation();
this.isDragging = false;
this.draggablePosition = { x: e.pageX, y: e.pageY };
this.setDraggableStyle();
window.addEventListener('mousemove', this.onDrag);
window.addEventListener('mouseup', this.onDragEnd);
},
onDrag(e: MouseEvent) {
e.preventDefault();
e.stopPropagation();
if (this.disabled) {
return;
}
if(!this.isDragging) {
this.isDragging = true;
const data = this.targetDataKey && this.draggingEl ? this.draggingEl.dataset.value : (this.data || '');
this.ndvStore.draggableStartDragging({type: this.type, data: data || '' });
this.$emit('dragstart', this.draggingEl);
document.body.style.cursor = 'grabbing';
}
this.animationFrameId = window.requestAnimationFrame(() => {
if (this.canDrop && this.stickyPosition) {
this.draggablePosition = { x: this.stickyPosition[0], y: this.stickyPosition[1]};
} else {
this.draggablePosition = { x: e.pageX, y: e.pageY };
}
this.setDraggableStyle();
this.$emit('drag', this.draggablePosition);
});
},
onDragEnd() {
if (this.disabled) {
return;
}
document.body.style.cursor = 'unset';
window.removeEventListener('mousemove', this.onDrag);
window.removeEventListener('mouseup', this.onDragEnd);
window.cancelAnimationFrame(this.animationFrameId);
setTimeout(() => {
this.$emit('dragend', this.draggingEl);
this.isDragging = false;
this.draggingEl = null;
this.ndvStore.draggableStopDragging();
}, 0);
},
},
});
</script>
<style lang="scss" module>
.dragging {
visibility: visible;
cursor: grabbing;
}
.draggable {
position: fixed;
z-index: 9999999;
top: 0;
left: 0;
}
.draggable-data-transfer {
width: 0;
height: 0;
}
</style>