Commits

Joel Rivera committed b9ee4fe

Improvements on the UI for the GO catalog browsing

  • Participants
  • Parent commits 9461171

Comments (0)

Files changed (3)

File lib/galaxy/webapps/globusonline/catalogbrw.py

+import json
 import logging
+import functools
+
+import requests
 
 from galaxy import web
 from galaxy.web.base.controller import BaseUIController
+from galaxy.web.framework.ext.globus import storage 
 
 log = logging.getLogger(__name__)
 
 
 class CatalogAPI(object):
-    DEFAULT_SERVER = 'graph.api.test.globuscs.info'
+    AUTH_SERVER = 'graph.api.test.globuscs.info'
     AUTH_URL = '/goauth/token?grant_type=client_credentials'
+    DS_SERVER  = 'datasets.globuscs.info'
+    DS_BASE_URI = '/tagfiler/catalog'
+    PROTOCOL = 'https'
 
 
-    def __init__(self, catalog, user, passwd, catalog_id=1, server=None,
-                 validate_certs=True):
-        self.user = user
-        self.passwd = passwd
+    def __init__(self, gouser, gopasswd='', gotoken=None, catalog_id=1,
+                 auth_server=None, ds_server=None, verify_certs=False):
+        self.user = gouser
+        self.passwd = gopasswd
         self.catalog_id = catalog_id
-        self.goauth = None
-        self.validate_certs = validate_certs
-        if server is None:
-            self.server = self.DEFAULT_SERVER
-        self.server_url = 'https://{0}{1}'.format(self.server, self.AUTH_URL)
+        self.gotoken = gotoken
+        self.verify_certs = verify_certs
+        if auth_server is None:
+            self.auth_server = self.AUTH_SERVER
+        if ds_server is None:
+            self.ds_server = self.DS_SERVER
+        self.auth_server_url = '{0}://{1}{2}'.format(
+            self.PROTOCOL,self.auth_server, self.AUTH_URL)
+        self.ds_server_url = '{0}://{1}{2}/{3}'.format(
+            self.PROTOCOL, self.ds_server, self.DS_BASE_URI,
+            self.catalog_id)
 
     def _login(self):
-        pass
+        auth = requests.auth.HTTPBasicAuth(self.user, self.passwd)
+        response = requests.get(self.auth_server_url,
+                                auth=auth, verify=self.verify_certs)
+        if response.ok:
+            self.gotoken= response.json['access_token']
+            return  True
+        else:
+            return False
 
-    def login(self):
-        if self.goauth is None:
-            self._login()
+    @property
+    def auth_request(self):
+        if self.gotoken is None:
+            raise Exception('Unable to get authenticated request, '
+                            'the instance does not have an access code.')
+        else:
+            return functools.partial(requests.get,  verify=self.verify_certs, 
+                                     headers={
+                                         'Authorization': 
+                                         'Globus-Goauthtoken %s' % self.gotoken})
 
-    def list(self):
-        pass
+    def auth_get(self, url_part, is_part=True):
+        if is_part:
+            url = self.ds_server_url + url_part
+        else:
+            url = url_part
+        return self.auth_request(url)
+
+    def login(self, validate=True):
+        if validate:
+            if self.gotoken is None:
+                return self._login()
+            else:
+                return True
+        else:
+            return self._login()
+
+    def query(self,  attributes):
+        resp = self.auth_get('/subject/{0}'.format(attributes))
+        if resp.ok:
+            return resp.json
+        else:
+            raise Exception('Invalid request %s' % resp.text)
 
 
 class CatalogBrowser(BaseUIController):
+    CRED_KEY = 'GO_CREDENTIALS'
+
+
+    def api(self, trans):
+        try:
+            cred = storage.get(trans, self.CRED_KEY)
+        except KeyError:
+            raise Exception('Mission credentials')
+        else:
+            return CatalogAPI(**cred)
+
+    @web.expose_api
+    def have_credentials(self, trans):
+        try:
+            cred = storage.get(trans, self.CRED_KEY)
+            return cred['gouser']
+        except KeyError:
+            return False
 
     @web.expose_api
     def credentials(self, trans, token):
-        return {'go_user': 'leuser', 
-                'go_token': 'letoken',
-                'bs_access': 'basespace access'}
-
+        try:
+            cred = storage.get(trans, self.CRED_KEY)
+        except KeyError:
+            raise Exception("Missing credentials in session")
+        else:
+            data = cred.copy()
+            data['bsaccess'] = 'basespace_access_token'
+            return data
     
     @web.expose_api
     def authenticate(self, trans, gouser, gopasswd, payload=None):
-        return "Authenticate"
-
+        api = CatalogAPI(gouser, gopasswd)
+        if api.login():
+            storage.set(trans, self.CRED_KEY, 
+                        {'gouser': gouser,
+                         'gotoken': api.gotoken})
+            return True
+        else:
+            return False
 
     @web.expose_api
     def get_dataset(self, trans):
         pass
 
     @web.expose_api        
-    def list_datasets(self, query=None):
-        pass
+    def list_datasets(self, trans, q='dataset_name'):
+        props = '(SampleName;id;DateCreated;owner)'
+        api = self.api(trans)
+        return list(self._format_listing_output(api.query(q + props)))
+
+    def _format_listing_output(self, results):
+        for r in  results:
+            yield {'name': r['SampleName'],
+                   'id': r['id'],
+                   'date': r['DateCreated'],
+                   'owner': r['owner']}
+        
+ 
+        
+        
   
      

File static/globus/catalog.js

 (function($, window, globalwin, undefined) {
 
+    function clear_form ($form) {
+	$form.find(':input').each(function(){
+	    switch(this.type) {
+	    case 'password':
+	    case 'select-multiple':
+	    case 'select-one':
+	    case 'text':
+	    case 'textarea':
+		$(this).val('');
+		break;
+	    case 'checkbox':
+	    case 'radio':
+		this.checked = false;
+	    }
+	});
+    }
 
-    function inform_of_current_credentials() {
+
+    var modal_id = 'askpasswd';
+    var mod_rsp_seltor = '#' + modal_id + ' p.rspmsg';
+    var modal_action = '/globusonline/catalog/browser/authenticate';
+
+    function tabulate_results(results) {
+	$('#datasets-table').detach();
+	var $table = $('<table class="table" id="datasets-table"></table>');
+	$table.append('<thead> ' +
+	    '<tr>' +
+	       '<th>Id</th>' + 
+	       '<th>Name</th>' + 
+	       '<th>Date</th>' + 
+	       '<th>Owner</th>' + 
+	    '</tr>' +
+	'</thead>');
+	var cols, tbody = new Array();
+	$.each(results, function(idx, elem){
+	    cols = '<td>' + elem.id +'</td>' +
+		'<td>' + elem.name +'</td>' +
+		'<td>' + elem.date +'</td>' +
+		'<td>' + elem.owner +'</td>';
+	    tbody.push('<tr>' + cols + '</tr>');
+	});
+	$table.append($('<tbody>' +  tbody.join('\n') + '</tbody>'));
+	$('input[name=path]').after($table);
+    }
+
+
+
+    function inform_of_current_credentials(user) {
+	var banner = '<p>' + 
+	    'Logged in as: <strong>' + user + '</strong>' +
+	    '</p>';
+	$('label[for=query]').before(banner);
+    }
+
+    function show_ask_for_credentials () {
+	console.log('Show ask for credentials');
+    	write_modal_rspmsg('Please specify your ' +
+			   '<strong>GO Catalog Credentials</strong>');
+	$('#' + modal_id + ' form').submit(function (e) {
+	    write_modal_rspmsg('Validating... ' +
+			       '<img src="/static/globus/vendor/select2/' +
+			       'select2-spinner.gif"/>', {reset: true});
+	    var $form = $(e.target);
+	    $.post($form.attr('action'), $form.serialize(),
+		   function (resp) {
+		       if (resp) {
+			   inform_of_current_credentials($('input[name=gouser]', 
+							   $form).val());
+			   clear_form($form);
+			   $.modal.close();
+		       } else {
+			   write_modal_rspmsg("Invalid credentials",
+					      {is_error_msg: true});
+		       }
+		   }
+		  );
+	    return false;
+
+	});
+	reset_modal_rspmsg();
+	$('#' + modal_id).modal();
 
     }
 
-    function show_ask_for_credentials () {
-
-    }
     
-    function _have_credentials(cb) {
-
-    }
-
     function _hide_exec(){
 	$('input[name=runtool_btn]').hide()
     }
 	$('input[name=runtool_btn]').show()
     }
 
+
+
+    function reset_modal_rspmsg () {
+	$(mod_rsp_seltor).empty();
+	$(mod_rsp_seltor).css({'color': 'black',
+			       'font-weight': 'normal'});
+    }
+    
+    function write_modal_rspmsg (msg, args) {
+	if (args === undefined) {
+	    var args = {};
+	}
+	if (args.is_error_msg !== undefined && args.is_error_msg) {
+	    $(mod_rsp_seltor).css({'color': 'red',
+				   'font-weight': 'bold'});
+	}
+	if (args.reset !== undefined  && args.reset) {
+	    reset_modal_rspmsg();
+	}
+	$(mod_rsp_seltor).html(msg);
+    }
+
+       
+    
+    /*
+      This function will detach the  modal wrap the fields
+      `div` and append that at the just before the closing `body` tag.
+      One of the reason to do this is because we can't have nested forms,
+      and we are already in one (the tool itself).
+    */
+    function _setup_modal () {
+	var $fields = $('#' + modal_id + ' > table');
+	var $apmod = $('#' + modal_id);
+	var $form = $('<form action="'+ modal_action + '" method="POST"> </form>');
+	$fields.detach();
+	$apmod.detach();
+	$form.append($fields)
+	$apmod.append($form);
+	$('body').append($apmod);
+    }
+    
     function check_credentials () {
-	$.get('/globus/catalog/credentials',
-	      function (resp){
-		  if (resp !== null) {
+	$.get('/globusonline/catalog/browser/have_credentials',
+	      function (resp) {
+		  if (resp !== false) {
 		      inform_of_current_credentials(resp);
 		  } else {
 		      show_ask_for_credentials();
 	      });
     }
 
-    function login(){
-	
+    function execute_query () {
+	var query = $('input[name=query]').val();
+	var params = {}
+	if (query.replace(' ', '') != '') {
+	    params['q'] = query;
+	}
+	$.get('/globusonline/catalog/browser/list_datasets',
+	      params, function (resp){
+		  tabulate_results(resp);
+	      });
+    }
+
+
+    function _setup_query_btn () {
+	var $btn  = $('<input class="btn btn-info" style="margin-left: 12px;"' + 
+	              'type="button" value="Execute query" />');
+	$btn.click(function(e){   execute_query();});
+	$('input[name=query]').after($btn);
+	$(window).keydown(function(event){
+	    var $target = $(event.target);
+	    if (event.keyCode == 13) {
+		if ($target.attr('name') == 'query') {
+		    execute_query();
+		} 
+		if (!(($target.attr('value') == 'Execute query') ||
+		      ($target.parents('#askpasswd').length > 0))) {
+		    event.preventDefault();
+		    return false;
+		}		    
+		
+	    }
+	});
     }
 
     function setup() {
+	_hide_exec();
+	_setup_query_btn();
+	_setup_modal();
 	check_credentials();
 
     }

File tools/globus/catalog.xml

 <tool id="globus_catalog" name="Catalog"
       tool_type="globus_datasource" >
-   <description>Transfer a single file from illumina</description>
+   <description>Fetch datasets from the Globus Online Catalog.</description>
    <command interpreter="python">
    </command>
    <inputs>
      <data name="outfile" type="data" format="txt" />
    </outputs>
    <help>
-     Browse and fetch datasets from the GlobusOnline catalog.
+     Fetch datasets from the Globus Online Catalog.
    </help>
 </tool>