mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(editor): Inline expression editor (#4814)
* WIP * 🔥 Remove unneeded watch * ⚡ Further setup * ⚡ Fix import * ⚡ Minor tweaks * 🔥 Remove logging * 🎨 Add some styling * 🎨 More styling changes * 🐛 Fix wrong marking of stale data * 🎨 Prevent fx on dragging * 🔥 Remove logging * ⚡ Refine draggable target offsets * refactor(editor): Consolidate expression management logic (#4836) * ⚡ Extract `ExpressionFunctionIcon` * ⚡ Simplify syntax * ⚡ Move to mixin * 🎨 Format * 📘 Unify types * ⚡ Dedup double brace handler * ⚡ Consolidate resolvable highlighter * 🎨 Format * ⚡ Consolidate language pack * ✏️ Add comment * ⚡ Move completions to plugins * ⚡ Partially deduplicate themes * refactor(editor): Apply styling feedback to inline expression editor (#4846) * 🎨 Adjust styling for expression parameter input * 🎨 Style outputs differently * ⚡ Set single line for RLC * 🎨 Style both openers identically * 🐛 Prevent defocus on resize * ⚡ Adjust line height * 🎨 Adjust border with for expression input * ⚡ Fix font family for inline output * ⚡ Set up telemetry * ⚡ Complete telemetry * ⚡ Simplify event source * ⚡ Set monospaced font for inline output * 🎨 Hide cursor on schema pill drop * 🧪 Update snapshots * ⚡ Consolidate editor styles * ✏️ Add tech debt comments * ⚡ Improve naming * ⚡ Improve inside resolvable detection * ⚡ Improve var naming * 🔥 Remove outdated comment * 🚚 Move constant to data * ✏️ Clarify comments * 🔥 Remove outdated comments * 🔥 Remove unneeded try-catch * 🔥 Remove unneeded method * 🔥 Remove unneeded check * 🔥 Remove `openExpression` check * 🔥 Remove unused timeout * 🔥 Remove commented out sections * ⚡ Use Pinia naming convention * ⚡ Re-evaluate on change of `ndvInputData` * 🐛 Fix handling of `0` in number-type input * 🐛 Surface focus and blur for mapping hints * 🔥 Remove logging * ✏️ Reword error * ⚡ Change kebab-case to PascalCase * ⚡ Refactor state fields for clarity * ⚡ Support double bracing on selection * 🎨 More styling * ⚡ Miscellaneous cleanup * ⚡ Disregard error on drop * 🎨 Fix schema pill styling * 🎨 More `background` to `background-color` fixes * 🧪 Update snapshots * 🎨 Replace non-existing var with white * 🧪 Update snapshot * 📦 Integrate `codemirror-lang-n8n-expression` * 🎨 Fix formatting * 🧪 Re-update test snapshots * 🧪 Update selectors for inline editor * 🔥 Remove unused test ID * 📘 Add type for `currentNodePaneType` * ⚡ Refactor mixin to util * ⚡ Use `:global` * 🔥 Remove comment * ⚡ Add watch * ⚡ Change import style * 👕 Fix lint * ⚡ Refactor preventing blur on resize * 🔥 Remove comment * 🧪 Re-update snapshots * 🎨 Prettify * 👕 Fix lint * 🔥 Remove comment Co-authored-by: Mutasem <mutdmour@gmail.com>
This commit is contained in:
@@ -12,11 +12,7 @@
|
||||
@closeDialog="closeExpressionEditDialog"
|
||||
@valueChanged="expressionUpdated"
|
||||
></expression-edit>
|
||||
<div
|
||||
class="parameter-input ignore-key-press"
|
||||
:style="parameterInputWrapperStyle"
|
||||
@click="openExpressionEdit"
|
||||
>
|
||||
<div class="parameter-input ignore-key-press" :style="parameterInputWrapperStyle">
|
||||
<resource-locator
|
||||
v-if="isResourceLocatorParameter"
|
||||
ref="resourceLocator"
|
||||
@@ -32,19 +28,21 @@
|
||||
:node="node"
|
||||
:path="path"
|
||||
@input="valueChanged"
|
||||
@modalOpenerClick="openExpressionEditorModal"
|
||||
@focus="setFocus"
|
||||
@blur="onBlur"
|
||||
@drop="onResourceLocatorDrop"
|
||||
/>
|
||||
<n8n-input
|
||||
v-else-if="isValueExpression || droppable || forceShowExpression"
|
||||
:size="inputSize"
|
||||
:type="getStringInputType"
|
||||
:rows="getArgument('rows')"
|
||||
<ExpressionParameterInput
|
||||
v-else-if="isValueExpression || forceShowExpression"
|
||||
:value="expressionDisplayValue"
|
||||
:title="displayTitle"
|
||||
:readOnly="isReadOnly"
|
||||
@keydown.stop
|
||||
:isReadOnly="isReadOnly"
|
||||
@valueChanged="expressionUpdated"
|
||||
@modalOpenerClick="openExpressionEditorModal"
|
||||
@focus="setFocus"
|
||||
@blur="onBlur"
|
||||
ref="inputField"
|
||||
/>
|
||||
<div
|
||||
v-else-if="
|
||||
@@ -99,6 +97,7 @@
|
||||
v-else
|
||||
v-model="tempValue"
|
||||
ref="inputField"
|
||||
class="input-with-opener"
|
||||
:size="inputSize"
|
||||
:type="getStringInputType"
|
||||
:rows="getArgument('rows')"
|
||||
@@ -113,15 +112,19 @@
|
||||
:placeholder="getPlaceholder()"
|
||||
>
|
||||
<template #suffix>
|
||||
<div class="expand-input-icon-container">
|
||||
<font-awesome-icon
|
||||
v-if="!isReadOnly"
|
||||
icon="expand-alt"
|
||||
class="edit-window-button clickable"
|
||||
:title="$locale.baseText('parameterInput.openEditWindow')"
|
||||
@click="displayEditDialog()"
|
||||
/>
|
||||
</div>
|
||||
<n8n-icon
|
||||
v-if="!isReadOnly"
|
||||
icon="external-link-alt"
|
||||
size="xsmall"
|
||||
class="edit-window-button textarea-modal-opener"
|
||||
:class="{
|
||||
focused: isFocused,
|
||||
invalid: !isFocused && getIssues.length > 0 && !isValueExpression,
|
||||
}"
|
||||
:title="$locale.baseText('parameterInput.openEditWindow')"
|
||||
@click="displayEditDialog()"
|
||||
@focus="setFocus"
|
||||
/>
|
||||
</template>
|
||||
</n8n-input>
|
||||
</div>
|
||||
@@ -329,6 +332,7 @@ import ScopesNotice from '@/components/ScopesNotice.vue';
|
||||
import ParameterOptions from '@/components/ParameterOptions.vue';
|
||||
import ParameterIssues from '@/components/ParameterIssues.vue';
|
||||
import ResourceLocator from '@/components/ResourceLocator/ResourceLocator.vue';
|
||||
import ExpressionParameterInput from '@/components/ExpressionParameterInput.vue';
|
||||
// @ts-ignore
|
||||
import PrismEditor from 'vue-prism-editor';
|
||||
import TextEdit from '@/components/TextEdit.vue';
|
||||
@@ -362,6 +366,7 @@ export default mixins(
|
||||
CodeEdit,
|
||||
CodeNodeEditor,
|
||||
ExpressionEdit,
|
||||
ExpressionParameterInput,
|
||||
NodeCredentials,
|
||||
CredentialsSelect,
|
||||
PrismEditor,
|
||||
@@ -464,6 +469,7 @@ export default mixins(
|
||||
},
|
||||
],
|
||||
},
|
||||
isFocused: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@@ -718,10 +724,12 @@ export default mixins(
|
||||
classes['parameter-value-container'] = true;
|
||||
}
|
||||
|
||||
if (this.isValueExpression || this.forceShowExpression) {
|
||||
classes['expression'] = true;
|
||||
}
|
||||
if (!this.droppable && !this.activeDrop && (this.getIssues.length || this.errorHighlight)) {
|
||||
if (
|
||||
!this.droppable &&
|
||||
!this.activeDrop &&
|
||||
(this.getIssues.length > 0 || this.errorHighlight) &&
|
||||
!this.isValueExpression
|
||||
) {
|
||||
classes['has-issues'] = true;
|
||||
}
|
||||
|
||||
@@ -890,26 +898,20 @@ export default mixins(
|
||||
: value;
|
||||
this.valueChanged(val);
|
||||
},
|
||||
openExpressionEdit() {
|
||||
if (this.isValueExpression) {
|
||||
this.expressionEditDialogVisible = true;
|
||||
this.trackExpressionEditOpen();
|
||||
return;
|
||||
}
|
||||
openExpressionEditorModal() {
|
||||
if (!this.isValueExpression) return;
|
||||
|
||||
this.expressionEditDialogVisible = true;
|
||||
this.trackExpressionEditOpen();
|
||||
},
|
||||
onBlur() {
|
||||
this.$emit('blur');
|
||||
this.isFocused = false;
|
||||
},
|
||||
onResourceLocatorDrop(data: string) {
|
||||
this.$emit('drop', data);
|
||||
},
|
||||
setFocus() {
|
||||
if (this.isValueExpression) {
|
||||
this.expressionEditDialogVisible = true;
|
||||
this.trackExpressionEditOpen();
|
||||
return;
|
||||
}
|
||||
|
||||
if (['json'].includes(this.parameter.type) && this.getArgument('alwaysOpenEditWindow')) {
|
||||
this.displayEditDialog();
|
||||
return;
|
||||
@@ -931,6 +933,7 @@ export default mixins(
|
||||
if (this.$refs.inputField && this.$refs.inputField.$el) {
|
||||
// @ts-ignore
|
||||
this.$refs.inputField.focus();
|
||||
this.isFocused = true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1014,8 +1017,6 @@ export default mixins(
|
||||
|
||||
if (command === 'resetValue') {
|
||||
this.valueChanged(this.parameter.default);
|
||||
} else if (command === 'openExpression') {
|
||||
this.expressionEditDialogVisible = true;
|
||||
} else if (command === 'addExpression') {
|
||||
if (this.isResourceLocatorParameter) {
|
||||
if (isResourceLocatorValue(this.value)) {
|
||||
@@ -1023,19 +1024,23 @@ export default mixins(
|
||||
} else {
|
||||
this.valueChanged({ __rl: true, value: `=${this.value}`, mode: '' });
|
||||
}
|
||||
} else if (
|
||||
this.parameter.type === 'number' &&
|
||||
(!this.value || this.value === '[Object: null]')
|
||||
) {
|
||||
this.valueChanged('={{ 0 }}');
|
||||
} else if (this.parameter.type === 'number' || this.parameter.type === 'boolean') {
|
||||
this.valueChanged(`={{${this.value}}}`);
|
||||
this.valueChanged(`={{ ${this.value} }}`);
|
||||
} else {
|
||||
this.valueChanged(`=${this.value}`);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.expressionEditDialogVisible = true;
|
||||
this.trackExpressionEditOpen();
|
||||
}, 375);
|
||||
this.setFocus();
|
||||
} else if (command === 'removeExpression') {
|
||||
let value: NodeParameterValueType = this.expressionEvaluated;
|
||||
|
||||
this.isFocused = false;
|
||||
|
||||
if (this.parameter.type === 'multiOptions' && typeof value === 'string') {
|
||||
value = (value || '')
|
||||
.split(',')
|
||||
@@ -1201,24 +1206,13 @@ export default mixins(
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.expression {
|
||||
textarea,
|
||||
input {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
--input-border-color: var(--color-secondary-tint-1);
|
||||
--input-background-color: var(--color-secondary-tint-3);
|
||||
--input-font-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.droppable {
|
||||
--input-border-color: var(--color-secondary);
|
||||
--input-background-color: var(--color-foreground-xlight);
|
||||
--input-border-style: dashed;
|
||||
|
||||
textarea,
|
||||
input {
|
||||
input,
|
||||
.cm-editor {
|
||||
border-width: 1.5px;
|
||||
}
|
||||
}
|
||||
@@ -1276,4 +1270,39 @@ export default mixins(
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.input-with-opener > .el-input__suffix {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.textarea-modal-opener {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: white;
|
||||
padding: 3px;
|
||||
line-height: 9px;
|
||||
border: var(--border-base);
|
||||
border-top-left-radius: var(--border-radius-base);
|
||||
border-bottom-right-radius: var(--border-radius-base);
|
||||
cursor: pointer;
|
||||
|
||||
svg {
|
||||
width: 9px !important;
|
||||
height: 9px;
|
||||
transform: rotate(270deg);
|
||||
|
||||
&:hover {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.focused {
|
||||
border-color: var(--color-secondary);
|
||||
}
|
||||
|
||||
.invalid {
|
||||
border-color: var(--color-danger);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user