Adding a support submission button on CLI to assist in support (#3206)

* Adding a support submission button on CLI to assist in identifying issues

* Fixes following rebase

* Rename build_api to BuildApi.js
10.9-maintenance
J Blackman 2023-01-05 06:16:20 +11:00 committed by GitHub
parent 1344baa59c
commit 902f979878
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 111 additions and 21 deletions

View File

@ -77,6 +77,9 @@
"cancel": {
"message": "Cancel"
},
"submit": {
"message": "Submit"
},
"autoConnectEnabled": {
"message": "Auto-Connect: Enabled - Configurator automatically tries to connect when new port is detected"
},
@ -533,15 +536,24 @@
"message" : "Configurator: <strong>{{configuratorVersion}}</strong>",
"description": "Message that appears in the GUI log panel indicating Configurator version"
},
"buildServerLoaded": {
"message" : "Loaded builds information for $1 from build server."
"buildServerSuccess": {
"message" : "Success: $1"
},
"buildServerLoadFailed": {
"message" : "<b>Build server query for $1 releases failed, using cached information. Reason: <code>$2</code></b>"
"buildServerFailure": {
"message" : "<b>Build server failure: $1 <code>$2</code></b>"
},
"buildServerUsingCached": {
"message" : "Using cached builds information for $1."
},
"buildServerSupportRequestSubmission": {
"message": "<br>*** Support data submitted *** <br>Id: $1<br><br><br># copy ID and provide to the betaflight team."
},
"supportWarningDialogTitle": {
"message": "Confirm Data Submission"
},
"supportWarningDialogText": {
"message": "Please confirm data submission to the Betaflight team.<br><br>This process will run some commands and submit the output to the build server.<br><br>You will then be provided a unique identifier for your data submission.<br><br>Please ensure you provide this unique identifier to the Betaflight team when using Discord or opening an issues on Github."
},
"releaseCheckLoaded": {
"message" : "Loaded release information for $1 from GitHub."
},
@ -2885,6 +2897,9 @@
"cliLoadFromFileBtn": {
"message": "Load from file"
},
"cliSupportRequestBtn": {
"message": "Submit Support Data"
},
"cliConfirmSnippetDialogTitle": {
"message": "Loaded file <strong>{{fileName}}</strong>. Review the loaded commands"
},

View File

@ -2,10 +2,10 @@ import GUI from "./gui";
import { i18n } from "./localization";
import { get as getStorage, set as setStorage } from "./SessionStorage";
export default class ReleaseLoader {
export default class BuildApi {
constructor (url) {
this._url = url;
constructor () {
this._url = 'https://build.betaflight.com';
this._cacheExpirationPeriod = 3600 * 1000;
}
@ -29,8 +29,6 @@ export default class ReleaseLoader {
if (!cachedData || !cachedLastUpdate || dataTimestamp - cachedLastUpdate > this._cacheExpirationPeriod) {
$.get(url, function (info) {
GUI.log(i18n.getMessage('buildServerLoaded', [url]));
// cache loaded info
const object = {};
object[dataTag] = info;
@ -38,7 +36,7 @@ export default class ReleaseLoader {
setStorage(object);
onSuccess(info);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerLoadFailed', [url, `HTTP ${xhr.status}`]));
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
} else {
@ -75,7 +73,41 @@ export default class ReleaseLoader {
GUI.log(i18n.getMessage('buildServerLoaded', [path]));
onSuccess(data);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerLoadFailed', [path, `HTTP ${xhr.status}`]));
GUI.log(i18n.getMessage('buildServerFailure', [path, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
});
}
getSupportCommands(onSuccess, onFailure) {
const url = `${this._url}/api/support/commands`;
$.get(url, function (data) {
onSuccess(data);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
});
}
submitSupportData(data, onSuccess, onFailure) {
const url = `${this._url}/api/support`;
$.ajax({
url: url,
type: "POST",
data: data,
contentType: "text/plain",
dataType: "text",
success: function(response) {
onSuccess(response);
},
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerFailure', [`HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
@ -92,11 +124,11 @@ export default class ReleaseLoader {
contentType: "application/json",
dataType: "json",
success: function(data) {
onSuccess(data);
success: function(response) {
onSuccess(response);
},
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerLoadFailed', [url, `HTTP ${xhr.status}`]));
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}
@ -107,10 +139,10 @@ export default class ReleaseLoader {
const url = `${this._url}/api/builds/${key}/status`;
$.get(url, function (data) {
GUI.log(i18n.getMessage('buildServerLoaded', [url]));
GUI.log(i18n.getMessage('buildServerSuccess', [url]));
onSuccess(data);
}).fail(xhr => {
GUI.log(i18n.getMessage('buildServerLoadFailed', [url, `HTTP ${xhr.status}`]));
GUI.log(i18n.getMessage('buildServerFailure', [url, `HTTP ${xhr.status}`]));
if (onFailure !== undefined) {
onFailure();
}

View File

@ -1,6 +1,7 @@
import { i18n } from "../localization";
import Clipboard from "../Clipboard";
import GUI from '../gui';
import BuildApi from '../BuildApi';
const cli = {
lineDelayMs: 15,
@ -13,6 +14,7 @@ const cli = {
copyButton: null,
windowWrapper: null,
},
lastArrival: 0,
};
function removePromptHash(promptText) {
@ -89,11 +91,16 @@ cli.initialize = function (callback) {
const enterKeyCode = 13;
function clearHistory() {
self.outputHistory = "";
self.GUI.windowWrapper.empty();
}
function executeCommands(outString) {
self.history.add(outString.trim());
const outputArray = outString.split("\n");
Promise.reduce(outputArray, function(delay, line, index) {
return Promise.reduce(outputArray, function(delay, line, index) {
return new Promise(function (resolve) {
GUI.timeout_add('CLI_send_slowly', function () {
let processingDelay = self.lineDelayMs;
@ -181,8 +188,7 @@ cli.initialize = function (callback) {
});
$('.tab-cli .clear').click(function() {
self.outputHistory = "";
self.GUI.windowWrapper.empty();
clearHistory();
});
if (Clipboard.available) {
@ -247,6 +253,38 @@ cli.initialize = function (callback) {
});
});
$('.tab-cli .support').click(function() {
function submitSupportData() {
clearHistory();
const api = new BuildApi();
api.getSupportCommands((commands) => {
executeCommands(commands.join('\n')).then(() => {
const delay = setInterval(() => {
const time = new Date().getTime();
if (self.lastArrival < time - 250) {
clearInterval(delay);
const text = self.outputHistory;
api.submitSupportData(text, (key) => {
writeToOutput(i18n.getMessage('buildServerSupportRequestSubmission', [key]));
});
}
}, 250);
});
});
}
const dialogSettings = {
title: i18n.getMessage("supportWarningDialogTitle"),
text: i18n.getMessage("supportWarningDialogText"),
buttonYesText: i18n.getMessage("submit"),
buttonNoText: i18n.getMessage("cancel"),
buttonYesCallback: submitSupportData,
};
GUI.showYesNoDialog(dialogSettings);
});
// Tab key detection must be on keydown,
// `keypress`/`keyup` happens too late, as `textarea` will have already lost focus.
textarea.keydown(function (event) {
@ -464,6 +502,8 @@ cli.read = function (readInfo) {
}
this.lastArrival = new Date().getTime();
if (!CONFIGURATOR.cliValid && validateText.indexOf('CLI') !== -1) {
GUI.log(i18n.getMessage('cliEnter'));
CONFIGURATOR.cliValid = true;

View File

@ -2,11 +2,11 @@ import { i18n } from '../localization';
import GUI from '../gui';
import { get as getConfig, set as setConfig } from '../ConfigStorage';
import { get as getStorage, set as setStorage } from '../SessionStorage';
import ReleaseLoader from '../release_loader';
import BuildApi from '../BuildApi';
const firmware_flasher = {
targets: null,
releaseLoader: new ReleaseLoader('https://build.betaflight.com'),
releaseLoader: new BuildApi(),
localFirmwareLoaded: false,
selectedBoard: undefined,
boardNeedsVerification: false,

View File

@ -24,6 +24,9 @@
<div class="btn save_btn">
<a class="copy" href="#" i18n="cliCopyToClipboardBtn"></a>
</div>
<div class="btn save_btn">
<a class="support" href="#" i18n="cliSupportRequestBtn"></a>
</div>
</div>
<div class="toolbar_expand_btn" nbrow="2">