Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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" : "BrowserAssetWidget",
"type": "browserAsset",
"path" : "deepforge/viz/widgets/BrowserAssetWidget"
}
]
}
}
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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this changed?

Copy link
Contributor Author

@umesh-timalsina umesh-timalsina Jul 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because File or Blob doesn't have attribute byteLength but size. You can still create an ArrayBuffer during the upload from the widget, but its not needed.

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);}
}
193 changes: 58 additions & 135 deletions src/common/viz/ConfigDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
define([
'q',
'js/Dialogs/PluginConfig/PluginConfigDialog',
'./ConfigDialogEntries/CustomConfigEntries',
'deepforge/utils',
'js/Utils/ComponentSettings',
'text!js/Dialogs/PluginConfig/templates/PluginConfigDialog.html',
'css!./ConfigDialog.css'
], function(
Q,
PluginConfigDialog,
CustomConfigEntries,
utils,
pluginConfigDialogTemplate,
ComponentSettings,
pluginConfigDialogTemplate
) {
var SECTION_DATA_KEY = 'section',
ATTRIBUTE_DATA_KEY = 'attribute',
Expand All @@ -18,38 +22,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 +95,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 +118,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 +194,16 @@ 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])){
const value = await this._widgets[namespace][name].getValue();
settings[namespace][name] = value;
}
}

return settings;
};
Expand Down Expand Up @@ -224,8 +259,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 +309,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;
});
Loading