diff --git a/luci-app-nikki/htdocs/luci-static/resources/view/nikki/editor.js b/luci-app-nikki/htdocs/luci-static/resources/view/nikki/editor.js index 698b37f96..2e584526b 100644 --- a/luci-app-nikki/htdocs/luci-static/resources/view/nikki/editor.js +++ b/luci-app-nikki/htdocs/luci-static/resources/view/nikki/editor.js @@ -5,6 +5,38 @@ 'require fs'; 'require tools.nikki as nikki' +function loadJS(url) { + return new Promise(function (resolve, reject) { + const script = document.createElement('script'); + script.src = url; + script.onload = resolve; + script.onerror = reject; + document.body.appendChild(script); + }); +} + +function loadCSS(url) { + return new Promise(function (resolve, reject) { + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = url; + link.onload = resolve; + link.onerror = reject; + document.head.appendChild(link); + }); +} + +async function loadCodeMirror() { + try{ + await loadJS('https://unpkg.com/codemirror@5/lib/codemirror.js'); + await loadJS('https://unpkg.com/codemirror@5/mode/yaml/yaml.js'); + await loadCSS('https://unpkg.com/codemirror@5/lib/codemirror.css'); + await loadCSS('https://unpkg.com/codemirror@5/theme/dracula.css'); + } catch (e) { + + } +} + return view.extend({ load: function () { return Promise.all([ @@ -12,6 +44,7 @@ return view.extend({ nikki.listProfiles(), nikki.listRuleProviders(), nikki.listProxyProviders(), + loadCodeMirror(), ]); }, render: function (data) { @@ -53,22 +86,51 @@ return view.extend({ o.write = function (section_id, formvalue) { return true; }; - o.onchange = function (event, section_id, value) { - return L.resolveDefault(fs.read_direct(value), '').then(function (content) { - m.lookupOption('nikki.editor._file_content')[0].getUIElement('editor').setValue(content); - }); - }; + o.onchange = L.bind(function (event, section_id, value) { + const uiElement = this.getUIElement(section_id, '_file_content'); + const editor = uiElement.node.firstChild.editor; + fs.read_direct(value).then(function (content) { + const mode = value.endsWith('.yml') || value.endsWith('.yaml') ? 'yaml' : null; + uiElement.setValue(content); + if (editor) { + editor.setValue(content); + editor.setOption('mode', mode); + editor.getDoc().clearHistory(); + } + }).catch(function (e) { + uiElement.setValue(''); + if (editor) { + editor.setValue(''); + editor.setOption('mode', null); + editor.getDoc().clearHistory(); + } + }) + }, s); o = s.option(form.TextValue, '_file_content',); o.rows = 25; o.wrap = false; - o.write = function (section_id, formvalue) { - const path = m.lookupOption('nikki.editor._file')[0].formvalue('editor'); + o.write = L.bind(function (section_id, formvalue) { + const path = this.getOption('_file').formvalue(section_id); return fs.write(path, formvalue); - }; - o.remove = function (section_id) { - const path = m.lookupOption('nikki.editor._file')[0].formvalue('editor'); + }, s); + o.remove = L.bind(function (section_id) { + const path = this.getOption('_file').formvalue(section_id); return fs.write(path); + }, s); + o.render = function () { + return this.super('render', arguments).then(function (widget) { + const textarea = widget.firstChild.firstChild; + if (CodeMirror) { + const editor = CodeMirror.fromTextArea(textarea, { lineNumbers: true, theme: 'dracula' }); + editor.on('change', function () { + editor.save(); + }); + editor.getWrapperElement().style.height = '420px'; + textarea.editor = editor; + } + return widget; + }); }; return m.render(); diff --git a/luci-app-nikki/htdocs/luci-static/resources/view/nikki/log.js b/luci-app-nikki/htdocs/luci-static/resources/view/nikki/log.js index 9bbf386bb..a35fd280a 100644 --- a/luci-app-nikki/htdocs/luci-static/resources/view/nikki/log.js +++ b/luci-app-nikki/htdocs/luci-static/resources/view/nikki/log.js @@ -29,10 +29,10 @@ return view.extend({ o = s.taboption('app_log', form.Button, 'clear_app_log'); o.inputstyle = 'negative'; o.inputtitle = _('Clear Log'); - o.onclick = function () { - m.lookupOption('nikki.log._app_log')[0].getUIElement('log').setValue(''); + o.onclick = L.bind(function (event, section_id) { + this.getUIElement(section_id, '_app_log').setValue(''); return nikki.clearAppLog(); - }; + }, s); o = s.taboption('app_log', form.TextValue, '_app_log'); o.rows = 25; @@ -52,20 +52,20 @@ return view.extend({ o = s.taboption('app_log', form.Button, 'scroll_app_log_to_bottom'); o.inputtitle = _('Scroll To Bottom'); - o.onclick = function () { - const element = m.lookupOption('nikki.log._app_log')[0].getUIElement('log').node.firstChild; + o.onclick = L.bind(function (event, section_id) { + const element = this.getUIElement(section_id, '_app_log').node.firstChild; element.scrollTop = element.scrollHeight; - }; + }, s); s.tab('core_log', _('Core Log')); o = s.taboption('core_log', form.Button, 'clear_core_log'); o.inputstyle = 'negative'; o.inputtitle = _('Clear Log'); - o.onclick = function () { - m.lookupOption('nikki.log._core_log')[0].getUIElement('log').setValue(''); + o.onclick = L.bind(function (event, section_id) { + this.getUIElement(section_id, '_core_log').setValue(''); return nikki.clearCoreLog(); - }; + }, s); o = s.taboption('core_log', form.TextValue, '_core_log'); o.rows = 25; @@ -85,10 +85,10 @@ return view.extend({ o = s.taboption('core_log', form.Button, 'scroll_core_log_to_bottom'); o.inputtitle = _('Scroll To Bottom'); - o.onclick = function () { - const element = m.lookupOption('nikki.log._core_log')[0].getUIElement('log').node.firstChild; + o.onclick = L.bind(function (event, section_id) { + const element = this.getUIElement(section_id, '_core_log').node.firstChild; element.scrollTop = element.scrollHeight; - }; + }, s); s.tab('debug_log', _('Debug Log'));