Add button to CLI for loading commands from file (#1230)

Add button to CLI for loading commands from file
10.7.0-preview
Michael Keller 2019-04-30 23:02:57 +12:00 committed by GitHub
commit 0c6d6c1001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 135 additions and 29 deletions

View File

@ -2289,6 +2289,18 @@
"cliCopySuccessful": { "cliCopySuccessful": {
"message": "Copied!" "message": "Copied!"
}, },
"cliLoadFromFileBtn": {
"message": "Load from file"
},
"cliConfirmSnippetDialogTitle": {
"message": "Review loaded commands"
},
"cliConfirmSnippetNote": {
"message": "<strong>Note</strong>: You can review and edit commands before execution."
},
"cliConfirmSnippetBtn": {
"message": "Execute"
},
"loggingNote": { "loggingNote": {
"message": "Data will be logged in this tab <span class=\"message-negative\">only</span>, leaving the tab will <span class=\"message-negative\">cancel</span> logging and application will return to its normal <strong>\"configurator\"</strong> state.<br /> You are free to select the global update period, data will be written into the log file every <strong>1</strong> second for performance reasons." "message": "Data will be logged in this tab <span class=\"message-negative\">only</span>, leaving the tab will <span class=\"message-negative\">cancel</span> logging and application will return to its normal <strong>\"configurator\"</strong> state.<br /> You are free to select the global update period, data will be written into the log file every <strong>1</strong> second for performance reasons."

View File

@ -42,7 +42,7 @@
float: left; float: left;
} }
.tab-cli textarea { .tab-cli textarea[name='commands'] {
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
width: 100%; width: 100%;
margin-top: 8px; margin-top: 8px;
@ -53,6 +53,18 @@
resize: none; resize: none;
} }
.jBox-container textarea#preview {
background-color: rgba(0, 0, 0, 0.75);
width: 100%;
resize: none;
overflow-y: scroll;
overflow-x: hidden;
font-family: monospace;
color: white;
padding: 5px;
margin-bottom: 5px;
}
.tab-cli #content-watermark { .tab-cli #content-watermark {
z-index: 0; z-index: 0;
} }

View File

@ -4,7 +4,10 @@ TABS.cli = {
lineDelayMs: 15, lineDelayMs: 15,
profileSwitchDelayMs: 100, profileSwitchDelayMs: 100,
outputHistory: "", outputHistory: "",
cliBuffer: "" cliBuffer: "",
GUI: {
snippetPreviewWindow: null,
},
}; };
function removePromptHash(promptText) { function removePromptHash(promptText) {
@ -95,6 +98,31 @@ TABS.cli.initialize = function (callback, nwGui) {
// nwGui variable is set in main.js // nwGui variable is set in main.js
const clipboardCopySupport = !(nwGui == null && !navigator.clipboard); const clipboardCopySupport = !(nwGui == null && !navigator.clipboard);
const enterKeyCode = 13;
function executeCommands(out_string) {
self.history.add(out_string.trim());
var outputArray = out_string.split("\n");
Promise.reduce(outputArray, function(delay, line, index) {
return new Promise(function (resolve) {
GUI.timeout_add('CLI_send_slowly', function () {
var processingDelay = self.lineDelayMs;
line = line.trim();
if (line.toLowerCase().startsWith('profile')) {
processingDelay = self.profileSwitchDelayMs;
}
const isLastCommand = outputArray.length === index + 1;
if (isLastCommand && self.cliBuffer) {
line = getCliCommand(line, self.cliBuffer);
}
self.sendLine(line, function () {
resolve(processingDelay);
});
}, delay)
})
}, 0);
}
$('#content').load("./tabs/cli.html", function () { $('#content').load("./tabs/cli.html", function () {
// translate to user-selected language // translate to user-selected language
@ -102,7 +130,7 @@ TABS.cli.initialize = function (callback, nwGui) {
CONFIGURATOR.cliActive = true; CONFIGURATOR.cliActive = true;
var textarea = $('.tab-cli textarea'); var textarea = $('.tab-cli textarea[name="commands"]');
CliAutoComplete.initialize(textarea, self.sendLine.bind(self), writeToOutput); CliAutoComplete.initialize(textarea, self.sendLine.bind(self), writeToOutput);
$(CliAutoComplete).on('build:start', function() { $(CliAutoComplete).on('build:start', function() {
@ -174,6 +202,64 @@ TABS.cli.initialize = function (callback, nwGui) {
$('.tab-cli .copy').hide(); $('.tab-cli .copy').hide();
} }
$('.tab-cli .load').click(function() {
var accepts = [
{
description: 'Config files', extensions: ["txt", "config"],
},
{
description: 'All files',
},
];
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(entry) {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
return;
}
if (!entry) {
console.log('No file selected');
return;
}
let previewArea = $("#snippetpreviewcontent textarea#preview");
function executeSnippet() {
const commands = previewArea.val();
executeCommands(commands);
self.GUI.snippetPreviewWindow.close();
}
function previewCommands(result) {
if (!self.GUI.snippetPreviewWindow) {
self.GUI.snippetPreviewWindow = new jBox("Modal", {
id: "snippetPreviewWindow",
width: 'auto',
height: 'auto',
closeButton: 'title',
animation: false,
title: i18n.getMessage("cliConfirmSnippetDialogTitle"),
content: $('#snippetpreviewcontent'),
onCreated: () =>
$("#snippetpreviewcontent a.confirm").click(() => executeSnippet())
,
});
}
previewArea.val(result);
self.GUI.snippetPreviewWindow.open();
}
entry.file((file) => {
let reader = new FileReader();
reader.onload =
() => previewCommands(reader.result);
reader.onerror = () => console.error(reader.error);
reader.readAsText(file);
});
});
});
// Tab key detection must be on keydown, // Tab key detection must be on keydown,
// `keypress`/`keyup` happens too late, as `textarea` will have already lost focus. // `keypress`/`keyup` happens too late, as `textarea` will have already lost focus.
textarea.keydown(function (event) { textarea.keydown(function (event) {
@ -200,7 +286,6 @@ TABS.cli.initialize = function (callback, nwGui) {
}); });
textarea.keypress(function (event) { textarea.keypress(function (event) {
const enterKeyCode = 13;
if (event.which == enterKeyCode) { if (event.which == enterKeyCode) {
event.preventDefault(); // prevent the adding of new line event.preventDefault(); // prevent the adding of new line
@ -209,28 +294,7 @@ TABS.cli.initialize = function (callback, nwGui) {
} }
var out_string = textarea.val(); var out_string = textarea.val();
self.history.add(out_string.trim()); executeCommands(out_string);
var outputArray = out_string.split("\n");
Promise.reduce(outputArray, function(delay, line, index) {
return new Promise(function (resolve) {
GUI.timeout_add('CLI_send_slowly', function () {
var processingDelay = self.lineDelayMs;
line = line.trim();
if (line.toLowerCase().startsWith('profile')) {
processingDelay = self.profileSwitchDelayMs;
}
const isLastCommand = outputArray.length === index + 1;
if (isLastCommand && self.cliBuffer) {
line = getCliCommand(line, self.cliBuffer);
}
self.sendLine(line, function () {
resolve(processingDelay);
});
}, delay)
})
}, 0);
textarea.val(''); textarea.val('');
} }
}); });
@ -433,6 +497,10 @@ TABS.cli.send = function (line, callback) {
}; };
TABS.cli.cleanup = function (callback) { TABS.cli.cleanup = function (callback) {
if (TABS.cli.GUI.snippetPreviewWindow) {
TABS.cli.GUI.snippetPreviewWindow.destroy();
TABS.cli.GUI.snippetPreviewWindow = null;
}
if (!(CONFIGURATOR.connectionValid && CONFIGURATOR.cliValid && CONFIGURATOR.cliActive)) { if (!(CONFIGURATOR.connectionValid && CONFIGURATOR.cliValid && CONFIGURATOR.cliActive)) {
if (callback) { if (callback) {
callback(); callback();

View File

@ -16,8 +16,22 @@
<div class="content_toolbar"> <div class="content_toolbar">
<div class="btn save_btn pull-right"> <div class="btn save_btn pull-right">
<a class="save" href="#" i18n="cliSaveToFileBtn"></a> <a class="save" href="#" i18n="cliSaveToFileBtn"></a>
<a class="load" href="#" i18n="cliLoadFromFileBtn"></a>
<a class="clear" href="#" i18n="cliClearOutputHistoryBtn"></a> <a class="clear" href="#" i18n="cliClearOutputHistoryBtn"></a>
<a class="copy" href="#" i18n="cliCopyToClipboardBtn"></a> <a class="copy" href="#" i18n="cliCopyToClipboardBtn"></a>
</div> </div>
</div> </div>
<!-- Snippet preview dialog -->
<div id="snippetpreviewcontent" style="display: none">
<div class="note">
<div class="note_spacer">
<p i18n="cliConfirmSnippetNote"></p>
</div>
</div>
<textarea id="preview" cols="120" rows="20"></textarea>
<div class="default_btn">
<a class="confirm" href="#" i18n="cliConfirmSnippetBtn"></a>
</div>
</div>
</div> </div>

View File

@ -14,7 +14,7 @@ describe('TABS.cli', () => {
describe('output', () => { describe('output', () => {
const cliTab = $('<div>').addClass('tab-cli'); const cliTab = $('<div>').addClass('tab-cli');
const cliOutput = $('<div>').addClass('wrapper') const cliOutput = $('<div>').addClass('wrapper')
const cliPrompt = $('<textarea>'); const cliPrompt = $('<textarea name="commands">');
cliTab.append($('<div>').addClass('window').append(cliOutput)); cliTab.append($('<div>').addClass('window').append(cliOutput));
cliTab.append(cliPrompt); cliTab.append(cliPrompt);
@ -101,7 +101,7 @@ describe('TABS.cli', () => {
describe('input', () => { describe('input', () => {
const content = $('<div>').attr('id', 'content'); const content = $('<div>').attr('id', 'content');
const cliTab = $('<div>').addClass('tab-cli'); const cliTab = $('<div>').addClass('tab-cli');
const cliPrompt = $('<textarea>'); const cliPrompt = $('<textarea name="commands">');
cliTab.append(cliPrompt); cliTab.append(cliPrompt);
beforeEach(() => { beforeEach(() => {