mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat(editor): Schema preview UI updates (#13578)
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions
This commit is contained in:
parent
c821f1c532
commit
8790a0df3d
|
@ -314,7 +314,7 @@ const onDragEnd = (el: HTMLElement) => {
|
|||
@click="toggleNodeAndScrollTop(item.id)"
|
||||
/>
|
||||
<VirtualSchemaItem
|
||||
v-else
|
||||
v-else-if="item.type === 'item'"
|
||||
v-bind="item"
|
||||
:search="search"
|
||||
:draggable="mappingEnabled"
|
||||
|
@ -323,6 +323,10 @@ const onDragEnd = (el: HTMLElement) => {
|
|||
@click="toggleLeaf(item.id)"
|
||||
>
|
||||
</VirtualSchemaItem>
|
||||
|
||||
<N8nTooltip v-else-if="item.type === 'icon'" :content="item.tooltip" placement="top">
|
||||
<N8nIcon :size="14" :icon="item.icon" class="icon" />
|
||||
</N8nTooltip>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
</DynamicScroller>
|
||||
|
@ -347,4 +351,11 @@ const onDragEnd = (el: HTMLElement) => {
|
|||
text-align: center;
|
||||
padding: var(--spacing-s) var(--spacing-s) var(--spacing-xl) var(--spacing-s);
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: inline-flex;
|
||||
margin-left: var(--spacing-xl);
|
||||
color: var(--color-text-light);
|
||||
margin-bottom: var(--spacing-s);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,8 +4,7 @@ import NodeIcon from '@/components/NodeIcon.vue';
|
|||
import { type INodeTypeDescription } from 'n8n-workflow';
|
||||
import { useI18n } from '@/composables/useI18n';
|
||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
|
||||
import { DATA_EDITING_DOCS_URL } from '@/constants';
|
||||
import { N8nNotice } from '@n8n/design-system';
|
||||
import { SCHEMA_PREVIEW_DOCS_URL } from '@/constants';
|
||||
|
||||
const props = defineProps<{
|
||||
title: string;
|
||||
|
@ -42,24 +41,28 @@ const emit = defineEmits<{
|
|||
<span v-if="info" class="info">{{ info }}</span>
|
||||
</div>
|
||||
<FontAwesomeIcon v-if="isTrigger" class="trigger-icon" icon="bolt" size="xs" />
|
||||
<div v-if="itemCount" class="item-count" data-test-id="run-data-schema-node-item-count">
|
||||
<div v-if="itemCount" class="extra-info" data-test-id="run-data-schema-node-item-count">
|
||||
{{ i18n.baseText('ndv.output.items', { interpolate: { count: itemCount } }) }}
|
||||
</div>
|
||||
<div v-else-if="preview" class="extra-info">
|
||||
{{ i18n.baseText('dataMapping.schemaView.previewNode') }}
|
||||
</div>
|
||||
</div>
|
||||
<N8nNotice
|
||||
<div
|
||||
v-if="preview && !collapsed"
|
||||
class="notice"
|
||||
theme="warning"
|
||||
data-test-id="schema-preview-warning"
|
||||
@click.stop
|
||||
>
|
||||
<i18n-t keypath="dataMapping.schemaView.preview">
|
||||
<template #link>
|
||||
<N8nLink :to="DATA_EDITING_DOCS_URL" size="small">
|
||||
<N8nLink :to="SCHEMA_PREVIEW_DOCS_URL" size="small" bold>
|
||||
{{ i18n.baseText('generic.learnMore') }}
|
||||
</N8nLink>
|
||||
</template>
|
||||
</i18n-t>
|
||||
</N8nNotice>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -117,7 +120,7 @@ const emit = defineEmits<{
|
|||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.item-count {
|
||||
.extra-info {
|
||||
font-size: var(--font-size-2xs);
|
||||
color: var(--color-text-light);
|
||||
margin-left: auto;
|
||||
|
@ -126,6 +129,9 @@ const emit = defineEmits<{
|
|||
.notice {
|
||||
margin-left: var(--spacing-2xl);
|
||||
margin-top: var(--spacing-2xs);
|
||||
margin-bottom: 0;
|
||||
padding-bottom: var(--spacing-2xs);
|
||||
color: var(--color-text-base);
|
||||
font-size: var(--font-size-2xs);
|
||||
line-height: var(--font-line-height-loose);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -43,7 +43,10 @@ const emit = defineEmits<{
|
|||
:data-node-type="nodeType"
|
||||
data-target="mappable"
|
||||
class="pill"
|
||||
:class="{ 'pill--highlight': highlight, 'pill--preview': preview }"
|
||||
:class="{
|
||||
'pill--highlight': highlight,
|
||||
'pill--preview': preview,
|
||||
}"
|
||||
data-test-id="run-data-schema-node-name"
|
||||
>
|
||||
<FontAwesomeIcon class="type-icon" :icon size="sm" />
|
||||
|
@ -77,6 +80,7 @@ const emit = defineEmits<{
|
|||
justify-content: center;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-size-s);
|
||||
color: var(--color-text-light);
|
||||
}
|
||||
|
||||
.pill {
|
||||
|
@ -98,16 +102,31 @@ const emit = defineEmits<{
|
|||
}
|
||||
|
||||
&.pill--preview {
|
||||
border-style: dashed;
|
||||
border-width: 1.5px;
|
||||
/* Cannot use CSS variable inside data URL, so instead switching based on data-theme and media query */
|
||||
--schema-preview-dashed-border: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' viewBox='0 0 400 400' fill='none' rx='4' ry='4' stroke='%230000002A' stroke-width='2' stroke-dasharray='4%2c 4' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
|
||||
--schema-preview-dashed-border-dark: url("data:image/svg+xml,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' viewBox='0 0 400 400' fill='none' rx='4' ry='4' stroke='%23FFFFFF2A' stroke-width='2' stroke-dasharray='4%2c 4' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e");
|
||||
color: var(--color-text-light);
|
||||
background-color: var(--color-run-data-background);
|
||||
border: none;
|
||||
max-width: calc(100% - var(--spacing-l));
|
||||
background-image: var(--schema-preview-dashed-border);
|
||||
|
||||
.title {
|
||||
color: var(--color-text-light);
|
||||
border-left: 1.5px dashed var(--color-foreground-light);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body:not([data-theme]) .pill--preview {
|
||||
background-image: var(--schema-preview-dashed-border-dark);
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme='dark'] .pill--preview {
|
||||
background-image: var(--schema-preview-dashed-border-dark);
|
||||
}
|
||||
|
||||
.draggable .pill.pill--highlight {
|
||||
color: var(--color-primary);
|
||||
border-color: var(--color-primary-tint-1);
|
||||
|
|
|
@ -110,7 +110,12 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
swapopacity="false"
|
||||
symbol="false"
|
||||
/>
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="extra-info"
|
||||
data-v-882a318e=""
|
||||
>
|
||||
Preview
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="notice"
|
||||
|
@ -119,13 +124,12 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
theme="warning"
|
||||
>
|
||||
|
||||
|
||||
This is a preview of the schema, execute the node to see the exact schema and data.
|
||||
Usually outputs the following fields. Execute the node to see the actual ones.
|
||||
|
||||
<a
|
||||
class="n8n-link"
|
||||
data-v-882a318e=""
|
||||
href="https://docs.n8n.io/data/data-editing/"
|
||||
href="https://docs.n8n.io/data/schema-preview/"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
|
@ -133,7 +137,7 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
class="primary"
|
||||
>
|
||||
<span
|
||||
class="n8n-text size-small regular"
|
||||
class="n8n-text size-small bold"
|
||||
>
|
||||
|
||||
|
||||
|
@ -146,7 +150,6 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -328,70 +331,38 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
|
||||
|
||||
|
||||
<div
|
||||
class="schema-item draggable"
|
||||
data-test-id="run-data-schema-item"
|
||||
data-v-0f5e7239=""
|
||||
|
||||
<span
|
||||
class="n8n-text compact size-14 regular n8n-icon icon el-tooltip__trigger el-tooltip__trigger icon el-tooltip__trigger el-tooltip__trigger n8n-icon icon el-tooltip__trigger el-tooltip__trigger icon el-tooltip__trigger el-tooltip__trigger"
|
||||
data-v-d00cba9a=""
|
||||
type="item"
|
||||
>
|
||||
<div
|
||||
class="toggle-container"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div
|
||||
class="pill pill--preview"
|
||||
data-name="..."
|
||||
data-nest-level="1"
|
||||
data-target="mappable"
|
||||
data-test-id="run-data-schema-node-name"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
beat="false"
|
||||
beatfade="false"
|
||||
border="false"
|
||||
bounce="false"
|
||||
class="type-icon"
|
||||
data-v-0f5e7239=""
|
||||
fade="false"
|
||||
fixedwidth="false"
|
||||
flash="false"
|
||||
flip="false"
|
||||
icon=""
|
||||
inverse="false"
|
||||
listitem="false"
|
||||
pulse="false"
|
||||
shake="false"
|
||||
size="sm"
|
||||
spin="false"
|
||||
spinpulse="false"
|
||||
spinreverse="false"
|
||||
swapopacity="false"
|
||||
symbol="false"
|
||||
/>
|
||||
<span
|
||||
class="content title"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
|
||||
<span>
|
||||
<!--v-if-->
|
||||
...
|
||||
</span>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="content text"
|
||||
data-test-id="run-data-schema-item-value"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
<span />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<font-awesome-icon-stub
|
||||
beat="false"
|
||||
beatfade="false"
|
||||
border="false"
|
||||
bounce="false"
|
||||
class="14"
|
||||
fade="false"
|
||||
fixedwidth="false"
|
||||
flash="false"
|
||||
flip="false"
|
||||
icon="ellipsis-h"
|
||||
inverse="false"
|
||||
listitem="false"
|
||||
pulse="false"
|
||||
shake="false"
|
||||
spin="false"
|
||||
spinpulse="false"
|
||||
spinreverse="false"
|
||||
swapopacity="false"
|
||||
symbol="false"
|
||||
/>
|
||||
|
||||
</span>
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -464,7 +435,12 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
<!--v-if-->
|
||||
</div>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="extra-info"
|
||||
data-v-882a318e=""
|
||||
>
|
||||
Preview
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="notice"
|
||||
|
@ -473,13 +449,12 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
theme="warning"
|
||||
>
|
||||
|
||||
|
||||
This is a preview of the schema, execute the node to see the exact schema and data.
|
||||
Usually outputs the following fields. Execute the node to see the actual ones.
|
||||
|
||||
<a
|
||||
class="n8n-link"
|
||||
data-v-882a318e=""
|
||||
href="https://docs.n8n.io/data/data-editing/"
|
||||
href="https://docs.n8n.io/data/schema-preview/"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
|
@ -487,7 +462,7 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
class="primary"
|
||||
>
|
||||
<span
|
||||
class="n8n-text size-small regular"
|
||||
class="n8n-text size-small bold"
|
||||
>
|
||||
|
||||
|
||||
|
@ -500,7 +475,6 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
</a>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -682,70 +656,38 @@ exports[`VirtualSchema.vue > renders preview schema when enabled and available 1
|
|||
|
||||
|
||||
|
||||
<div
|
||||
class="schema-item draggable"
|
||||
data-test-id="run-data-schema-item"
|
||||
data-v-0f5e7239=""
|
||||
|
||||
<span
|
||||
class="n8n-text compact size-14 regular n8n-icon icon el-tooltip__trigger el-tooltip__trigger icon el-tooltip__trigger el-tooltip__trigger n8n-icon icon el-tooltip__trigger el-tooltip__trigger icon el-tooltip__trigger el-tooltip__trigger"
|
||||
data-v-d00cba9a=""
|
||||
type="item"
|
||||
>
|
||||
<div
|
||||
class="toggle-container"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<div
|
||||
class="pill pill--preview"
|
||||
data-name="..."
|
||||
data-nest-level="1"
|
||||
data-target="mappable"
|
||||
data-test-id="run-data-schema-node-name"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
<font-awesome-icon-stub
|
||||
beat="false"
|
||||
beatfade="false"
|
||||
border="false"
|
||||
bounce="false"
|
||||
class="type-icon"
|
||||
data-v-0f5e7239=""
|
||||
fade="false"
|
||||
fixedwidth="false"
|
||||
flash="false"
|
||||
flip="false"
|
||||
icon=""
|
||||
inverse="false"
|
||||
listitem="false"
|
||||
pulse="false"
|
||||
shake="false"
|
||||
size="sm"
|
||||
spin="false"
|
||||
spinpulse="false"
|
||||
spinreverse="false"
|
||||
swapopacity="false"
|
||||
symbol="false"
|
||||
/>
|
||||
<span
|
||||
class="content title"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
|
||||
<span>
|
||||
<!--v-if-->
|
||||
...
|
||||
</span>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
class="content text"
|
||||
data-test-id="run-data-schema-item-value"
|
||||
data-v-0f5e7239=""
|
||||
>
|
||||
<span />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<font-awesome-icon-stub
|
||||
beat="false"
|
||||
beatfade="false"
|
||||
border="false"
|
||||
bounce="false"
|
||||
class="14"
|
||||
fade="false"
|
||||
fixedwidth="false"
|
||||
flash="false"
|
||||
flip="false"
|
||||
icon="ellipsis-h"
|
||||
inverse="false"
|
||||
listitem="false"
|
||||
pulse="false"
|
||||
shake="false"
|
||||
spin="false"
|
||||
spinpulse="false"
|
||||
spinreverse="false"
|
||||
swapopacity="false"
|
||||
symbol="false"
|
||||
/>
|
||||
|
||||
</span>
|
||||
<!--teleport start-->
|
||||
<!--teleport end-->
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -821,7 +763,7 @@ exports[`VirtualSchema.vue > renders previous nodes schema for AI tools 1`] = `
|
|||
</div>
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="item-count"
|
||||
class="extra-info"
|
||||
data-test-id="run-data-schema-node-item-count"
|
||||
data-v-882a318e=""
|
||||
>
|
||||
|
@ -893,7 +835,7 @@ exports[`VirtualSchema.vue > renders schema for correct output branch 1`] = `
|
|||
</div>
|
||||
<!--v-if-->
|
||||
<div
|
||||
class="item-count"
|
||||
class="extra-info"
|
||||
data-test-id="run-data-schema-node-item-count"
|
||||
data-v-882a318e=""
|
||||
>
|
||||
|
@ -1447,7 +1389,7 @@ exports[`VirtualSchema.vue > renders schema with spaces and dots 1`] = `
|
|||
symbol="false"
|
||||
/>
|
||||
<div
|
||||
class="item-count"
|
||||
class="extra-info"
|
||||
data-test-id="run-data-schema-node-item-count"
|
||||
data-v-882a318e=""
|
||||
>
|
||||
|
|
|
@ -261,7 +261,14 @@ export type RenderHeader = {
|
|||
preview?: boolean;
|
||||
};
|
||||
|
||||
type Renders = RenderHeader | RenderItem;
|
||||
export type RenderIcon = {
|
||||
id: string;
|
||||
type: 'icon';
|
||||
icon: string;
|
||||
tooltip: string;
|
||||
};
|
||||
|
||||
type Renders = RenderHeader | RenderItem | RenderIcon;
|
||||
|
||||
const icons = {
|
||||
object: 'cube',
|
||||
|
@ -285,13 +292,11 @@ const emptyItem = (): RenderItem => ({
|
|||
type: 'item',
|
||||
});
|
||||
|
||||
const dummyItem = (): RenderItem => ({
|
||||
id: `dummy-${window.crypto.randomUUID()}`,
|
||||
icon: '',
|
||||
level: 1,
|
||||
title: '...',
|
||||
type: 'item',
|
||||
preview: true,
|
||||
const moreFieldsItem = (): RenderIcon => ({
|
||||
id: `moreFields-${window.crypto.randomUUID()}`,
|
||||
type: 'icon',
|
||||
icon: 'ellipsis-h',
|
||||
tooltip: useI18n().baseText('dataMapping.schemaView.previewExtraFields'),
|
||||
});
|
||||
|
||||
const isDataEmpty = (schema: Schema) => {
|
||||
|
@ -445,7 +450,7 @@ export const useFlattenSchema = () => {
|
|||
acc.push(...flattenSchema(item));
|
||||
|
||||
if (item.preview) {
|
||||
acc.push(dummyItem());
|
||||
acc.push(moreFieldsItem());
|
||||
}
|
||||
|
||||
return acc;
|
||||
|
|
|
@ -92,6 +92,7 @@ export const BUILTIN_NODES_DOCS_URL = `https://${DOCS_DOMAIN}/integrations/built
|
|||
export const BUILTIN_CREDENTIALS_DOCS_URL = `https://${DOCS_DOMAIN}/integrations/builtin/credentials/`;
|
||||
export const DATA_PINNING_DOCS_URL = `https://${DOCS_DOMAIN}/data/data-pinning/`;
|
||||
export const DATA_EDITING_DOCS_URL = `https://${DOCS_DOMAIN}/data/data-editing/`;
|
||||
export const SCHEMA_PREVIEW_DOCS_URL = `https://${DOCS_DOMAIN}/data/schema-preview/`;
|
||||
export const MFA_DOCS_URL = `https://${DOCS_DOMAIN}/user-management/two-factor-auth/`;
|
||||
export const NPM_COMMUNITY_NODE_SEARCH_API_URL = 'https://api.npms.io/v2/';
|
||||
export const NPM_PACKAGE_DOCS_BASE_URL = 'https://www.npmjs.com/package/';
|
||||
|
|
|
@ -661,8 +661,9 @@
|
|||
"dataMapping.schemaView.emptyData": "No fields - item(s) exist, but they're empty",
|
||||
"dataMapping.schemaView.disabled": "This node is disabled and will just pass data through",
|
||||
"dataMapping.schemaView.noMatches": "No results for '{search}'",
|
||||
"dataMapping.schemaView.preview": "This is a preview of the schema, execute the node to see the exact schema and data. {link}",
|
||||
"dataMapping.schemaView.previewNode": "(schema preview)",
|
||||
"dataMapping.schemaView.preview": "Usually outputs the following fields. Execute the node to see the actual ones. {link}",
|
||||
"dataMapping.schemaView.previewExtraFields": "There may be more fields. Execute the node to be sure.",
|
||||
"dataMapping.schemaView.previewNode": "Preview",
|
||||
"displayWithChange.cancelEdit": "Cancel Edit",
|
||||
"displayWithChange.clickToChange": "Click to Change",
|
||||
"displayWithChange.setValue": "Set Value",
|
||||
|
|
Loading…
Reference in a new issue