n8n/packages/editor-ui/src/components/RunDataSchema.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

158 lines
3.7 KiB
Vue

<script lang="ts" setup>
import { computed, ref } from 'vue';
import { INodeUi, Schema } from "@/Interface";
import RunDataSchemaItem from "@/components/RunDataSchemaItem.vue";
import Draggable from '@/components/Draggable.vue';
import { useNDVStore } from "@/stores/ndv";
import { useWebhooksStore } from "@/stores/webhooks";
import { runExternalHook } from "@/mixins/externalHooks";
import { telemetry } from "@/plugins/telemetry";
import { IDataObject } from "n8n-workflow";
import { getSchema, mergeDeep } from "@/utils";
type Props = {
data: IDataObject[]
mappingEnabled: boolean
distanceFromActive: number
runIndex: number
totalRuns: number
node: INodeUi | null
}
const props = withDefaults(defineProps<Props>(), {
distanceFromActive: 0,
});
const draggingPath = ref<string>('');
const ndvStore = useNDVStore();
const webhooksStore = useWebhooksStore();
const schema = computed<Schema>(() => {
const [head, ...tail] = props.data;
return getSchema(mergeDeep([head, ...tail, head]));
});
const onDragStart = (el: HTMLElement) => {
if (el && el.dataset?.path) {
draggingPath.value = el.dataset.path;
}
ndvStore.resetMappingTelemetry();
};
const onDragEnd = (el: HTMLElement) => {
draggingPath.value = '';
setTimeout(() => {
const mappingTelemetry = ndvStore.mappingTelemetry;
const telemetryPayload = {
src_node_type: props.node?.type,
src_field_name: el.dataset.name || '',
src_nodes_back: props.distanceFromActive,
src_run_index: props.runIndex,
src_runs_total: props.totalRuns,
src_field_nest_level: el.dataset.depth || 0,
src_view: 'schema',
src_element: el,
success: false,
...mappingTelemetry,
};
runExternalHook('runDataJson.onDragEnd', webhooksStore, telemetryPayload);
telemetry.track('User dragged data for mapping', telemetryPayload);
}, 1000); // ensure dest data gets set if drop
};
</script>
<template>
<div :class="$style.schemaWrapper">
<draggable
type="mapping"
targetDataKey="mappable"
:disabled="!mappingEnabled"
@dragstart="onDragStart"
@dragend="onDragEnd"
>
<template #preview="{ canDrop, el }">
<div v-if="el" :class="[$style.dragPill, canDrop ? $style.droppablePill : $style.defaultPill]" v-html="el.outerHTML" />
</template>
<template>
<div :class="$style.schema">
<run-data-schema-item
:schema="schema"
:level="0"
:parent="null"
:subKey="`${schema.type}-0-0`"
:mappingEnabled="mappingEnabled"
:draggingPath="draggingPath"
:distanceFromActive="distanceFromActive"
:node="node"
/>
</div>
</template>
</draggable>
</div>
</template>
<style lang="scss" module>
.schemaWrapper {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
overflow: auto;
line-height: 1.5;
word-break: normal;
height: 100%;
width: 100%;
background-color: var(--color-background-base);
}
.schema {
display: inline-block;
padding: 0 var(--spacing-s) var(--spacing-s);
}
.dragPill {
display: inline-flex;
height: 24px;
padding: 0 var(--spacing-3xs);
border: 1px solid var(--color-foreground-light);
border-radius: 4px;
background: var(--color-background-xlight);
font-size: var(--font-size-2xs);
color: var(--color-text-base);
white-space: nowrap;
align-items: center;
span {
display: flex;
height: 100%;
align-items: center;
}
}
.droppablePill {
&,
span span {
color: var(--color-success);
border-color: var(--color-success-light);
background: var(--color-success-tint-3);
}
}
.defaultPill {
transform: translate(-50%, -100%);
box-shadow: 0 2px 6px rgba(68, 28, 23, 0.2);
&,
span span {
color: var(--color-primary);
border-color: var(--color-primary-tint-1);
background: var(--color-primary-tint-3);
}
}
</style>