aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--static/panes/tool.js33
-rw-r--r--types/compilation/compilation.interfaces.ts8
-rw-r--r--views/templates/panes/tool-output.pug3
3 files changed, 42 insertions, 2 deletions
diff --git a/static/panes/tool.js b/static/panes/tool.js
index eafa859c0..3bb123d68 100644
--- a/static/panes/tool.js
+++ b/static/panes/tool.js
@@ -36,6 +36,7 @@ var monacoConfig = require('../monaco-config');
var ceoptions = require('../options').options;
var utils = require('../utils');
var PaneRenaming = require('../widgets/pane-renaming').PaneRenaming;
+var saveAs = require('file-saver').saveAs;
function makeAnsiToHtml(color) {
return new AnsiToHtml({
@@ -317,12 +318,14 @@ Tool.prototype.initButtons = function (state) {
this.hideable = this.domRoot.find('.hideable');
- this.initToggleButtons(state);
+ this.initButtonsVisibility(state);
};
-Tool.prototype.initToggleButtons = function (state) {
+Tool.prototype.initButtonsVisibility = function (state) {
this.toggleArgs = this.domRoot.find('.toggle-args');
this.toggleStdin = this.domRoot.find('.toggle-stdin');
+ this.artifactBtn = this.domRoot.find('.artifact-btn');
+ this.artifactText = this.domRoot.find('.artifact-text');
if (state.argsPanelShown === true) {
this.showPanel(this.toggleArgs, this.panelArgs);
@@ -337,6 +340,7 @@ Tool.prototype.initToggleButtons = function (state) {
}
}
}
+ this.artifactBtn.addClass('d-none');
};
Tool.prototype.showPanel = function (button, panel) {
@@ -511,6 +515,31 @@ Tool.prototype.onCompileResult = function (id, compiler, result) {
if (toolResult.sourcechanged && this.editorId) {
this.eventHub.emit('newSource', this.editorId, toolResult.newsource);
}
+ this.artifactBtn.off('click');
+ if (toolResult.artifact) {
+ this.artifactBtn.removeClass('d-none');
+ this.artifactText.text('Download ' + toolResult.artifactGenerated.title);
+ this.artifactBtn.click(
+ _.bind(function () {
+ // The artifact content can be passed either as plain text or as a base64 encoded binary file
+ if (toolResult.artifactGenerated.type === 'application/octet-stream') {
+ // Fetch is the most convenient non ES6 way to build a binary blob out of a base64 string
+ fetch('data:application/octet-stream;base64,' + toolResult.artifactGenerated.content)
+ .then(res => res.blob())
+ .then(blob => saveAs(blob, toolResult.artifact.name));
+ } else {
+ saveAs(
+ new Blob([toolResult.artifact.content], {
+ type: toolResult.artifact.type,
+ }),
+ toolResult.artifact.name
+ );
+ }
+ }, this)
+ );
+ } else {
+ this.artifactBtn.addClass('d-none');
+ }
} else {
this.setEditorContent('No tool result');
}
diff --git a/types/compilation/compilation.interfaces.ts b/types/compilation/compilation.interfaces.ts
index c63c6e11e..235b86a63 100644
--- a/types/compilation/compilation.interfaces.ts
+++ b/types/compilation/compilation.interfaces.ts
@@ -99,6 +99,13 @@ export type BuildResult = {
compilationOptions: any[];
};
+export type Artifact = {
+ content: string;
+ type: string;
+ name: string;
+ title: string;
+};
+
export type ToolResult = {
id: string;
name: string;
@@ -106,4 +113,5 @@ export type ToolResult = {
languageId: string;
stderr: ResultLine[];
stdout: ResultLine[];
+ artifact?: Artifact;
};
diff --git a/views/templates/panes/tool-output.pug b/views/templates/panes/tool-output.pug
index 437bf74ad..d4aa8cde2 100644
--- a/views/templates/panes/tool-output.pug
+++ b/views/templates/panes/tool-output.pug
@@ -15,6 +15,9 @@
button.btn.btn-sm.btn-light.toggle-stdin
span.fas.fa-sign-in-alt
span.hideable Stdin
+ button.btn.btn-sm.btn-light.artifact-btn(title="Download generated artifact" aria-label="Download generated artifact")
+ span.fa.fa-download
+ span.hideable.artifact-text Download
.top-bar.btn-toolbar.bg-light.panel-args.d-none(role="toolbar")
input.options.form-control(type="text" placeholder="Tool arguments..." size="256" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false")
.top-bar.btn-toolbar.bg-light.panel-stdin.d-none(role="toolbar")