Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(editor-ui): add mapping discoverability tooltip to mappable inputs #4227

Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
70715ae
refactor(editor-ui): move json data view into its own component
cstuncsik Sep 21, 2022
6a44fc5
fix(editor-ui): make JSON data component work again
cstuncsik Sep 21, 2022
65aff8b
fix(editor-ui): JSON data component type issues
cstuncsik Sep 21, 2022
9db6323
fix(editor-ui): JSON data component prop 'inputData'
cstuncsik Sep 21, 2022
f5db6f4
refactor(editor-ui): rename helper function
cstuncsik Sep 21, 2022
705dea6
fix(editor-ui): add declaration to `vue-json-pretty` component
cstuncsik Sep 22, 2022
0eec36e
refactor(editor-ui): JSON mapping move more logic to new component
cstuncsik Sep 22, 2022
4883a4c
refactor(editor-ui): some cleanup in JSON mapping component
cstuncsik Sep 22, 2022
349591c
refactor(editor-ui): changing key mapping translation
cstuncsik Sep 26, 2022
1cfb7a3
refactor(editor-ui): add basic drag'n'drop functionality to JSON view
cstuncsik Sep 26, 2022
762792a
refactor(editor-ui): moving JSON view actions into separate components
cstuncsik Sep 26, 2022
2215eb0
fix(editor-ui): JSON view action copy default selected path
cstuncsik Sep 26, 2022
1e0be05
fix(editor-ui): refactor draggable to play nicer with other (3rd part…
cstuncsik Sep 27, 2022
ae93900
fix(editor-ui): improve draggable performance
cstuncsik Sep 27, 2022
5226046
fix(editor-ui): add disable user selection class to body
cstuncsik Sep 27, 2022
2f8e3f1
fix(editor-ui): reduce click handler cognitive load in JSON view copy…
cstuncsik Sep 27, 2022
1e05ffc
fix(editor-ui): JSON view mapped path
cstuncsik Sep 28, 2022
97d8a6d
fix(editor-ui): remove unnecessary wrapper around RunDataTable.vue
cstuncsik Sep 28, 2022
2275d74
fix(editor-ui): respect input node distance when json parameter path …
cstuncsik Sep 28, 2022
26df8dc
fix(editor-ui): JSON mapping property highlight
cstuncsik Sep 28, 2022
aa8afd2
fix(editor-ui): block event only on mousemove for draggable to not se…
cstuncsik Sep 28, 2022
be0cbbd
refactor(editor-ui): fixing prop types and organising imports
cstuncsik Sep 28, 2022
9f83266
fix(editor-ui): JSON view use double quotes where appropriate
cstuncsik Sep 28, 2022
ed10cae
Merge branch 'n8n-4684-release-json-mapping-feature' into n8n-4668-wr…
cstuncsik Sep 28, 2022
f4b7ec5
fix(editor-ui): fix new package additions after merge conflict
cstuncsik Sep 28, 2022
52ab95e
fix(editor-ui): fix package update after merge conflict
cstuncsik Sep 28, 2022
6ac2714
fix(editor-ui): JSON view prop names text break
cstuncsik Sep 28, 2022
ebcfaf8
Merge branch 'n8n-4684-release-json-mapping-feature' into n8n-4786-ad…
cstuncsik Sep 29, 2022
3007d70
fix(editor-ui): update helper after merge conflict
cstuncsik Sep 29, 2022
ed4905c
refactor(editor-ui): cleanup RunaDataTable tooltips
cstuncsik Sep 29, 2022
569fe31
refactor(editor-ui): add temporary static tooltip to input with mapping
cstuncsik Sep 29, 2022
651c0ab
fix(editor-ui): input mapping tooltip proper input name
cstuncsik Sep 29, 2022
cd1e9d9
Merge branch 'n8n-4684-release-json-mapping-feature' into n8n-4786-ad…
cstuncsik Sep 30, 2022
bcfe9ac
Merge branch 'n8n-4684-release-json-mapping-feature' into n8n-4786-ad…
cstuncsik Sep 30, 2022
bdba9fe
fix(editor-ui): show input mapping tooltip when conditions are met
cstuncsik Sep 30, 2022
103b7fa
fix(editor-ui): show different input mapping tooltip for different vi…
cstuncsik Sep 30, 2022
2e8bdef
fix(editor-ui): drop lodash isEmpty
cstuncsik Oct 2, 2022
0e69b4f
fix(editor-ui): using and keeping only getter function
cstuncsik Oct 2, 2022
483b41f
fix(editor-ui): check `INodeExecutionData[]` array emptyness (still n…
cstuncsik Oct 3, 2022
330fe42
Merge branch 'n8n-4684-release-json-mapping-feature' into n8n-4786-ad…
cstuncsik Oct 3, 2022
ed14aa9
feat(editor-ui): add telemetry calls to data mapping (#4250)
cstuncsik Oct 4, 2022
ec8d7c7
Merge branch 'n8n-4684-release-json-mapping-feature' into n8n-4786-ad…
cstuncsik Oct 4, 2022
cad4a4c
fix(editor-ui): using a placeholder gif in mapping discoverability to…
cstuncsik Oct 5, 2022
6bc5adf
refactor(design-system): adding optional configurable buttons to tool…
cstuncsik Oct 5, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 6 additions & 1 deletion packages/editor-ui/src/Interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
IWorkflowSettings as IWorkflowSettingsWorkflow,
WorkflowExecuteMode,
PublicInstalledPackage,
IResourceLocatorResult,
INodeTypeNameVersion,
ILoadOptions,
INodeCredentials,
Expand Down Expand Up @@ -943,9 +942,15 @@ export interface IUiState {
sessionId: string;
input: {
displayMode: IRunDataDisplayMode;
data: {
isEmpty: boolean;
cstuncsik marked this conversation as resolved.
Show resolved Hide resolved
}
};
output: {
displayMode: IRunDataDisplayMode;
data: {
isEmpty: boolean;
}
editMode: {
enabled: boolean;
value: string;
Expand Down
51 changes: 36 additions & 15 deletions packages/editor-ui/src/components/ParameterInputFull.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,32 @@
@drop="onDrop"
>
<template v-slot="{ droppable, activeDrop }">
<parameter-input
ref="param"
:parameter="parameter"
:value="value"
:displayOptions="displayOptions"
:path="path"
:isReadOnly="isReadOnly"
:droppable="droppable"
:activeDrop="activeDrop"
:forceShowExpression="forceShowExpression"
@valueChanged="valueChanged"
@focus="onFocus"
@blur="onBlur"
@drop="onDrop"
inputSize="small" />
<n8n-tooltip
placement="bottom-start"
:manual="true"
:value="showMappingTooltip"
>
<div
slot="content"
v-html="$locale.baseText(`dataMapping.${displayMode}Hint`, { interpolate: { name: parameter.displayName } })"
/>
<parameter-input
ref="param"
:parameter="parameter"
:value="value"
:displayOptions="displayOptions"
:path="path"
:isReadOnly="isReadOnly"
:droppable="droppable"
:activeDrop="activeDrop"
:forceShowExpression="forceShowExpression"
@valueChanged="valueChanged"
@focus="onFocus"
@blur="onBlur"
@drop="onDrop"
inputSize="small"
/>
</n8n-tooltip>
</template>
</draggable-target>
<input-hint :class="$style.hint" :hint="$locale.nodeText().hint(parameter, path)" />
Expand All @@ -54,6 +65,7 @@ import Vue from 'vue';

import {
INodeUi,
IRunDataDisplayMode,
IUpdateInformation,
} from '@/Interface';

Expand Down Expand Up @@ -108,6 +120,15 @@ export default mixins(
showExpressionSelector (): boolean {
return this.isResourceLocator ? !hasOnlyListMode(this.parameter): true;
},
isInputDataEmpty (): boolean {
return this.$store.getters['ui/getNDVInputDataIsEmpty'];
},
displayMode(): IRunDataDisplayMode {
return this.$store.getters['ui/inputPanelDisplayMode'];
},
showMappingTooltip (): boolean {
return this.focused && !this.isInputDataEmpty && window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) !== 'true';
},
},
methods: {
onFocus() {
Expand Down
13 changes: 12 additions & 1 deletion packages/editor-ui/src/components/RunData.vue
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@
</n8n-text>
</div>

<RunDataTable
<run-data-table
v-else-if="hasNodeRun && displayMode === 'table'"
class="ph-no-capture"
:node="node"
Expand Down Expand Up @@ -322,6 +322,7 @@
import { PropType } from "vue";
import mixins from 'vue-typed-mixins';
import { saveAs } from 'file-saver';
import isEmpty from 'lodash/isEmpty';
cstuncsik marked this conversation as resolved.
Show resolved Hide resolved
import {
IBinaryData,
IBinaryKeyData,
Expand Down Expand Up @@ -1068,6 +1069,16 @@ export default mixins(
node() {
this.init();
},
inputData:{
handler(data: INodeExecutionData[]) {
if(this.paneType && data){
const isDataEmpty = data.length === 0 || data.every(isEmpty) || data.every(item => isEmpty(item.json));
this.$store.commit('ui/setNDVPanelDataIsEmpty', { panel: this.paneType, isEmpty: isDataEmpty });
cstuncsik marked this conversation as resolved.
Show resolved Hide resolved
}
},
immediate: true,
deep: true,
},
jsonData (value: IDataObject[]) {
this.refreshDataSize();

Expand Down
83 changes: 3 additions & 80 deletions packages/editor-ui/src/components/RunDataTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<th v-for="(column, i) in tableData.columns || []" :key="column">
<n8n-tooltip
placement="bottom-start"
:disabled="!mappingEnabled || showHintWithDelay"
:disabled="!mappingEnabled"
:open-delay="1000"
>
<div slot="content">
Expand Down Expand Up @@ -48,34 +48,11 @@
:class="{
[$style.header]: true,
[$style.draggableHeader]: mappingEnabled,
[$style.activeHeader]: (i === activeColumn || forceShowGrip) && mappingEnabled,
[$style.activeHeader]: i === activeColumn && mappingEnabled,
[$style.draggingHeader]: isDragging,
}"
>
<span>{{ column || '&nbsp;' }}</span>
<n8n-tooltip
v-if="mappingEnabled"
placement="bottom-start"
:manual="true"
:value="i === 0 && showHintWithDelay"
>
<div
v-if="focusedMappableInput"
slot="content"
v-html="
$locale.baseText('dataMapping.tableHint', {
interpolate: { name: focusedMappableInput },
})
"
></div>
<div v-else slot="content">
<img src='/static/data-mapping-gif.gif'/>
{{ $locale.baseText('dataMapping.dragColumnToFieldHint') }}
</div>
<div :class="$style.dragButton">
<font-awesome-icon icon="grip-vertical" />
</div>
</n8n-tooltip>
</div>
</template>
</draggable>
Expand Down Expand Up @@ -158,15 +135,14 @@

import Vue, { PropType } from 'vue';
import mixins from 'vue-typed-mixins';
import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants';
import { INodeUi, ITableData } from '@/Interface';
import { GenericValue, IDataObject, INodeExecutionData } from 'n8n-workflow';
import Draggable from './Draggable.vue';
import { shorten } from './helpers';
import { externalHooks } from './mixins/externalHooks';

export default mixins(externalHooks).extend({
name: 'RunDataTable',
name: 'run-data-table',
components: { Draggable },
props: {
node: {
Expand All @@ -181,9 +157,6 @@ export default mixins(externalHooks).extend({
distanceFromActive: {
type: Number,
},
showMappingHint: {
type: Boolean,
},
runIndex: {
type: Number,
},
Expand All @@ -194,30 +167,13 @@ export default mixins(externalHooks).extend({
data() {
return {
activeColumn: -1,
showHintWithDelay: false,
forceShowGrip: false,
draggedColumn: false,
draggingPath: null as null | string,
hoveringPath: null as null | string,
mappingHintVisible: false,
};
},
mounted() {
if (this.showMappingHint) {
this.mappingHintVisible = true;

setTimeout(() => {
this.mappingHintVisible = false;
}, 6000);
}

if (this.showMappingHint && this.showHint) {
setTimeout(() => {
this.showHintWithDelay = this.showHint;
this.$telemetry.track('User viewed data mapping tooltip', { type: 'param focus' });
}, 500);
}

if (this.tableData && this.tableData.columns && this.$refs.draggable) {
const tbody = (this.$refs.draggable as Vue).$refs.wrapper as HTMLElement;
if (tbody) {
Expand All @@ -231,17 +187,6 @@ export default mixins(externalHooks).extend({
tableData(): ITableData {
return this.convertToTable(this.inputData);
},
focusedMappableInput(): string {
return this.$store.getters['ui/focusedMappableInput'];
},
showHint(): boolean {
return (
!this.draggedColumn &&
((this.showMappingHint && this.mappingHintVisible) ||
(!!this.focusedMappableInput &&
window.localStorage.getItem(LOCAL_STORAGE_MAPPING_FLAG) !== 'true'))
);
},
},
methods: {
shorten,
Expand Down Expand Up @@ -459,28 +404,6 @@ export default mixins(externalHooks).extend({
};
},
},
watch: {
focusedMappableInput(curr: boolean) {
setTimeout(
() => {
this.forceShowGrip = !!this.focusedMappableInput;
},
curr ? 300 : 150,
);
},
showHint(curr: boolean, prev: boolean) {
if (curr) {
setTimeout(() => {
this.showHintWithDelay = this.showHint;
if (this.showHintWithDelay) {
this.$telemetry.track('User viewed data mapping tooltip', { type: 'param focus' });
}
}, 1000);
} else {
this.showHintWithDelay = false;
}
},
},
});
</script>

Expand Down
12 changes: 12 additions & 0 deletions packages/editor-ui/src/modules/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,15 @@ const module: Module<IUiState, IRootState> = {
sessionId: '',
input: {
displayMode: 'table',
data: {
isEmpty: true,
},
},
output: {
displayMode: 'table',
data: {
isEmpty: true,
},
editMode: {
enabled: false,
value: '',
Expand Down Expand Up @@ -224,6 +230,9 @@ const module: Module<IUiState, IRootState> = {
mappingTelemetry: (state: IUiState) => state.ndv.mappingTelemetry,
getCurrentView: (state: IUiState) => state.currentView,
isNodeView: (state: IUiState) => [VIEWS.NEW_WORKFLOW.toString(), VIEWS.WORKFLOW.toString(), VIEWS.EXECUTION.toString()].includes(state.currentView),
getNDVDataIsEmpty: (state: IUiState) => (panel: 'input' | 'output'): boolean => state.ndv[panel].data.isEmpty,
cstuncsik marked this conversation as resolved.
Show resolved Hide resolved
getNDVInputDataIsEmpty: (state: IUiState) => state.ndv.input.data.isEmpty,
getNDVOutputDataIsEmpty: (state: IUiState) => state.ndv.output.data.isEmpty,
cstuncsik marked this conversation as resolved.
Show resolved Hide resolved
},
mutations: {
setMainPanelDimensions: (state: IUiState, params: { panelType:string, dimensions: { relativeLeft?: number, relativeRight?: number, relativeWidth?: number }}) => {
Expand Down Expand Up @@ -330,6 +339,9 @@ const module: Module<IUiState, IRootState> = {
resetMappingTelemetry(state: IUiState) {
state.ndv.mappingTelemetry = {};
},
setNDVPanelDataIsEmpty(state: IUiState, payload: {panel: 'input' | 'output', isEmpty: boolean}) {
Vue.set(state.ndv[payload.panel].data, 'isEmpty', payload.isEmpty);
},
},
actions: {
openModal: async (context: ActionContext<IUiState, IRootState>, modalKey: string) => {
Expand Down
1 change: 1 addition & 0 deletions packages/editor-ui/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@
"dataMapping.success.title": "You just mapped some data!",
"dataMapping.success.moreInfo": "Check out our <a href=\"https://docs.n8n.io/data/data-mapping\" target=\"_blank\">docs</a> for more details on mapping data in n8n",
"dataMapping.tableHint": "<img src='/static/data-mapping-gif.gif'/> Drag a column onto <b>{name}</b> to map it",
"dataMapping.jsonHint": "<img src='/static/json-mapping-gif.gif'/> Drag a JSON key onto <b>{name}</b> to map data",
"dataMapping.mapKeyToField": "Map '{name}' to a field",
"dataMapping.mapAllKeysToField": "Map every '{name}' to a field",
"displayWithChange.cancelEdit": "Cancel Edit",
Expand Down