mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
907 lines
31 KiB
JavaScript
907 lines
31 KiB
JavaScript
// =================================================================== module object, exports
|
|
/** User object constructor.
|
|
* @param {SpaceGhost} spaceghost a spaceghost instance
|
|
* @param {String} apikey apikey for use when not using session authentication
|
|
*/
|
|
var API = function API( spaceghost, apikey ){
|
|
this.spaceghost = spaceghost;
|
|
this.apikey = apikey;
|
|
|
|
this.encodedIdExpectedLength = 16;
|
|
this.jQueryLocation = '../../static/scripts/libs/jquery/jquery.js';
|
|
|
|
this.configuration = new ConfigurationAPI( this );
|
|
this.histories = new HistoriesAPI( this );
|
|
this.hdas = new HDAAPI( this );
|
|
this.datasets = new DatasetsAPI( this );
|
|
this.tools = new ToolsAPI( this );
|
|
this.workflows = new WorkflowsAPI( this );
|
|
this.users = new UsersAPI( this );
|
|
this.visualizations = new VisualizationsAPI( this );
|
|
};
|
|
exports.API = API;
|
|
|
|
/** Creates a new api module object.
|
|
* @param {SpaceGhost} spaceghost a spaceghost instance
|
|
* @exported
|
|
*/
|
|
exports.create = function createAPI( spaceghost, apikey ){
|
|
return new API( spaceghost );
|
|
};
|
|
|
|
|
|
API.prototype.toString = function toString(){
|
|
return ( this.spaceghost + '.API:'
|
|
+ (( this.apikey )?( this.apikey ):( '(session)' )) );
|
|
};
|
|
|
|
// ------------------------------------------------------------------- APIError
|
|
/** @class Thrown when Galaxy the API returns an error from a request */
|
|
function APIError( msg, status ){
|
|
Error.apply( this, arguments );
|
|
this.name = "APIError";
|
|
this.message = msg;
|
|
this.status = status;
|
|
}
|
|
APIError.prototype = new Error();
|
|
APIError.prototype.constructor = Error;
|
|
API.prototype.APIError = APIError;
|
|
exports.APIError = APIError;
|
|
|
|
/* ------------------------------------------------------------------- TODO:
|
|
can we component-ize this to become the basis for js-based api binding/resource
|
|
|
|
*/
|
|
// =================================================================== INTERNAL
|
|
var require = patchRequire( require ),
|
|
utils = require( 'utils' );
|
|
|
|
API.prototype._ajax = function _ajax( url, options ){
|
|
options = options || {};
|
|
options.async = false;
|
|
|
|
// PUT data needs to be stringified in jq.ajax and the content changed
|
|
//TODO: server side handling could change this?
|
|
if( ( options.type && [ 'PUT', 'POST' ].indexOf( options.type ) !== -1 )
|
|
&& ( options.data ) ){
|
|
options.contentType = 'application/json';
|
|
options.data = JSON.stringify( options.data );
|
|
}
|
|
|
|
this.ensureJQuery( '../../static/scripts/libs/jquery/jquery.js' );
|
|
var resp = this.spaceghost.evaluate( function( url, options ){
|
|
return jQuery.ajax( url, options );
|
|
}, url, options );
|
|
//this.spaceghost.debug( 'resp: ' + this.spaceghost.jsonStr( resp ) );
|
|
|
|
if( resp.status !== 200 ){
|
|
// grrr... this doesn't lose the \n\r\t
|
|
//throw new APIError( resp.responseText.replace( /[\s\n\r\t]+/gm, ' ' ).replace( /"/, '' ) );
|
|
this.spaceghost.debug( 'API error: code: ' + resp.status + ', response:\n' +
|
|
( resp.responseJSON? this.spaceghost.jsonStr( resp.responseJSON ) : resp.responseText ) );
|
|
throw new APIError( resp.responseText, resp.status );
|
|
}
|
|
if( options.dataType === undefined || options.dataType === 'json' ){
|
|
return JSON.parse( resp.responseText );
|
|
}
|
|
return resp.responseText;
|
|
};
|
|
|
|
// =================================================================== TESTING
|
|
/** Checks whether fn raises an error with a message that contains a status and given string.
|
|
* NOTE: DOES NOT work with steps. @see SpaceGhost#assertStepsRaise
|
|
* @param {Function} testFn a function that may throw an error
|
|
* @param {Integer} statusExpected the HTTP status code expected
|
|
* @param {String} errMsgContains some portion of the correct error msg
|
|
* @private
|
|
*/
|
|
API.prototype._APIRaises = function _APIRaises( testFn, statusExpected, errMsgContains ){
|
|
var failed = false;
|
|
try {
|
|
testFn.call( this.spaceghost );
|
|
} catch( err ){
|
|
if( ( err.name === 'APIError' )
|
|
&& ( err.status && err.status === statusExpected )
|
|
&& ( err.message.indexOf( errMsgContains ) !== -1 ) ){
|
|
failed = true;
|
|
|
|
// re-raise other, non-searched-for errors
|
|
} else {
|
|
throw err;
|
|
}
|
|
}
|
|
return failed;
|
|
};
|
|
|
|
/** Simple assert raises.
|
|
* NOTE: DOES NOT work with steps. @see SpaceGhost#assertStepsRaise
|
|
* @param {Function} testFn a function that may throw an error
|
|
* @param {Integer} statusExpected the HTTP status code expected
|
|
* @param {String} errMsgContains some portion of the correct error msg
|
|
* @param {String} msg assertion message to display
|
|
*/
|
|
API.prototype.assertRaises = function assertRaises( testFn, statusExpected, errMsgContains, msg ){
|
|
return this.spaceghost.test.assert( this._APIRaises( testFn, statusExpected, errMsgContains ), msg );
|
|
};
|
|
|
|
/** Simple assert does not raise.
|
|
* NOTE: DOES NOT work with steps. @see SpaceGhost#assertStepsRaise
|
|
* @param {Function} testFn a function that may throw an error
|
|
* @param {Integer} statusExpected the HTTP status code expected
|
|
* @param {String} errMsgContains some portion of the correct error msg
|
|
* @param {String} msg assertion message to display
|
|
*/
|
|
API.prototype.assertDoesntRaise = function assertDoesntRaise( testFn, statusExpected, errMsgContains, msg ){
|
|
return this.spaceghost.test.assert( !this._APIRaises( testFn, statusExpected, errMsgContains ), msg );
|
|
};
|
|
|
|
// =================================================================== MISC
|
|
API.prototype.isEncodedId = function isEncodedId( id ){
|
|
if( typeof id !== 'string' ){ return false; }
|
|
if( id.match( /[g-zG-Z]/ ) ){ return false; }
|
|
return ( id.length === this.encodedIdExpectedLength );
|
|
};
|
|
|
|
// ------------------------------------------------------------------- is type or throw err
|
|
API.prototype.ensureId = function ensureId( id ){
|
|
if( !this.isEncodedId( id ) ){
|
|
throw new APIError( 'ID is not a valid encoded id: ' + id );
|
|
}
|
|
return id;
|
|
};
|
|
|
|
API.prototype.ensureObject = function ensureObject( obj ){
|
|
if( !utils.isObject( obj ) ){
|
|
throw new APIError( 'Not a valid object: ' + obj );
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
// ------------------------------------------------------------------- jquery
|
|
// using jq for the ajax in this module - that's why these are here
|
|
//TODO:?? could go in spaceghost
|
|
API.prototype.hasJQuery = function hasJQuery(){
|
|
return this.spaceghost.evaluate( function pageHasJQuery(){
|
|
var has = false;
|
|
try {
|
|
has = typeof ( jQuery + '' ) === 'string';
|
|
} catch( err ){}
|
|
return has;
|
|
});
|
|
};
|
|
|
|
API.prototype.ensureJQuery = function ensureJQuery(){
|
|
if( !this.hasJQuery() ){
|
|
var absLoc = this.jQueryLocation,
|
|
injected = this.spaceghost.page.injectJs( absLoc );
|
|
if( !injected ){
|
|
throw new APIError( 'Could not inject jQuery' );
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// =================================================================== CONFIGURATION
|
|
var ConfigurationAPI = function ConfigurationAPI( api ){
|
|
this.api = api;
|
|
};
|
|
ConfigurationAPI.prototype.toString = function toString(){
|
|
return this.api + '.ConfigurationAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
ConfigurationAPI.prototype.urlTpls = {
|
|
index : '/api/configuration'
|
|
};
|
|
|
|
ConfigurationAPI.prototype.index = function index( deleted ){
|
|
this.api.spaceghost.info( 'configuration.index' );
|
|
|
|
return this.api._ajax( this.urlTpls.index, {
|
|
data : {}
|
|
});
|
|
};
|
|
|
|
|
|
// =================================================================== HISTORIES
|
|
var HistoriesAPI = function HistoriesAPI( api ){
|
|
this.api = api;
|
|
};
|
|
HistoriesAPI.prototype.toString = function toString(){
|
|
return this.api + '.HistoriesAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
HistoriesAPI.prototype.urlTpls = {
|
|
index : '/api/histories',
|
|
show : '/api/histories/%s',
|
|
create : '/api/histories',
|
|
delete_ : '/api/histories/%s',
|
|
undelete: '/api/histories/deleted/%s/undelete',
|
|
update : '/api/histories/%s',
|
|
};
|
|
|
|
HistoriesAPI.prototype.index = function index( params ){
|
|
var spaceghost = this.api.spaceghost;
|
|
spaceghost.info( 'histories.index:\n' + spaceghost.jsonStr( params ) );
|
|
if( params === undefined ){
|
|
params = { deleted: false };
|
|
}
|
|
if( params.deleted === undefined ){
|
|
params.deleted = false;
|
|
}
|
|
spaceghost.debug( 'params (now):' + spaceghost.jsonStr( params ) );
|
|
return this.api._ajax( this.urlTpls.index, {
|
|
data : params
|
|
});
|
|
};
|
|
|
|
HistoriesAPI.prototype.show = function show( id, params ){
|
|
var spaceghost = this.api.spaceghost;
|
|
this.api.spaceghost.info( 'histories.show: ' + id + '\n' + spaceghost.jsonStr( params ) );
|
|
id = ( id === 'most_recently_used' )?( id ):( this.api.ensureId( id ) );
|
|
if( params === undefined ){
|
|
params = { deleted: false };
|
|
}
|
|
if( params.deleted === undefined ){
|
|
params.deleted = false;
|
|
}
|
|
spaceghost.debug( 'params (now):' + spaceghost.jsonStr( params ) );
|
|
return this.api._ajax( utils.format( this.urlTpls.show, id ), {
|
|
data : params
|
|
});
|
|
};
|
|
|
|
HistoriesAPI.prototype.create = function create( payload ){
|
|
this.api.spaceghost.info( 'histories.create: ' + this.api.spaceghost.jsonStr( payload ) );
|
|
|
|
// py.payload <-> ajax.data
|
|
payload = this.api.ensureObject( payload );
|
|
return this.api._ajax( utils.format( this.urlTpls.create ), {
|
|
type : 'POST',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
HistoriesAPI.prototype.delete_ = function delete_( id, purge ){
|
|
this.api.spaceghost.info( 'histories.delete: ' + [ id, (( purge )?( '(purge!)' ):( '' )) ] );
|
|
|
|
// py.payload <-> ajax.data
|
|
var url = utils.format( this.urlTpls.delete_, this.api.ensureId( id ) );
|
|
if( purge ){
|
|
url += '?purge=True';
|
|
}
|
|
return this.api._ajax( url, {
|
|
type : 'DELETE'
|
|
});
|
|
};
|
|
|
|
HistoriesAPI.prototype.undelete = function undelete( id ){
|
|
//throw ( 'unimplemented' );
|
|
this.api.spaceghost.info( 'histories.undelete: ' + id );
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.undelete, this.api.ensureId( id ) ), {
|
|
type : 'POST'
|
|
});
|
|
};
|
|
|
|
HistoriesAPI.prototype.update = function update( id, payload ){
|
|
this.api.spaceghost.info( 'histories.update: ' + id + ',' + this.api.spaceghost.jsonStr( payload ) );
|
|
|
|
// py.payload <-> ajax.data
|
|
id = this.api.ensureId( id );
|
|
payload = this.api.ensureObject( payload );
|
|
url = utils.format( this.urlTpls.update, id );
|
|
|
|
return this.api._ajax( url, {
|
|
type : 'PUT',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
|
|
// =================================================================== HDAS
|
|
var HDAAPI = function HDAAPI( api ){
|
|
this.api = api;
|
|
};
|
|
HDAAPI.prototype.toString = function toString(){
|
|
return this.api + '.HDAAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
HDAAPI.prototype.urlTpls = {
|
|
index : '/api/histories/%s/contents',
|
|
show : '/api/histories/%s/contents/%s',
|
|
create : '/api/histories/%s/contents',
|
|
update : '/api/histories/%s/contents/%s'
|
|
};
|
|
|
|
HDAAPI.prototype.index = function index( historyId, ids ){
|
|
this.api.spaceghost.info( 'hdas.index: ' + [ historyId, ids ] );
|
|
var data = {};
|
|
if( ids ){
|
|
ids = ( utils.isArray( ids ) )?( ids.join( ',' ) ):( ids );
|
|
data.ids = ids;
|
|
}
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.index, this.api.ensureId( historyId ) ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
HDAAPI.prototype.show = function show( historyId, id, deleted ){
|
|
this.api.spaceghost.info( 'hdas.show: ' + [ historyId, id, (( deleted )?( 'w/deleted' ):( '' )) ] );
|
|
|
|
id = ( id === 'most_recently_used' )?( id ):( this.api.ensureId( id ) );
|
|
deleted = deleted || false;
|
|
return this.api._ajax( utils.format( this.urlTpls.show, this.api.ensureId( historyId ), id ), {
|
|
data : { deleted: deleted }
|
|
});
|
|
};
|
|
|
|
HDAAPI.prototype.create = function create( historyId, payload ){
|
|
this.api.spaceghost.info( 'hdas.create: ' + [ historyId, this.api.spaceghost.jsonStr( payload ) ] );
|
|
|
|
// py.payload <-> ajax.data
|
|
payload = this.api.ensureObject( payload );
|
|
return this.api._ajax( utils.format( this.urlTpls.create, this.api.ensureId( historyId ) ), {
|
|
type : 'POST',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
HDAAPI.prototype.update = function create( historyId, id, payload ){
|
|
this.api.spaceghost.info( 'hdas.update: ' + [ historyId, id, this.api.spaceghost.jsonStr( payload ) ] );
|
|
|
|
// py.payload <-> ajax.data
|
|
historyId = this.api.ensureId( historyId );
|
|
id = this.api.ensureId( id );
|
|
payload = this.api.ensureObject( payload );
|
|
url = utils.format( this.urlTpls.update, historyId, id );
|
|
|
|
return this.api._ajax( url, {
|
|
type : 'PUT',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
HDAAPI.prototype.delete_ = function create( historyId, id, purge ){
|
|
this.api.spaceghost.info( 'hdas.delete_: ' + [ historyId, id ] );
|
|
historyId = this.api.ensureId( historyId );
|
|
id = this.api.ensureId( id );
|
|
|
|
// have to attach like GET param - due to body loss in jq
|
|
url = utils.format( this.urlTpls.update, historyId, id );
|
|
if( purge ){
|
|
url += '?purge=True';
|
|
}
|
|
return this.api._ajax( url, {
|
|
type : 'DELETE'
|
|
});
|
|
};
|
|
|
|
//TODO: delete_
|
|
|
|
|
|
// =================================================================== HDAS
|
|
var DatasetsAPI = function DatasetsAPI( api ){
|
|
this.api = api;
|
|
};
|
|
DatasetsAPI.prototype.toString = function toString(){
|
|
return this.api + '.DatasetsAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
DatasetsAPI.prototype.urlTpls = {
|
|
index : '/api/datasets',
|
|
show : '/api/datasets/%s',
|
|
// wut.
|
|
display : '/api/histories/%s/contents/%s/display'
|
|
};
|
|
|
|
DatasetsAPI.prototype.index = function index(){
|
|
this.api.spaceghost.info( 'datasets.index: ' );
|
|
var data = {};
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.index ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
DatasetsAPI.prototype.show = function show( id ){
|
|
this.api.spaceghost.info( 'datasets.show: ' + [ id ] );
|
|
var data = {};
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.show, id ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
DatasetsAPI.prototype.display = function show( historyId, id, params ){
|
|
this.api.spaceghost.info( 'datasets.display: ' + [ historyId, id ] );
|
|
if( params === undefined ){
|
|
params = {};
|
|
}
|
|
return this.api._ajax( utils.format( this.urlTpls.display, this.api.ensureId( historyId ), id ), {
|
|
data : params,
|
|
dataType : 'text'
|
|
});
|
|
};
|
|
|
|
|
|
|
|
// =================================================================== TOOLS
|
|
var ToolsAPI = function ToolsAPI( api ){
|
|
this.api = api;
|
|
};
|
|
ToolsAPI.prototype.toString = function toString(){
|
|
return this.api + '.ToolsAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
ToolsAPI.prototype.urlTpls = {
|
|
index : '/api/tools',
|
|
show : '/api/tools/%s',
|
|
create : '/api/tools'
|
|
};
|
|
|
|
ToolsAPI.prototype.index = function index( in_panel, trackster ){
|
|
this.api.spaceghost.info( 'tools.index: ' + [ in_panel, trackster ] );
|
|
var data = {};
|
|
// in_panel defaults to true, trackster defaults to false
|
|
if( in_panel !== undefined ){
|
|
data.in_panel = ( in_panel )?( true ):( false );
|
|
}
|
|
if( in_panel !== undefined ){
|
|
data.trackster = ( trackster )?( true ):( false );
|
|
}
|
|
return this.api._ajax( utils.format( this.urlTpls.index ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
ToolsAPI.prototype.show = function show( id ){
|
|
this.api.spaceghost.info( 'tools.show: ' + [ id ] );
|
|
var data = {};
|
|
|
|
data.io_details = true;
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.show, id ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
ToolsAPI.prototype.create = function create( payload ){
|
|
this.api.spaceghost.info( 'tools.create: ' + [ this.api.spaceghost.jsonStr( payload ) ] );
|
|
|
|
// py.payload <-> ajax.data
|
|
payload = this.api.ensureObject( payload );
|
|
return this.api._ajax( utils.format( this.urlTpls.create ), {
|
|
type : 'POST',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
//ToolsAPI.prototype.uploadByForm = function upload( historyId, options ){
|
|
// this.api.spaceghost.debug( '-------------------------------------------------' );
|
|
// this.api.spaceghost.info( 'tools.upload: ' + [ historyId, '(contents)', this.api.spaceghost.jsonStr( options ) ] );
|
|
// this.api.ensureId( historyId );
|
|
// options = options || {};
|
|
//
|
|
// this.api.spaceghost.evaluate( function( url ){
|
|
// var html = [
|
|
// '<form action="', url, '" method="post" enctype="multipart/form-data">',
|
|
// '<input type="file" name="files_0|file_data">',
|
|
// '<input type="hidden" name="tool_id" />',
|
|
// '<input type="hidden" name="history_id" />',
|
|
// '<input type="hidden" name="inputs" />',
|
|
// '<button type="submit">Submit</button>',
|
|
// '</form>'
|
|
// ];
|
|
// document.write( html.join('') );
|
|
// //document.getElementsByTagName( 'body' )[0].innerHTML = html.join('');
|
|
// }, utils.format( this.urlTpls.create ) );
|
|
//
|
|
// this.api.spaceghost.fill( 'form', {
|
|
// 'files_0|file_data' : '1.txt',
|
|
// 'tool_id' : 'upload1',
|
|
// 'history_id' : historyId,
|
|
// 'inputs' : JSON.stringify({
|
|
// 'file_type' : 'auto',
|
|
// 'files_0|type' : 'upload_dataset',
|
|
// 'to_posix_lines' : true,
|
|
// 'space_to_tabs' : false,
|
|
// 'dbkey' : '?'
|
|
// })
|
|
// }, true );
|
|
// // this causes the page to switch...I think
|
|
//};
|
|
|
|
/** paste a file - either from a string (options.paste) or from a filesystem file (options.filepath) */
|
|
ToolsAPI.prototype.uploadByPaste = function upload( historyId, options ){
|
|
this.api.spaceghost.info( 'tools.upload: ' + [ historyId, this.api.spaceghost.jsonStr( options ) ] );
|
|
this.api.ensureId( historyId );
|
|
options = options || {};
|
|
|
|
var inputs = {
|
|
'files_0|NAME' : options.name || 'Test Dataset',
|
|
'dbkey' : options.dbkey || '?',
|
|
'file_type' : options.ext || 'auto'
|
|
};
|
|
if( options.filepath ){
|
|
var fs = require( 'fs' );
|
|
inputs[ 'files_0|url_paste' ] = fs.read( options.filepath );
|
|
|
|
} else if( options.paste ){
|
|
inputs[ 'files_0|url_paste' ] = options.paste;
|
|
}
|
|
if( options.posix ){
|
|
inputs[ 'files_0|to_posix_lines' ] = 'Yes';
|
|
}
|
|
if( options.tabs ){
|
|
inputs[ 'files_0|space_to_tab' ] = 'Yes';
|
|
}
|
|
return this.api._ajax( utils.format( this.urlTpls.create ), {
|
|
type : 'POST',
|
|
data : {
|
|
tool_id : 'upload1',
|
|
upload_type : 'upload_dataset',
|
|
history_id : historyId,
|
|
inputs : inputs
|
|
}
|
|
});
|
|
};
|
|
|
|
/** post a file to the upload1 tool over ajax */
|
|
ToolsAPI.prototype.upload = function upload( historyId, options ){
|
|
this.api.spaceghost.info( 'api.tools.upload: ' + [ historyId, this.api.spaceghost.jsonStr( options ) ] );
|
|
this.api.ensureId( historyId );
|
|
options = options || {};
|
|
|
|
// We can post an upload using jquery and formdata (see below), the more
|
|
// difficult part is attaching the file without user intervention.
|
|
// To do this we need to (unfortunately) create a form phantom can attach the file to first.
|
|
this.api.spaceghost.evaluate( function(){
|
|
$( 'body' ).append( '<input type="file" name="casperjs-upload-file" />' );
|
|
});
|
|
this.api.spaceghost.page.uploadFile( 'input[name="casperjs-upload-file"]', options.filepath );
|
|
|
|
var inputs = {
|
|
'file_type' : options.ext || 'auto',
|
|
'files_0|type' : 'upload_dataset',
|
|
'dbkey' : options.dbkey || '?'
|
|
};
|
|
if( options.posix ){
|
|
inputs[ 'files_0|to_posix_lines' ] = 'Yes';
|
|
}
|
|
if( options.tabs ){
|
|
inputs[ 'files_0|space_to_tab' ] = 'Yes';
|
|
}
|
|
|
|
var response = this.api.spaceghost.evaluate( function( url, historyId, inputs ){
|
|
var file = $( 'input[name="casperjs-upload-file"]' )[0].files[0],
|
|
formData = new FormData();
|
|
|
|
formData.append( 'files_0|file_data', file );
|
|
formData.append( 'history_id', historyId );
|
|
formData.append( 'tool_id', 'upload1' );
|
|
formData.append( 'inputs', JSON.stringify( inputs ) );
|
|
return $.ajax({
|
|
url : url,
|
|
async : false,
|
|
type : 'POST',
|
|
data : formData,
|
|
// when sending FormData don't have jq process or cache the data
|
|
cache : false,
|
|
contentType : false,
|
|
processData : false,
|
|
// if we don't add this, payload isn't processed as JSON
|
|
headers : { 'Accept': 'application/json' }
|
|
});
|
|
}, utils.format( this.urlTpls.create ), historyId, inputs );
|
|
|
|
if( response.status !== 200 ){
|
|
// grrr... this doesn't lose the \n\r\t
|
|
//throw new APIError( response.responseText.replace( /[\s\n\r\t]+/gm, ' ' ).replace( /"/, '' ) );
|
|
this.api.spaceghost.debug( 'API error: code: ' + response.status + ', response:\n' +
|
|
( response.responseJSON? this.api.spaceghost.jsonStr( response.responseJSON ) : response.responseText ) );
|
|
throw new APIError( response.responseText, response.status );
|
|
}
|
|
return JSON.parse( response.responseText );
|
|
};
|
|
|
|
/** amount of time allowed to upload a file (before erroring) */
|
|
ToolsAPI.prototype.DEFAULT_UPLOAD_TIMEOUT = 30 * 1000;
|
|
|
|
/** add two casperjs steps - upload a file, wait for the job to complete, and run 'then' when they are */
|
|
ToolsAPI.prototype.thenUpload = function thenUpload( historyId, options, then ){
|
|
var spaceghost = this.api.spaceghost,
|
|
uploadedId;
|
|
|
|
// upload via the api
|
|
spaceghost.then( function(){
|
|
var returned = this.api.tools.upload( historyId, options );
|
|
this.debug( 'returned: ' + this.jsonStr( returned ) );
|
|
uploadedId = returned.outputs[0].id;
|
|
this.debug( 'uploadedId: ' + uploadedId );
|
|
});
|
|
|
|
spaceghost.then( function(){
|
|
var hda = null;
|
|
this.waitFor(
|
|
function testHdaState(){
|
|
hda = spaceghost.api.hdas.show( historyId, uploadedId );
|
|
spaceghost.debug( spaceghost.jsonStr( hda.state ) );
|
|
return !( hda.state === 'upload' || hda.state === 'queued' || hda.state === 'running' );
|
|
},
|
|
function _then(){
|
|
spaceghost.info( 'upload finished: ' + uploadedId );
|
|
if( then ){
|
|
then.call( spaceghost, uploadedId, hda );
|
|
}
|
|
//var hda = spaceghost.api.hdas.show( historyId, uploadedId );
|
|
//spaceghost.debug( spaceghost.jsonStr( hda ) );
|
|
},
|
|
function timeout(){
|
|
throw new APIError( 'timeout uploading file', 408 );
|
|
},
|
|
options.timeout || spaceghost.api.tools.DEFAULT_UPLOAD_TIMEOUT
|
|
);
|
|
});
|
|
return spaceghost;
|
|
};
|
|
|
|
/** add two casperjs steps - upload multiple files (described in optionsArray) and wait for all jobs to complete */
|
|
ToolsAPI.prototype.thenUploadMultiple = function thenUploadMultiple( historyId, optionsArray, then ){
|
|
var spaceghost = this.api.spaceghost,
|
|
uploadedIds = [];
|
|
|
|
this.api.spaceghost.then( function(){
|
|
var spaceghost = this;
|
|
optionsArray.forEach( function( options ){
|
|
var returned = spaceghost.api.tools.upload( historyId, options );
|
|
spaceghost.debug( 'uploaded:' + spaceghost.jsonStr( returned ) );
|
|
uploadedIds.push( returned.outputs[0].id );
|
|
});
|
|
});
|
|
|
|
// wait for every hda to finish running - IOW, don't use uploadedIds
|
|
this.api.spaceghost.then( function(){
|
|
this.debug( this.jsonStr( uploadedIds ) );
|
|
this.waitFor(
|
|
function testHdaStates(){
|
|
var hdas = spaceghost.api.hdas.index( historyId ),
|
|
running = hdas.filter( function( hda ){
|
|
return ( hda.state === 'upload' || hda.state === 'queued' || hda.state === 'running' );
|
|
}).map( function( hda ){
|
|
return hda.id;
|
|
});
|
|
//spaceghost.debug( 'still uploading: ' + spaceghost.jsonStr( running ) );
|
|
return running.length === 0;
|
|
},
|
|
function _then(){
|
|
var hdas = spaceghost.api.hdas.index( historyId );
|
|
spaceghost.debug( spaceghost.jsonStr( hdas ) );
|
|
if( then ){
|
|
then.call( spaceghost, uploadedIds );
|
|
}
|
|
},
|
|
function timeout(){
|
|
throw new APIError( 'timeout uploading files', 408 );
|
|
},
|
|
( options.timeout || spaceghost.api.tools.DEFAULT_UPLOAD_TIMEOUT ) * optionsArray.length
|
|
);
|
|
});
|
|
return spaceghost;
|
|
};
|
|
|
|
|
|
/** get the current history's id, then upload there */
|
|
ToolsAPI.prototype.thenUploadToCurrent = function thenUploadToCurrent( options, then ){
|
|
var spaceghost = this.api.spaceghost;
|
|
return spaceghost.then( function(){
|
|
var currentHistoryId = this.api.histories.index()[0].id;
|
|
spaceghost.api.tools.thenUpload( currentHistoryId, options, then );
|
|
});
|
|
};
|
|
|
|
|
|
// =================================================================== WORKFLOWS
|
|
var WorkflowsAPI = function WorkflowsAPI( api ){
|
|
this.api = api;
|
|
};
|
|
WorkflowsAPI.prototype.toString = function toString(){
|
|
return this.api + '.WorkflowsAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
WorkflowsAPI.prototype.urlTpls = {
|
|
index : '/api/workflows',
|
|
show : '/api/workflows/%s',
|
|
// run a workflow
|
|
create : '/api/workflows',
|
|
update : '/api/workflows/%s',
|
|
|
|
upload : '/api/workflows/upload', // POST
|
|
download: '/api/workflows/download/%s' // GET
|
|
};
|
|
|
|
WorkflowsAPI.prototype.index = function index(){
|
|
this.api.spaceghost.info( 'workflows.index: ' + [] );
|
|
var data = {};
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.index ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
WorkflowsAPI.prototype.show = function show( id ){
|
|
this.api.spaceghost.info( 'workflows.show: ' + [ id ] );
|
|
var data = {};
|
|
|
|
id = ( id === 'most_recently_used' )?( id ):( this.api.ensureId( id ) );
|
|
return this.api._ajax( utils.format( this.urlTpls.show, this.api.ensureId( id ) ), {
|
|
data : data
|
|
});
|
|
};
|
|
|
|
WorkflowsAPI.prototype.create = function create( payload ){
|
|
this.api.spaceghost.info( 'workflows.create: ' + [ this.api.spaceghost.jsonStr( payload ) ] );
|
|
|
|
// py.payload <-> ajax.data
|
|
payload = this.api.ensureObject( payload );
|
|
return this.api._ajax( utils.format( this.urlTpls.create ), {
|
|
type : 'POST',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
WorkflowsAPI.prototype.upload = function create( workflowJSON ){
|
|
this.api.spaceghost.info( 'workflows.upload: ' + [ this.api.spaceghost.jsonStr( workflowJSON ) ] );
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.upload ), {
|
|
type : 'POST',
|
|
data : { 'workflow': this.api.ensureObject( workflowJSON ) }
|
|
});
|
|
};
|
|
|
|
|
|
// =================================================================== USERS
|
|
var UsersAPI = function UsersAPI( api ){
|
|
this.api = api;
|
|
};
|
|
UsersAPI.prototype.toString = function toString(){
|
|
return this.api + '.UsersAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
//NOTE: lots of admin only functionality in this section
|
|
UsersAPI.prototype.urlTpls = {
|
|
index : '/api/users',
|
|
show : '/api/users/%s',
|
|
create : '/api/users',
|
|
delete_ : '/api/users/%s',
|
|
undelete: '/api/users/deleted/%s/undelete',
|
|
update : '/api/users/%s'
|
|
};
|
|
|
|
UsersAPI.prototype.index = function index( deleted ){
|
|
this.api.spaceghost.info( 'users.index: ' + (( deleted )?( 'w deleted' ):( '(wo deleted)' )) );
|
|
|
|
deleted = deleted || false;
|
|
return this.api._ajax( this.urlTpls.index, {
|
|
data : { deleted: deleted }
|
|
});
|
|
};
|
|
|
|
UsersAPI.prototype.show = function show( id, deleted ){
|
|
this.api.spaceghost.info( 'users.show: ' + [ id, (( deleted )?( 'w deleted' ):( '' )) ] );
|
|
|
|
id = ( id === 'current' )?( id ):( this.api.ensureId( id ) );
|
|
deleted = deleted || false;
|
|
return this.api._ajax( utils.format( this.urlTpls.show, id ), {
|
|
data : { deleted: deleted }
|
|
});
|
|
};
|
|
|
|
UsersAPI.prototype.create = function create( payload ){
|
|
this.api.spaceghost.info( 'users.create: ' + this.api.spaceghost.jsonStr( payload ) );
|
|
|
|
// py.payload <-> ajax.data
|
|
payload = this.api.ensureObject( payload );
|
|
return this.api._ajax( utils.format( this.urlTpls.create ), {
|
|
type : 'POST',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
UsersAPI.prototype.delete_ = function delete_( id, purge ){
|
|
this.api.spaceghost.info( 'users.delete: ' + [ id, (( purge )?( '(purge!)' ):( '' )) ] );
|
|
|
|
// py.payload <-> ajax.data
|
|
var payload = ( purge )?({ purge: true }):({});
|
|
return this.api._ajax( utils.format( this.urlTpls.delete_, this.api.ensureId( id ) ), {
|
|
type : 'DELETE',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
UsersAPI.prototype.undelete = function undelete( id ){
|
|
//throw ( 'unimplemented' );
|
|
this.api.spaceghost.info( 'users.undelete: ' + id );
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.undelete, this.api.ensureId( id ) ), {
|
|
type : 'POST'
|
|
});
|
|
};
|
|
|
|
UsersAPI.prototype.update = function create( id, payload ){
|
|
this.api.spaceghost.info( 'users.update: ' + id + ',' + this.api.spaceghost.jsonStr( payload ) );
|
|
|
|
// py.payload <-> ajax.data
|
|
id = this.api.ensureId( id );
|
|
payload = this.api.ensureObject( payload );
|
|
url = utils.format( this.urlTpls.update, id );
|
|
|
|
return this.api._ajax( url, {
|
|
type : 'PUT',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
|
|
// =================================================================== VISUALIZATIONS
|
|
var VisualizationsAPI = function VisualizationsAPI( api ){
|
|
this.api = api;
|
|
};
|
|
VisualizationsAPI.prototype.toString = function toString(){
|
|
return this.api + '.VisualizationsAPI';
|
|
};
|
|
|
|
// -------------------------------------------------------------------
|
|
VisualizationsAPI.prototype.urlTpls = {
|
|
index : '/api/visualizations',
|
|
show : '/api/visualizations/%s',
|
|
create : '/api/visualizations',
|
|
//delete_ : '/api/visualizations/%s',
|
|
//undelete: '/api/visualizations/deleted/%s/undelete',
|
|
update : '/api/visualizations/%s'
|
|
};
|
|
|
|
VisualizationsAPI.prototype.index = function index(){
|
|
this.api.spaceghost.info( 'visualizations.index' );
|
|
|
|
return this.api._ajax( this.urlTpls.index );
|
|
};
|
|
|
|
VisualizationsAPI.prototype.show = function show( id ){
|
|
this.api.spaceghost.info( 'visualizations.show' );
|
|
|
|
return this.api._ajax( utils.format( this.urlTpls.show, this.api.ensureId( id ) ) );
|
|
};
|
|
|
|
VisualizationsAPI.prototype.create = function create( payload ){
|
|
this.api.spaceghost.info( 'visualizations.create: ' + this.api.spaceghost.jsonStr( payload ) );
|
|
|
|
// py.payload <-> ajax.data
|
|
payload = this.api.ensureObject( payload );
|
|
return this.api._ajax( utils.format( this.urlTpls.create ), {
|
|
type : 'POST',
|
|
data : payload
|
|
});
|
|
};
|
|
|
|
VisualizationsAPI.prototype.update = function create( id, payload ){
|
|
this.api.spaceghost.info( 'visualizations.update: ' + id + ',' + this.api.spaceghost.jsonStr( payload ) );
|
|
|
|
// py.payload <-> ajax.data
|
|
id = this.api.ensureId( id );
|
|
payload = this.api.ensureObject( payload );
|
|
url = utils.format( this.urlTpls.update, id );
|
|
|
|
return this.api._ajax( url, {
|
|
type : 'PUT',
|
|
data : payload
|
|
});
|
|
};
|