From 5b315f938afddad911f2c69a2deca2ca5b3f8c17 Mon Sep 17 00:00:00 2001 From: Udo Walter Date: Thu, 22 Nov 2018 04:27:34 +0000 Subject: [webapp] replace script textareas with a code editor npm install is necessary to load the editor module --- webapp/package-lock.json | 19 +++++++++++ webapp/package.json | 1 + webapp/src/assets/styles.css | 5 +++ webapp/src/components/ConfiguratorModule.vue | 2 +- webapp/src/components/ConfiguratorModuleConfig.vue | 37 +++++++++++++++++++--- webapp/src/components/ConfiguratorModuleEntry.vue | 33 ++++++++++++++++--- webapp/src/components/RegistrationModule.vue | 6 ++-- webapp/src/components/RegistrationModuleEdit.vue | 35 +++++++++++++++++--- webapp/src/main.js | 13 ++++++++ 9 files changed, 133 insertions(+), 18 deletions(-) diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 4d73910..83b8532 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -2005,6 +2005,11 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, + "codemirror": { + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.42.0.tgz", + "integrity": "sha512-pbApC8zDzItP3HRphD6kQVwS976qB5Qi0hU3MZMixLk+AyugOW1RF+8XJEjeyl5yWsHNe88tDUxzeRh5AOxPRw==" + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -2831,6 +2836,11 @@ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "dev": true }, + "diff-match-patch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz", + "integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==" + }, "diffie-hellman": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -11223,6 +11233,15 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.17.tgz", "integrity": "sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==" }, + "vue-codemirror": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/vue-codemirror/-/vue-codemirror-4.0.6.tgz", + "integrity": "sha512-ilU7Uf0mqBNSSV3KT7FNEeRIxH4s1fmpG4TfHlzvXn0QiQAbkXS9lLfwuZpaBVEnpP5CSE62iGJjoliTuA8poQ==", + "requires": { + "codemirror": "^5.41.0", + "diff-match-patch": "^1.0.0" + } + }, "vue-eslint-parser": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz", diff --git a/webapp/package.json b/webapp/package.json index bc4513b..73d6809 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -13,6 +13,7 @@ "dependencies": { "axios": "^0.18.0", "vue": "^2.5.17", + "vue-codemirror": "^4.0.6", "vue-i18n": "^7.8.1", "vue-router": "^3.0.1", "vue-touch": "^2.0.0-beta.4", diff --git a/webapp/src/assets/styles.css b/webapp/src/assets/styles.css index 94be2f2..0df7f2a 100644 --- a/webapp/src/assets/styles.css +++ b/webapp/src/assets/styles.css @@ -41,3 +41,8 @@ html { .element-container { padding: 26px; } + +.CodeMirror { + min-height: 200px; + height: auto; +} \ No newline at end of file diff --git a/webapp/src/components/ConfiguratorModule.vue b/webapp/src/components/ConfiguratorModule.vue index 0f79a30..51889de 100644 --- a/webapp/src/components/ConfiguratorModule.vue +++ b/webapp/src/components/ConfiguratorModule.vue @@ -101,7 +101,7 @@ diff --git a/webapp/src/components/ConfiguratorModuleConfig.vue b/webapp/src/components/ConfiguratorModuleConfig.vue index 5253086..b8bb793 100644 --- a/webapp/src/components/ConfiguratorModuleConfig.vue +++ b/webapp/src/components/ConfiguratorModuleConfig.vue @@ -53,7 +53,10 @@ - +
+
code{{ $t('script') }}
+ +
{{ $t('entries') }} @@ -113,7 +116,11 @@ export default { timeout: '', script: '', expertMode: false, - items: [] + items: [], + interval: { + id: null, + counter: 0 + } } }, computed: { @@ -129,11 +136,11 @@ export default { deep: true, async handler (value) { if (value.type === 'config' && value.show) { - this.name = value.info.name - this.description = value.info.description + this.name = value.info.name || '' + this.description = value.info.description || '' this.defaultEntry = value.info.defaultEntry this.timeout = value.info.timeout - this.script = value.info.script + this.script = value.info.script || '' if (this.script) this.expertMode = true else this.expertMode = false this.items = [] @@ -143,6 +150,8 @@ export default { customName: x.config_x_entry.customName, keyBind: x.config_x_entry.keyBind })) + this.interval.id = setInterval(this.refreshEditor, 50) + this.interval.counter = 0 } } } @@ -172,6 +181,11 @@ export default { }) this.$store.dispatch('configurator/loadData') this.setDialog({ show: false }) + }, + refreshEditor () { + this.interval.counter++ + if (this.$refs.editor) this.$refs.editor.codemirror.refresh() + if (this.interval.counter >= 15) clearInterval(this.interval.id) } } } @@ -191,4 +205,17 @@ export default { margin-left: 20px; margin-right: 20px; } + +.script-heading { + display: flex; + align-items: center; +} + +.script-heading > span { + margin-left: 9px; +} + +.script-editor { + margin-top: 8px; +} diff --git a/webapp/src/components/ConfiguratorModuleEntry.vue b/webapp/src/components/ConfiguratorModuleEntry.vue index 7907742..3bb03a3 100644 --- a/webapp/src/components/ConfiguratorModuleEntry.vue +++ b/webapp/src/components/ConfiguratorModuleEntry.vue @@ -22,7 +22,8 @@ - +
code{{ $t('script') }}
+
@@ -42,7 +43,11 @@ export default { data () { return { name: '', - script: '' + script: '', + interval: { + id: null, + counter: 0 + } } }, computed: { @@ -54,8 +59,10 @@ export default { deep: true, handler (value) { if (value.type === 'entry' && value.show) { - this.name = value.info.name - this.script = value.info.script + this.name = value.info.name || '' + this.script = value.info.script || '' + this.interval.id = setInterval(this.refreshEditor, 50) + this.interval.counter = 0 } } } @@ -71,6 +78,11 @@ export default { }) this.$store.dispatch('configurator/loadData') this.setDialog({ show: false }) + }, + refreshEditor () { + this.interval.counter++ + if (this.$refs.editor) this.$refs.editor.codemirror.refresh() + if (this.interval.counter >= 15) clearInterval(this.interval.id) } } } @@ -81,4 +93,17 @@ export default { .dialog-title { z-index: 1; } + +.script-heading { + display: flex; + align-items: center; +} + +.script-heading > span { + margin-left: 9px; +} + +.script-editor { + margin-top: 8px; +} diff --git a/webapp/src/components/RegistrationModule.vue b/webapp/src/components/RegistrationModule.vue index f9b857f..8ba3c58 100644 --- a/webapp/src/components/RegistrationModule.vue +++ b/webapp/src/components/RegistrationModule.vue @@ -55,12 +55,12 @@ - - + + diff --git a/webapp/src/components/RegistrationModuleEdit.vue b/webapp/src/components/RegistrationModuleEdit.vue index 302cc2e..7adee37 100644 --- a/webapp/src/components/RegistrationModuleEdit.vue +++ b/webapp/src/components/RegistrationModuleEdit.vue @@ -48,7 +48,8 @@ deletable-chips > - +
code{{ $t('script') }}
+ @@ -72,7 +73,11 @@ export default { type: '', groups: [], script: '', - types: ['BASH', 'IPXE'] + types: ['BASH', 'IPXE'], + interval: { + id: null, + counter: 0 + } } }, computed: { @@ -84,11 +89,13 @@ export default { deep: true, handler (value) { if (value.type === 'edit' && value.show) { - this.name = value.info.name - this.description = value.info.description + this.name = value.info.name || '' + this.description = value.info.description || '' this.type = value.info.type || 'BASH' this.groups = value.info.groups ? value.info.groups.map(x => x.id) : [] - this.script = value.info.script + this.script = value.info.script || '' + this.interval.id = setInterval(this.refreshEditor, 50) + this.interval.counter = 0 } } } @@ -107,6 +114,11 @@ export default { }) this.$store.dispatch('registration/loadHooks') this.setDialog({ show: false }) + }, + refreshEditor () { + this.interval.counter++ + if (this.$refs.editor) this.$refs.editor.codemirror.refresh() + if (this.interval.counter >= 15) clearInterval(this.interval.id) } } } @@ -117,4 +129,17 @@ export default { .dialog-title { z-index: 1; } + +.script-heading { + display: flex; + align-items: center; +} + +.script-heading > span { + margin-left: 9px; +} + +.script-editor { + margin-top: 8px; +} diff --git a/webapp/src/main.js b/webapp/src/main.js index 4193481..030f9f7 100644 --- a/webapp/src/main.js +++ b/webapp/src/main.js @@ -1,6 +1,10 @@ import Vue from 'vue' import Vuetify from 'vuetify' import 'vuetify/dist/vuetify.min.css' +import VueCodemirror from 'vue-codemirror' +import 'codemirror/mode/shell/shell.js' +import 'codemirror/lib/codemirror.css' +import 'codemirror/theme/monokai.css' import VueTouch from 'vue-touch' import Vuex from 'vuex' import globalStore from '@/store/global' @@ -38,6 +42,15 @@ Vue.use(Vuetify, { } }) +Vue.use(VueCodemirror, { + options: { + theme: 'monokai', + mode: 'shell', + lineNumbers: true, + viewportMargin: Infinity + } +}) + Vue.use(VueTouch) axios.interceptors.response.use(null, error => { -- cgit v1.2.3-55-g7522