Skip to content

Commit

Permalink
Bypass blob storage in UploadArtifact. Closes #1704 (#1717)
Browse files Browse the repository at this point in the history
* Bypass blob storage in UploadArtifact(Closes #1704)

* WIP- Fix eslinting issues

* WIP-Refactor CustomConfigEntries, Address PR suggestions

* WIP- add spinner; fix unused imports

* WIP- Gracefully handle dialog errors, rename BrowserAssetWidget->FileWidget

* Fix widget name in components.json, Use toast to show errors
  • Loading branch information
umesh-timalsina committed Jul 31, 2020
1 parent 062d1c9 commit 4176861
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 176 deletions.
11 changes: 10 additions & 1 deletion config/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
"container": "float",
"DEBUG_ONLY": false
}

]
},
"RootViz": {
Expand Down Expand Up @@ -135,5 +135,14 @@
},
"Storage": {
"backends": ["gme", "sciserver-files", "s3"]
},
"PropertyGridWidgets": {
"widgets" : [
{
"name" : "FileWidget",
"type": "file",
"path" : "deepforge/viz/widgets/FileWidget"
}
]
}
}
32 changes: 20 additions & 12 deletions src/common/globals.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,31 +271,39 @@ define([
const allConfigs = await configDialog.show(metadata);
const context = client.getCurrentPluginContext(pluginName);
context.pluginConfig = allConfigs[pluginName];
context.pluginConfig.storage.id = storageMetadata
.find(metadata => metadata.name === context.pluginConfig.storage.name)
.id;
const hasStorageConfig = pluginConfig => !!pluginConfig.storage;
if (hasStorageConfig(context.pluginConfig)){
context.pluginConfig.storage.id = storageMetadata
.find(metadata => metadata.name === context.pluginConfig.storage.name)
.id;
}
return await Q.ninvoke(client, 'runBrowserPlugin', pluginName, context);
};


DeepForge.create.Artifact = async function() {
const USER_ASSET_TYPE = 'userAsset';
const metadata = copy(WebGMEGlobal.allPluginsMetadata[UPLOAD_PLUGIN]);
const storageOpts = getStorageOptions();
const hasUserAssetType = metadata.configStructure
.map(config => config.valueType)
.find(val => val === USER_ASSET_TYPE);

metadata.configStructure.unshift({
name: 'artifactOptions',
displayName: 'New Artifact',
valueType: 'section'
});

const storageHeader = {
name: 'storageOptions',
displayName: 'Storage',
valueType: 'section'
};
metadata.configStructure.push(storageHeader);
metadata.configStructure.push(storageOpts);

if(!hasUserAssetType){
const storageOpts = getStorageOptions();
const storageHeader = {
name: 'storageOptions',
displayName: 'Storage',
valueType: 'section'
};
metadata.configStructure.push(storageHeader);
metadata.configStructure.push(storageOpts);
}
await runArtifactPlugin(UPLOAD_PLUGIN, metadata);
};

Expand Down
2 changes: 1 addition & 1 deletion src/common/storage/backends/sciserver-files/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ define([
const metadata = {
filename: filename,
volume: this.volume,
size: content.byteLength,
size: content.byteLength || content.size,
volumePool: this.volumePool
};
return this.createDataInfo(metadata);
Expand Down
15 changes: 15 additions & 0 deletions src/common/viz/ConfigDialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,18 @@
color: #888;
font-style: italic;
}

.glyphicon-refresh-animate {
-animation: spin .7s infinite linear;
-webkit-animation: spin2 .7s infinite linear;
}

@-webkit-keyframes spin2 {
from { -webkit-transform: rotate(0deg);}
to { -webkit-transform: rotate(360deg);}
}

@keyframes spin {
from { transform: scale(1) rotate(0deg);}
to { transform: scale(1) rotate(360deg);}
}
202 changes: 67 additions & 135 deletions src/common/viz/ConfigDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@
define([
'q',
'js/Dialogs/PluginConfig/PluginConfigDialog',
'./ConfigDialogEntries/CustomConfigEntries',
'deepforge/utils',
'js/Utils/ComponentSettings',
'panel/FloatingActionButton/styles/Materialize',
'text!js/Dialogs/PluginConfig/templates/PluginConfigDialog.html',
'css!./ConfigDialog.css'
], function(
Q,
PluginConfigDialog,
CustomConfigEntries,
utils,
pluginConfigDialogTemplate,
ComponentSettings,
Materialize,
pluginConfigDialogTemplate
) {
var SECTION_DATA_KEY = 'section',
ATTRIBUTE_DATA_KEY = 'attribute',
Expand All @@ -18,38 +24,66 @@ define([
ENTRY_BASE = $('<div class="form-group"><div class="row"><label class="col-sm-4 control-label">NAME</label><div class="col-sm-8 controls"></div></div><div class="row description"><div class="col-sm-4"></div></div></div>'),
//jscs:enable maximumLineLength
DESCRIPTION_BASE = $('<div class="desc muted col-sm-8"></div>'),
SECTION_HEADER = $('<h6 class="config-section-header">');
SPINNER_BASE = $('<span class="text-primary glyphicon glyphicon-refresh glyphicon-refresh-animate"></span>');

var ConfigDialog = function(client) {
PluginConfigDialog.call(this, {client: client});
this._widgets = {};
this._customEntriesManager = new CustomConfigEntries();
this._initCustomEntriesManagerMethods();
this.imported = this._registerCustomPropertyGridWidgets();
};

ConfigDialog.prototype = Object.create(PluginConfigDialog.prototype);

ConfigDialog.prototype._initCustomEntriesManagerMethods = function () {
this._customEntriesManager.getEntryForProperty = this.getEntryForProperty.bind(this);
this._customEntriesManager.getBaseStorageDir = this.getBaseStorageDir.bind(this);
};

ConfigDialog.prototype._registerCustomPropertyGridWidgets = async function() {
const self = this;
const customWidgets = ComponentSettings.resolveWithWebGMEGlobal(
{},
'PropertyGridWidgets'
).widgets || [];

const promises = customWidgets.map(widgetInfo => {
return new Promise((resolve, reject) => {
require([widgetInfo.path], function(customWidget) {
const targetType = widgetInfo.type;
self._propertyGridWidgetManager
.registerWidgetForType(targetType, customWidget);
resolve();
}, reject);
});
});
return Promise.all(promises);
};

ConfigDialog.prototype.show = async function(pluginMetadata, options={}) {
const deferred = Q.defer();

this._pluginMetadata = pluginMetadata;
const prevConfig = await this.getSavedConfig();
await this.imported;
this._initDialog(pluginMetadata, prevConfig, options);

this._dialog.on('shown', () => {
this._dialog.find('input').first().focus();
});

this._btnSave.on('click', event => {
this.submit(deferred.resolve);
this._btnSave.on('click', async event => {
event.stopPropagation();
event.preventDefault();
await this.submit(deferred.resolve);
});

//save&run on CTRL + Enter
this._dialog.on('keydown.PluginConfigDialog', event => {
this._dialog.on('keydown.PluginConfigDialog', async event => {
if (event.keyCode === 13 && (event.ctrlKey || event.metaKey)) {
event.stopPropagation();
event.preventDefault();
this.submit(deferred.resolve);
await this.submit(deferred.resolve);
}
});
this._dialog.modal('show');
Expand All @@ -63,6 +97,7 @@ define([
this._divContainer = this._dialog.find('.modal-body');
this._saveConfigurationCb = this._dialog.find('.save-configuration');
this._modalHeader = this._dialog.find('.modal-header');
this._modalFooter = this._dialog.find('.modal-footer');
this._saveConfigurationCb.find('input').prop('checked', true);

// Create the header
Expand All @@ -85,8 +120,10 @@ define([
};
};

ConfigDialog.prototype.submit = function (callback) {
const config = this._getAllConfigValues();
ConfigDialog.prototype.submit = async function (callback) {
this._btnSave.attr('disabled', true);
SPINNER_BASE.insertAfter(this._modalFooter.find('form'));
const config = await this._getAllConfigValues();
const saveConfig = this._saveConfigurationCb.find('input')
.prop('checked');

Expand Down Expand Up @@ -159,16 +196,23 @@ define([
return response.status < 399 ? await response.json() : null;
};

ConfigDialog.prototype._getAllConfigValues = function () {
ConfigDialog.prototype._getAllConfigValues = async function () {
var settings = {};

Object.keys(this._widgets).forEach(namespace => {
for (const namespace of Object.keys(this._widgets)){
settings[namespace] = {};

Object.keys(this._widgets[namespace]).forEach(name => {
settings[namespace][name] = this._widgets[namespace][name].getValue();
});
});
for(const name of Object.keys(this._widgets[namespace])){
let value;
try {
value = await this._widgets[namespace][name].getValue();
} catch (e) {
Materialize.toast(e.message, 4000);
this._dialog.modal('hide');
throw e;
}
settings[namespace][name] = value;
}
}

return settings;
};
Expand Down Expand Up @@ -224,8 +268,8 @@ define([

ConfigDialog.prototype.getEntryForProperty = function (configEntry, prevConfig = {}) {
let entry = null;
if (ConfigDialog.ENTRIES[configEntry.valueType]) {
entry = ConfigDialog.ENTRIES[configEntry.valueType].call(this, configEntry, prevConfig);
if (CustomConfigEntries.isCustomEntryValueType(configEntry.valueType)) {
entry = this._customEntriesManager[configEntry.valueType](configEntry, prevConfig);
} else {
const widget = this.getWidgetForProperty(configEntry);
const el = ENTRY_BASE.clone();
Expand Down Expand Up @@ -274,127 +318,15 @@ define([
}
};

ConfigDialog.WIDGETS = {};
ConfigDialog.ENTRIES = {};
ConfigDialog.ENTRIES.section = function(configEntry) {
const sectionHeader = SECTION_HEADER.clone();
sectionHeader.text(configEntry.displayName);
return {el: sectionHeader};
ConfigDialog.prototype.getBaseStorageDir = function() {
return `${this._client.getActiveProjectId()}/artifacts`;
};

ConfigDialog.ENTRIES.group = function(configEntry, config) {
const widget = {el: null};
widget.el = $('<div>', {class: configEntry.name});

const entries = configEntry.valueItems
.map(item => this.getEntryForProperty(item, config));

entries.forEach(entry => widget.el.append(entry.el));

widget.getValue = () => {
const config = {};
entries.forEach(entry => {
if (entry.widget) {
config[entry.id || entry.name] = entry.widget.getValue();
}
});
return config;
};

widget.setValue = config => {
entries.forEach(entry => {
const value = config[entry.id || entry.name];
if (entry.widget && value !== undefined) {
entry.widget.setValue(value);
}
});
return config;
};

return {widget, el: widget.el};
ConfigDialog.prototype.getComponentId = function() {
return 'ConfigDialog';
};

ConfigDialog.ENTRIES.dict = function(configEntry, config) {
const widget = {el: null, active: null};
widget.el = $('<div>', {class: configEntry.name});

const entriesForItem = {};
const valueItemsDict = {};
for (let i = 0; i < configEntry.valueItems.length; i++) {
const valueItem = configEntry.valueItems[i];
const entries = valueItem.configStructure
.map(item => {
const entry = this.getEntryForProperty(item, config);
return entry;
});

entries.forEach(entry => {
if (i > 0) {
entry.el.css('display', 'none');
}
widget.el.append(entry.el);
});

const displayName = valueItem.displayName || valueItem.name;
entriesForItem[displayName] = entries;
valueItemsDict[displayName] = valueItem;
}

const itemNames = Object.keys(valueItemsDict);
const defaultValue = itemNames[0];

const configForKeys = {
name: configEntry.name,
displayName: configEntry.displayName,
value: defaultValue,
valueType: 'string',
valueItems: itemNames
};
const selector = this.getEntryForProperty(configForKeys);

widget.active = defaultValue;
widget.onSetSelector = value => {
const oldEntries = entriesForItem[widget.active];
oldEntries.forEach(entry => entry.el.css('display', 'none'));

widget.active = value;
entriesForItem[widget.active]
.forEach(entry => entry.el.css('display', ''));
};

selector.el.find('select').on('change', event => {
const {value} = event.target;
widget.onSetSelector(value);
});

widget.getValue = () => {
const displayName = widget.active;
const name = valueItemsDict[displayName].name;
const config = {};
entriesForItem[name].forEach(entry => {
if (entry.widget) {
config[entry.id] = entry.widget.getValue();
}
});
return {name, config};
};

widget.setValue = value => {
const {name, config} = value;
selector.widget.setValue(name);
widget.onSetSelector(name);
entriesForItem[name].forEach(entry => {
if (entry.widget) {
entry.widget.setValue(config[entry.id]);
}
});
return {name, config};
};

widget.el.prepend(selector.el);

return {widget, el: widget.el};
};
ConfigDialog.WIDGETS = {};

return ConfigDialog;
});

0 comments on commit 4176861

Please sign in to comment.