mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
feat: replace function node code editor with monaco
This commit is contained in:
parent
37930057d8
commit
c63f365a65
|
@ -27,6 +27,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/open-sans": "^4.5.0",
|
"@fontsource/open-sans": "^4.5.0",
|
||||||
"n8n-design-system": "~0.5.0",
|
"n8n-design-system": "~0.5.0",
|
||||||
|
"monaco-editor": "^0.29.1",
|
||||||
"timeago.js": "^4.0.2",
|
"timeago.js": "^4.0.2",
|
||||||
"v-click-outside": "^3.1.2",
|
"v-click-outside": "^3.1.2",
|
||||||
"vue-fragment": "^1.5.2"
|
"vue-fragment": "^1.5.2"
|
||||||
|
@ -72,11 +73,12 @@
|
||||||
"lodash.get": "^4.4.2",
|
"lodash.get": "^4.4.2",
|
||||||
"lodash.set": "^4.3.2",
|
"lodash.set": "^4.3.2",
|
||||||
"n8n-workflow": "~0.73.0",
|
"n8n-workflow": "~0.73.0",
|
||||||
"sass": "^1.26.5",
|
"monaco-editor-webpack-plugin": "^5.0.0",
|
||||||
"normalize-wheel": "^1.0.1",
|
"normalize-wheel": "^1.0.1",
|
||||||
"prismjs": "^1.17.1",
|
"prismjs": "^1.17.1",
|
||||||
"quill": "^2.0.0-dev.3",
|
"quill": "^2.0.0-dev.3",
|
||||||
"quill-autoformat": "^0.1.1",
|
"quill-autoformat": "^0.1.1",
|
||||||
|
"sass": "^1.26.5",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "^8.0.2",
|
||||||
"string-template-parser": "^1.2.6",
|
"string-template-parser": "^1.2.6",
|
||||||
"ts-jest": "^26.3.0",
|
"ts-jest": "^26.3.0",
|
||||||
|
|
|
@ -1,61 +1,107 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="dialogVisible">
|
<el-dialog
|
||||||
<el-dialog :visible="dialogVisible" append-to-body :close-on-click-modal="false" width="80%" :title="`Edit ${parameter.displayName}`" :before-close="closeDialog">
|
visible
|
||||||
<div class="text-editor-wrapper ignore-key-press">
|
append-to-body
|
||||||
<div class="editor-description">
|
:close-on-click-modal="false"
|
||||||
{{parameter.displayName}}:
|
width="80%"
|
||||||
</div>
|
:title="`Edit ${parameter.displayName}`"
|
||||||
<div class="text-editor" @keydown.stop>
|
:before-close="closeDialog"
|
||||||
<prism-editor :lineNumbers="true" :code="value" :readonly="isReadOnly" @change="valueChanged" language="js"></prism-editor>
|
>
|
||||||
</div>
|
<div class="text-editor-wrapper ignore-key-press">
|
||||||
</div>
|
<div ref="code" class="text-editor" @keydown.stop></div>
|
||||||
</el-dialog>
|
</div>
|
||||||
</div>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import PrismEditor from 'vue-prism-editor';
|
// import PrismEditor from 'vue-prism-editor';
|
||||||
|
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||||
|
|
||||||
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||||
|
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
|
import { IExecutionResponse } from '@/Interface';
|
||||||
|
import { INodeExecutionData } from 'n8n-workflow';
|
||||||
|
|
||||||
export default mixins(
|
export default mixins(genericHelpers).extend({
|
||||||
genericHelpers,
|
name: 'CodeEdit',
|
||||||
)
|
props: ['dialogVisible', 'parameter', 'value'],
|
||||||
.extend({
|
data() {
|
||||||
name: 'CodeEdit',
|
return {
|
||||||
props: [
|
monacoInstance: null as monaco.editor.IStandaloneCodeEditor | null,
|
||||||
'dialogVisible',
|
monacoLibrary: null as monaco.IDisposable | null,
|
||||||
'parameter',
|
};
|
||||||
'value',
|
},
|
||||||
],
|
mounted() {
|
||||||
components: {
|
setTimeout(this.loadEditor);
|
||||||
PrismEditor,
|
},
|
||||||
|
destroyed() {
|
||||||
|
this.monacoLibrary!.dispose();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
closeDialog() {
|
||||||
|
// Handle the close externally as the visible parameter is an external prop
|
||||||
|
// and is so not allowed to be changed here.
|
||||||
|
this.$emit('closeDialog');
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
valueChanged (value: string) {
|
|
||||||
this.$emit('valueChanged', value);
|
|
||||||
},
|
|
||||||
|
|
||||||
closeDialog () {
|
loadEditor() {
|
||||||
// Handle the close externally as the visible parameter is an external prop
|
if (!this.$refs.code) return;
|
||||||
// and is so not allowed to be changed here.
|
|
||||||
this.$emit('closeDialog');
|
this.monacoInstance = monaco.editor.create(this.$refs.code as HTMLElement, {
|
||||||
return false;
|
value: this.value,
|
||||||
},
|
language: 'javascript',
|
||||||
|
tabSize: 2,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.monacoInstance.onDidChangeModelContent((ev) => {
|
||||||
|
if (this.monacoInstance) {
|
||||||
|
const model = this.monacoInstance.getModel();
|
||||||
|
if (model) {
|
||||||
|
this.$emit('valueChanged', model.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.loadAutocompleteData();
|
||||||
},
|
},
|
||||||
});
|
|
||||||
|
loadAutocompleteData(): void {
|
||||||
|
const executedWorkflow: IExecutionResponse | null = this.$store.getters.getWorkflowExecution;
|
||||||
|
|
||||||
|
let autocompleteData: INodeExecutionData[] = [{ json: { myNewField: 2 } }];
|
||||||
|
|
||||||
|
if (executedWorkflow) {
|
||||||
|
const lastNodeExecuted = executedWorkflow.data.resultData.lastNodeExecuted;
|
||||||
|
|
||||||
|
if (lastNodeExecuted) {
|
||||||
|
const data = executedWorkflow.data.resultData.runData[lastNodeExecuted];
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
autocompleteData = data[0].data!.main[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.monacoLibrary = monaco.languages.typescript.javascriptDefaults.addExtraLib(
|
||||||
|
[
|
||||||
|
`/**\n\`\`\`\nconst items = ${JSON.stringify(autocompleteData, null, 2)}\n\`\`\`\n*/`,
|
||||||
|
`const items = ${JSON.stringify(autocompleteData)}`,
|
||||||
|
].join('\n'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.editor-description {
|
.editor-description {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
padding: 0 0 0.5em 0.2em;;
|
padding: 0 0 0.5em 0.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-editor {
|
||||||
|
min-height: 30rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div v-else-if="['json', 'string'].includes(parameter.type) || remoteParameterOptionsLoadingIssues !== null">
|
<div v-else-if="['json', 'string'].includes(parameter.type) || remoteParameterOptionsLoadingIssues !== null">
|
||||||
<code-edit :dialogVisible="codeEditDialogVisible" :value="value" :parameter="parameter" @closeDialog="closeCodeEditDialog" @valueChanged="expressionUpdated"></code-edit>
|
<code-edit v-if="codeEditDialogVisible" :value="value" :parameter="parameter" @closeDialog="closeCodeEditDialog" @valueChanged="expressionUpdated"></code-edit>
|
||||||
<text-edit :dialogVisible="textEditDialogVisible" :value="value" :parameter="parameter" @closeDialog="closeTextEditDialog" @valueChanged="expressionUpdated"></text-edit>
|
<text-edit :dialogVisible="textEditDialogVisible" :value="value" :parameter="parameter" @closeDialog="closeTextEditDialog" @valueChanged="expressionUpdated"></text-edit>
|
||||||
|
|
||||||
<div v-if="isEditor === true" class="clickable" @click="displayEditDialog()">
|
<div v-if="isEditor === true" class="clickable" @click="displayEditDialog()">
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
chainWebpack: config => config.resolve.symlinks(false),
|
chainWebpack: config => config.resolve.symlinks(false),
|
||||||
// transpileDependencies: [
|
// transpileDependencies: [
|
||||||
|
@ -13,6 +15,9 @@ module.exports = {
|
||||||
devServer: {
|
devServer: {
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new MonacoWebpackPlugin(),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
loaderOptions: {
|
loaderOptions: {
|
||||||
|
|
Loading…
Reference in a new issue