Skip to content

Commit 3f48674

Browse files
authored
Update artifact downloading and refactor UI storage helpers. Fix #1748 (#1749)
* Update artifact downloading and refactor UI storage helpers. Fix #1748 * Refactor download logic to StorageHelpers
1 parent 6b2f138 commit 3f48674

File tree

4 files changed

+88
-78
lines changed

4 files changed

+88
-78
lines changed

src/common/viz/StorageHelpers.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*globals define*/
2+
define([
3+
'deepforge/viz/ConfigDialog',
4+
'deepforge/storage/index',
5+
'panel/FloatingActionButton/styles/Materialize',
6+
], function(
7+
ConfigDialog,
8+
Storage,
9+
Materialize,
10+
) {
11+
const StorageHelpers = {};
12+
13+
StorageHelpers.getAuthenticationConfig = async function (dataInfo) {
14+
const {backend} = dataInfo;
15+
const metadata = Storage.getStorageMetadata(backend);
16+
metadata.configStructure = metadata.configStructure
17+
.filter(option => option.isAuth);
18+
if (metadata.configStructure.length) {
19+
const configDialog = new ConfigDialog();
20+
const title = `Authenticate with ${metadata.name}`;
21+
const iconClass = `glyphicon glyphicon-download-alt`;
22+
const config = await configDialog.show(metadata, {title, iconClass});
23+
24+
return config[backend];
25+
}
26+
};
27+
28+
StorageHelpers.download = async function (dataInfo, dataName='data') {
29+
const config = await StorageHelpers.getAuthenticationConfig(dataInfo);
30+
const storageAdapter = await Storage.getClient(dataInfo.backend, null, config);
31+
const storageName = Storage.getStorageMetadata(dataInfo.backend).name;
32+
33+
Materialize.toast(`Fetching ${dataName} from ${storageName}...`, 2000);
34+
let reminders = setInterval(
35+
() => Materialize.toast(`Still fetching ${dataName} from ${storageName}...`, 5000),
36+
10000
37+
);
38+
const url = await storageAdapter.getDownloadURL(dataInfo);
39+
clearInterval(reminders);
40+
41+
const save = document.createElement('a');
42+
43+
save.href = url;
44+
save.target = '_self';
45+
const hasExtension = dataName.includes('.');
46+
const filename = hasExtension ? dataName :
47+
dataName + '.dat';
48+
save.download = filename;
49+
save.click();
50+
(window.URL || window.webkitURL).revokeObjectURL(save.href);
51+
};
52+
53+
return StorageHelpers;
54+
});

src/visualizers/panels/ArtifactIndex/ArtifactIndexControl.js

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@
33

44
define([
55
'deepforge/storage/index',
6-
'deepforge/viz/ConfigDialog',
76
'blob/BlobClient',
87
'js/Constants'
98
], function (
109
Storage,
11-
ConfigDialog,
1210
BlobClient,
1311
CONSTANTS
1412
) {
@@ -62,16 +60,6 @@ define([
6260
this._client.completeTransaction();
6361
};
6462

65-
this._widget.getDownloadURL = async (id, config) => {
66-
const node = this._client.getNode(id);
67-
const dataInfo = this.getDataInfo(node);
68-
const {backend} = dataInfo;
69-
const storage = await Storage.getClient(backend, this._logger, config);
70-
71-
return await storage.getDownloadURL(dataInfo);
72-
};
73-
this._widget.getConfigDialog = () => new ConfigDialog(this._client);
74-
7563
this._widget.onAttributeChange = (id, attr, newValue) => {
7664
const node = this._client.getNode(id);
7765
const name = node.getAttribute('name');

src/visualizers/panels/ForgeActionButton/Actions.js

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,40 +7,17 @@ define([
77
'q',
88
'js/RegistryKeys',
99
'deepforge/globals',
10-
'deepforge/viz/TextPrompter'
10+
'deepforge/viz/TextPrompter',
11+
'deepforge/viz/StorageHelpers',
1112
], function(
1213
LibraryDialog,
1314
Materialize,
1415
Q,
1516
REGISTRY_KEYS,
1617
DeepForge,
17-
TextPrompter
18+
TextPrompter,
19+
StorageHelpers,
1820
) {
19-
////////////// Downloading files //////////////
20-
var downloadAttrs = [
21-
'data',
22-
'execFiles'
23-
],
24-
download = {};
25-
26-
downloadAttrs.forEach(attr => {
27-
download[attr] = function() {
28-
return downloadButton.call(this, attr);
29-
};
30-
});
31-
32-
// Add download model button
33-
var downloadButton = function(attr) {
34-
var id = this._currentNodeId,
35-
node = this.client.getNode(id),
36-
hash = node.getAttribute(attr);
37-
38-
if (hash) {
39-
return '/rest/blob/download/' + hash;
40-
}
41-
return null;
42-
};
43-
4421
var returnToLast = (place) => {
4522
var returnId = DeepForge.last[place];
4623
WebGMEGlobal.State.registerActiveObject(returnId);
@@ -175,7 +152,16 @@ define([
175152
{
176153
name: 'Download',
177154
icon: 'play_for_work',
178-
href: download.data // function to create href url
155+
action: async function() {
156+
const node = this.client.getNode(this._currentNodeId);
157+
const artifactName = node.getAttribute('name');
158+
try {
159+
const dataInfo = JSON.parse(node.getAttribute('data'));
160+
await StorageHelpers.download(dataInfo, artifactName);
161+
} catch (err) {
162+
Materialize.toast(`Unable to download ${artifactName}: ${err.message}`);
163+
}
164+
}
179165
}
180166
],
181167
Job: [
@@ -184,7 +170,16 @@ define([
184170
name: 'Download Execution Files',
185171
icon: 'play_for_work',
186172
priority: 1,
187-
href: download.execFiles
173+
href: function() {
174+
const id = this._currentNodeId;
175+
const node = this.client.getNode(id);
176+
const hash = node.getAttribute('execFiles');
177+
178+
if (hash) {
179+
return '/rest/blob/download/' + hash;
180+
}
181+
return null;
182+
}
188183
},
189184
// Stop execution button
190185
{

src/visualizers/widgets/ArtifactIndex/ArtifactIndexWidget.js

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ define([
77
'panel/FloatingActionButton/styles/Materialize',
88
'deepforge/storage/index',
99
'deepforge/viz/ConfirmDialog',
10+
'deepforge/viz/StorageHelpers',
1011
'text!./Table.html',
1112
'css!./styles/ArtifactIndexWidget.css'
1213
], function (
@@ -15,6 +16,7 @@ define([
1516
Materialize,
1617
Storage,
1718
ConfirmDialog,
19+
StorageHelpers,
1820
TABLE_HTML
1921
) {
2022
'use strict';
@@ -53,31 +55,28 @@ define([
5355
var node = new ModelItem(this.$list, desc);
5456
this.nodes[desc.id] = node;
5557
node.$delete.on('click', async event => {
58+
event.stopPropagation();
59+
event.preventDefault();
5660
const {dataInfo} = desc;
5761
const deleteData = await this.askIfDeleteFromStorage(dataInfo);
5862
const config = deleteData ?
59-
await this.getAuthenticationConfig(dataInfo) : null;
63+
await StorageHelpers.getAuthenticationConfig(dataInfo) : null;
6064
this.onNodeDeleteClicked(desc.id, config);
61-
event.stopPropagation();
62-
event.preventDefault();
6365
});
6466
node.$download.on('click', async event => {
65-
const config = await this.getAuthenticationConfig(desc.dataInfo);
67+
event.stopPropagation();
68+
event.preventDefault();
6669
try {
67-
const url = await this.getDownloadURL(desc.id, config);
68-
const filename = desc.name.includes('.') ? desc.name : desc.name + '.dat';
69-
this.download(filename, url);
70+
await StorageHelpers.download(desc.dataInfo, desc.name);
7071
} catch (err) {
71-
const msg = `Unable to fetch data: ${err.message}`;
72+
const msg = `Unable to fetch ${desc.name}: ${err.message}`;
7273
Materialize.toast(msg, 4000);
7374
}
74-
event.stopPropagation();
75-
event.preventDefault();
7675
});
7776
node.$el.on('click', event => {
78-
this.onNodeClick(desc.id);
7977
event.stopPropagation();
8078
event.preventDefault();
79+
this.onNodeClick(desc.id);
8180
});
8281
node.$name.on('dblclick', event => this.editInPlace(event,{
8382
nodeId : desc.id,
@@ -115,21 +114,6 @@ define([
115114
return await dialog.show();
116115
};
117116

118-
ArtifactIndexWidget.prototype.getAuthenticationConfig = async function (dataInfo) {
119-
const {backend} = dataInfo;
120-
const metadata = Storage.getStorageMetadata(backend);
121-
metadata.configStructure = metadata.configStructure
122-
.filter(option => option.isAuth);
123-
if (metadata.configStructure.length) {
124-
const configDialog = this.getConfigDialog();
125-
const title = `Authenticate with ${metadata.name}`;
126-
const iconClass = `glyphicon glyphicon-download-alt`;
127-
const config = await configDialog.show(metadata, {title, iconClass});
128-
129-
return config[backend];
130-
}
131-
};
132-
133117
ArtifactIndexWidget.prototype.removeNode = function (gmeId) {
134118
var node = this.nodes[gmeId];
135119
if (node) {
@@ -180,16 +164,5 @@ define([
180164
ArtifactIndexWidget.prototype.onDeactivate = function () {
181165
};
182166

183-
ArtifactIndexWidget.prototype.download = function (filename, url) {
184-
const element = document.createElement('a');
185-
element.style.display = 'none';
186-
document.body.appendChild(element);
187-
element.href = url;
188-
element.target = '_self';
189-
element.setAttribute('download', filename);
190-
element.click();
191-
document.body.removeChild(element);
192-
};
193-
194167
return ArtifactIndexWidget;
195168
});

0 commit comments

Comments
 (0)