Skip to content

Commit 3ac2249

Browse files
committed
migrate to ACE
1 parent af61c92 commit 3ac2249

File tree

26 files changed

+227
-136
lines changed

26 files changed

+227
-136
lines changed

frontend/public/index.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,13 @@
1010
<link rel="stylesheet" href="https://unpkg.com/prismjs@1.29.0/themes/prism.css"/>
1111
<link rel="stylesheet" href="tw.css">
1212
<link rel="stylesheet" href="vanillatoasts/vanillatoasts.css">
13-
<link rel="stylesheet" href="https://unpkg.com/codemirror@5.65.16/lib/codemirror.css">
1413
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>
1514
<link rel="icon" href="images/logo.svg" type="image/svg+xml">
1615
<script src="./config.js"></script>
1716
<script src="https://unpkg.com/vue@3.x"></script>
1817
<script src="https://unpkg.com/vue-router@4.0.10"></script>
1918
<script src="https://unpkg.com/chart.js@4.2.0/dist/chart.umd.js"></script>
2019
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
21-
<script src="https://unpkg.com/codemirror@5.65.16/lib/codemirror.js"></script>
22-
<script src="https://unpkg.com/codemirror@5.65.16/mode/javascript/javascript.js"></script>
2320
</head>
2421

2522
<body>

frontend/src/aceEditor.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
'use strict';
2+
3+
const ace = require('ace-builds');
4+
require('ace-builds/src-noconflict/mode-javascript');
5+
require('ace-builds/src-noconflict/mode-json');
6+
require('ace-builds/src-noconflict/theme-chrome');
7+
8+
/**
9+
* Create an Ace editor on a container element (div). The container must have
10+
* explicit dimensions (e.g. height/min-height and width).
11+
* @param {HTMLElement} container - A div element to attach the editor to
12+
* @param {Object} options - { value: string, mode: 'javascript'|'json', lineNumbers: boolean, ... }
13+
* @returns {ace.Ace.Editor} The Ace editor instance
14+
*/
15+
function createAceEditor(container, options = {}) {
16+
const {
17+
value = '',
18+
mode = 'javascript',
19+
lineNumbers = true,
20+
minLines,
21+
maxLines,
22+
readOnly = false,
23+
wrap = false
24+
} = options;
25+
26+
const editor = ace.edit(container);
27+
editor.setTheme('ace/theme/chrome');
28+
editor.session.setMode(mode === 'json' ? 'ace/mode/json' : 'ace/mode/javascript');
29+
editor.setValue(value, -1);
30+
editor.setOptions({
31+
showLineNumbers: lineNumbers,
32+
readOnly,
33+
wrap
34+
});
35+
if (minLines != null) editor.setOption('minLines', minLines);
36+
if (maxLines != null) editor.setOption('maxLines', maxLines);
37+
38+
return editor;
39+
}
40+
41+
/**
42+
* Destroy an Ace editor and release resources.
43+
* @param {ace.Ace.Editor|null} editor - The editor instance from createAceEditor
44+
*/
45+
function destroyAceEditor(editor) {
46+
if (editor) {
47+
editor.destroy();
48+
}
49+
}
50+
51+
module.exports = { createAceEditor, destroyAceEditor };

frontend/src/chat/chat-message-script/chat-message-script.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
<div class="p-0 max-h-[50vh] max-w-[calc(100vw-4rem)] lg:max-w-[calc(100vw-20rem)] overflow-y-auto" v-show="activeTab === 'code'">
8686
<div v-if="isEditing" class="flex flex-col space-y-2">
8787
<div class="border border-gray-200">
88-
<textarea ref="scriptEditor" class="w-full h-[45vh]" @input="handleScriptInput"></textarea>
88+
<div ref="scriptEditor" class="w-full h-[45vh] min-h-[200px]"></div>
8989
</div>
9090
<div class="flex justify-end gap-2 pb-2">
9191
<button
@@ -143,7 +143,7 @@
143143
<div class="my-4">
144144
<label class="block text-sm font-medium leading-6 text-gray-900">Code</label>
145145
<div class="border border-gray-200">
146-
<textarea class="p-2 h-[300px] w-full" ref="dashboardCodeEditor"></textarea>
146+
<div class="h-[300px] w-full" ref="dashboardCodeEditor"></div>
147147
</div>
148148
</div>
149149
<async-button

frontend/src/chat/chat-message-script/chat-message-script.js

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
/* global CodeMirror, Prism */
1+
/* global Prism */
22
'use strict';
33

44
const api = require('../../api');
55
const template = require('./chat-message-script.html');
6+
const { createAceEditor, destroyAceEditor } = require('../../aceEditor');
67

78
module.exports = app => app.component('chat-message-script', {
89
template,
@@ -68,16 +69,20 @@ module.exports = app => app.component('chat-message-script', {
6869
this.showCreateDashboardModal = true;
6970
this.$nextTick(() => {
7071
if (this.dashboardEditor) {
71-
this.dashboardEditor.toTextArea();
72+
destroyAceEditor(this.dashboardEditor);
73+
this.dashboardEditor = null;
74+
}
75+
const container = this.$refs.dashboardCodeEditor;
76+
if (container) {
77+
this.dashboardEditor = createAceEditor(container, {
78+
value: this.dashboardCode,
79+
mode: 'javascript',
80+
lineNumbers: true
81+
});
82+
this.dashboardEditor.session.on('change', () => {
83+
this.dashboardCode = this.dashboardEditor.getValue();
84+
});
7285
}
73-
this.$refs.dashboardCodeEditor.value = this.dashboardCode;
74-
this.dashboardEditor = CodeMirror.fromTextArea(this.$refs.dashboardCodeEditor, {
75-
mode: 'javascript',
76-
lineNumbers: true
77-
});
78-
this.dashboardEditor.on('change', () => {
79-
this.dashboardCode = this.dashboardEditor.getValue();
80-
});
8186
});
8287
},
8388
openOverwriteDashboardConfirmation() {
@@ -95,35 +100,33 @@ module.exports = app => app.component('chat-message-script', {
95100
this.isEditing = true;
96101
this.editedScript = this.script;
97102
this.$nextTick(() => {
98-
if (!this.$refs.scriptEditor) {
99-
return;
100-
}
101-
this.$refs.scriptEditor.value = this.editedScript;
102-
if (typeof CodeMirror === 'undefined') {
103-
return;
104-
}
105-
this.destroyCodeMirror();
106-
this.codeEditor = CodeMirror.fromTextArea(this.$refs.scriptEditor, {
103+
const container = this.$refs.scriptEditor;
104+
if (!container) return;
105+
this.destroyAceEditor();
106+
this.codeEditor = createAceEditor(container, {
107+
value: this.editedScript,
107108
mode: 'javascript',
108-
lineNumbers: true,
109-
smartIndent: false
109+
lineNumbers: true
110+
});
111+
this.codeEditor.session.on('change', () => {
112+
this.editedScript = this.codeEditor.getValue();
110113
});
111114
});
112115
},
113116
cancelEditing() {
114117
this.isEditing = false;
115-
this.destroyCodeMirror();
118+
this.destroyAceEditor();
116119
this.editedScript = this.script;
117120
this.highlightCode();
118121
},
119122
finishEditing() {
120123
this.isEditing = false;
121-
this.destroyCodeMirror();
124+
this.destroyAceEditor();
122125
this.highlightCode();
123126
},
124-
destroyCodeMirror() {
127+
destroyAceEditor() {
125128
if (this.codeEditor) {
126-
this.codeEditor.toTextArea();
129+
destroyAceEditor(this.codeEditor);
127130
this.codeEditor = null;
128131
}
129132
},
@@ -211,7 +214,7 @@ module.exports = app => app.component('chat-message-script', {
211214
watch: {
212215
showCreateDashboardModal(val) {
213216
if (!val && this.dashboardEditor) {
214-
this.dashboardEditor.toTextArea();
217+
destroyAceEditor(this.dashboardEditor);
215218
this.dashboardEditor = null;
216219
}
217220
},
@@ -232,7 +235,7 @@ module.exports = app => app.component('chat-message-script', {
232235
}
233236
},
234237
unmounted() {
235-
this.destroyCodeMirror();
238+
this.destroyAceEditor();
236239
document.body.removeEventListener('click', this.handleBodyClick);
237240
}
238241
});

frontend/src/clone-document/clone-document.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div>
22
<div class="mb-2">
3-
<textarea class="border border-gray-200 p-2 h-[300px] w-full" ref="codeEditor"></textarea>
3+
<div class="border border-gray-200 h-[300px] w-full" ref="codeEditor"></div>
44
</div>
55
<button @click="cloneDocument()" class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Submit</button>
66
<div v-if="errors.length > 0" class="rounded-md bg-red-50 p-4 mt-1">

frontend/src/clone-document/clone-document.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const appendCSS = require('../appendCSS');
1515
appendCSS(require('./clone-document.css'));
1616

1717
const template = require('./clone-document.html');
18+
const { createAceEditor, destroyAceEditor } = require('../aceEditor');
1819

1920
module.exports = app => app.component('clone-document', {
2021
props: ['currentModel', 'doc', 'schemaPaths'],
@@ -64,11 +65,19 @@ module.exports = app => app.component('clone-document', {
6465
}
6566

6667
this.documentData = JSON.stringify(filteredDoc, null, 2);
67-
this.$refs.codeEditor.value = this.documentData;
68-
this.editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
68+
const container = this.$refs.codeEditor;
69+
this.editor = createAceEditor(container, {
70+
value: this.documentData,
6971
mode: 'javascript',
70-
lineNumbers: true,
71-
smartIndent: false
72+
lineNumbers: true
7273
});
74+
this.editor.session.on('change', () => {
75+
this.documentData = this.editor.getValue();
76+
});
77+
},
78+
beforeDestroy() {
79+
if (this.editor) {
80+
destroyAceEditor(this.editor);
81+
}
7382
}
7483
});

frontend/src/create-dashboard/create-dashboard.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<div class="my-4">
1414
<label class="block text-sm font-medium leading-6 text-gray-900">Code</label>
1515
<div class="border border-gray-200">
16-
<textarea class="p-2 h-[300px] w-full" ref="codeEditor"></textarea>
16+
<div class="h-[300px] w-full" ref="codeEditor"></div>
1717
</div>
1818
</div>
1919
<async-button

frontend/src/create-dashboard/create-dashboard.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
const api = require('../api');
44

55
const template = require('./create-dashboard.html');
6+
const { createAceEditor, destroyAceEditor } = require('../aceEditor');
67

78
module.exports = app => app.component('create-dashboard', {
89
template,
@@ -33,9 +34,19 @@ module.exports = app => app.component('create-dashboard', {
3334
}
3435
},
3536
mounted: function() {
36-
this._editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
37+
const container = this.$refs.codeEditor;
38+
this._editor = createAceEditor(container, {
39+
value: this.code || '',
3740
mode: 'javascript',
3841
lineNumbers: true
3942
});
43+
this._editor.session.on('change', () => {
44+
this.code = this._editor.getValue();
45+
});
46+
},
47+
beforeDestroy() {
48+
if (this._editor) {
49+
destroyAceEditor(this._editor);
50+
}
4051
}
4152
});

frontend/src/create-document/create-document.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
</div>
3636
<div class="mb-2">
3737
<label class="block text-sm font-bold text-gray-900">Document to Create</label>
38-
<textarea class="border border-gray-200 p-2 h-[300px] w-full mt-2" ref="codeEditor"></textarea>
38+
<div class="border border-gray-200 h-[300px] w-full mt-2" ref="codeEditor"></div>
3939
</div>
4040
<button @click="createDocument()" class="rounded-md bg-ultramarine-600 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-ultramarine-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600">Submit</button>
4141
<div v-if="errors.length > 0" class="rounded-md bg-red-50 p-4 mt-1">

frontend/src/create-document/create-document.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const appendCSS = require('../appendCSS');
1515
appendCSS(require('./create-document.css'));
1616

1717
const template = require('./create-document.html');
18+
const { createAceEditor, destroyAceEditor } = require('../aceEditor');
1819

1920
module.exports = app => app.component('create-document', {
2021
props: ['currentModel', 'paths'],
@@ -104,11 +105,19 @@ module.exports = app => app.component('create-document', {
104105
this.documentData += ` ${requiredPaths[i].path}: ${isLast ? '' : ','}\n`;
105106
}
106107
this.documentData += '}';
107-
this.$refs.codeEditor.value = this.documentData;
108-
this.editor = CodeMirror.fromTextArea(this.$refs.codeEditor, {
108+
const container = this.$refs.codeEditor;
109+
this.editor = createAceEditor(container, {
110+
value: this.documentData,
109111
mode: 'javascript',
110-
lineNumbers: true,
111-
smartIndent: false
112+
lineNumbers: true
112113
});
114+
this.editor.session.on('change', () => {
115+
this.documentData = this.editor.getValue();
116+
});
117+
},
118+
beforeDestroy() {
119+
if (this.editor) {
120+
destroyAceEditor(this.editor);
121+
}
113122
}
114123
});

0 commit comments

Comments
 (0)