diff --git a/js/app/controllers/EpnTapModule.js b/js/app/controllers/EpnTapModule.js index e875f47..e6f98cd 100644 --- a/js/app/controllers/EpnTapModule.js +++ b/js/app/controllers/EpnTapModule.js @@ -58,7 +58,7 @@ Ext.define('amdaDesktop.EpnTapModule', { this.targetNamesStore = Ext.data.StoreManager.lookup('targetNamesStore'); }, - addUIListeners: function() { + addListeners: function() { this.targetNameCB.on('change', function() { this.updateGetBtnStatus(); }, this); @@ -101,7 +101,7 @@ Ext.define('amdaDesktop.EpnTapModule', { loadTarget: function(target) { this.target = target; this.aquireElements(); - this.addUIListeners(); + this.addListeners(); // this.servicesStore.clearFilter(); this.granulesStore.removeAll(); @@ -145,6 +145,7 @@ Ext.define('amdaDesktop.EpnTapModule', { 'timeMin': timeMin, 'timeMax': timeMax }, + // timeout: 3000, success: this.updateNbResults, failure: this.updateNbResultsFail, scope: this @@ -191,30 +192,22 @@ Ext.define('amdaDesktop.EpnTapModule', { }, onPageChanged: function() { - var myProxy = this.granulesStore.getProxy(); - myProxy.params = this.getGranuleParams(); - myProxy.extraParams = this.getGranuleParams(); - // //--- Set value to your parameter ----// - // myProxy.setExtraParam('url', this.selectedService.data['access_url']); - // myProxy.setExtraParam('MENU_DETAIL', '555555'); + this.granulesStore.getProxy().extraParams = this.getGranuleParams(); }, + /** Trigerred when a row is clicked in `servicesGrid` table (see `EpnTapUI.createServicesGrid()`). Among other things, send a new query and fill `granulesGrid`. */ onServiceSelected: function(record) { + // Ext.Ajax.abortAll(); this.selectedService = record; var nbRes = this.selectedService.get('nb_results'); if(nbRes > 0 && !isNaN(nbRes)) { - loadMask.show(); this.granulesStore.load({ params: this.getGranuleParams(), start: 0, limit: this.granulesStore.pageSize, - callback: function(records, operation, success) { - console.log(records, operation); - loadMask.hide(); - }, scope: this }); } diff --git a/js/app/views/EpnTapUI.js b/js/app/views/EpnTapUI.js index 337da87..73e219a 100644 --- a/js/app/views/EpnTapUI.js +++ b/js/app/views/EpnTapUI.js @@ -113,7 +113,10 @@ Ext.create('Ext.data.Store', { sorters: [ {property: 'nb_results', direction: 'DESC'}, {property: 'short_name', direction: 'ASC'} - ] + ], + listeners: { + // load: function(record) { console.log(record); } + } }); /** @@ -136,21 +139,22 @@ selected. - `thumbnail_url`: the thumbnail_url EPN-TAP parameter (ibid). */ Ext.create('Ext.data.Store', { - storeId:'granulesStore', - pageSize: 25, + id: 'granulesStore', + model: 'granulesModel', autoload: false, - fields:['num', 'dataproduct_type', 'target_name', 'time_min', 'time_max', 'access_format', 'granule_uid', 'access_estsize', 'access_url', 'thumbnail_url'], + pageSize: 25, proxy: { type: 'ajax', url: 'php/epntap.php', reader: { type: 'json', - root: 'rows' + root: 'data' } - }, - sorters: [ - {property: 'num', direction: 'ASC'} - ] + }, listeners: { + 'metachange': function(store, meta) { + Ext.getCmp('epnTapGranulesGrid').reconfigure(store, meta.columns); + } + } }); /** @@ -385,7 +389,6 @@ Ext.define('amdaUI.EpnTapUI', { }; }, - /** Create `epnTapServicesGrid`, an ExtJS grid containing the EPN-TAP services matching with the filter form (`serviceFilterPanel`). @@ -472,7 +475,6 @@ Ext.define('amdaUI.EpnTapUI', { } } }); - return epnTapServicesGrid; }, @@ -498,6 +500,7 @@ Ext.define('amdaUI.EpnTapUI', { - currently only the granule thumbnail, in full size. A click on a granule triggers `EpnTapModule.onGranuleSelected()`. + TODO: infinite scroll! http://docs.sencha.com/extjs/4.2.3/extjs-build/examples/grid/infinite-scroll-with-filter.html */ createGranulesGrid: function() { var txtRender = function(val) { @@ -510,9 +513,8 @@ Ext.define('amdaUI.EpnTapUI', { return '<img width="40px height="40px" src="' + val + '">'; }; var dptRender = function(val) { - console.log(Ext.data.StoreManager.lookup('productTypesStore')); - return val; - // (val in productTypeDict) ? '<p style="white-space: normal;">' + productTypeDict[val] + '</p>' : '<em>' + val + '</em>'; + var productTypeDict = Ext.data.StoreManager.lookup('productTypesStore').data.map; + return productTypeDict[val].data.name; }; var formatRender = function(val) { // A dictionnary used to associate the mimetype (i.e "application/fits") to a pretty printed word (i.e "fits"). @@ -585,16 +587,16 @@ Ext.define('amdaUI.EpnTapUI', { store: Ext.data.StoreManager.lookup('granulesStore'), flex: 4, columns: [ - { text: 'Num', dataIndex: 'num', flex: 1, renderer: txtRender }, + // { text: 'Num', dataIndex: 'num', flex: 1, renderer: txtRender, hidden: true }, // { text: 'Type', dataIndex: 'dataproduct_type', flex: 2, renderer: dptRender }, - { text: 'Target', dataIndex: 'target_name', flex: 2, renderer: txtRender }, - { text: 'Time min', dataIndex: 'time_min', flex: 2, renderer: txtRender }, - { text: 'Time max', dataIndex: 'time_max', flex: 2, renderer: txtRender }, + // { text: 'Target', dataIndex: 'target_name', flex: 2, renderer: txtRender, hidden: true }, + // { text: 'Time min', dataIndex: 'time_min', flex: 2, renderer: txtRender }, + // { text: 'Time max', dataIndex: 'time_max', flex: 2, renderer: txtRender }, // { text: 'Format', dataIndex: 'access_format', flex: 2, renderer: formatRender }, - { text: 'uid', dataIndex: 'granule_uid', flex: 2, renderer: txtRender }, - { text: 'Size', dataIndex: 'access_estsize', flex: 1, renderer: sizeRender }, - { text: 'URL', dataIndex: 'access_url', flex: 1, renderer: linkRender }, - { text: 'Thumb.', dataIndex: 'thumbnail_url', flex: 1, renderer: imgRender} + // { text: 'uid', dataIndex: 'granule_uid', flex: 2, renderer: txtRender }, + // { text: 'Size', dataIndex: 'access_estsize', flex: 1, renderer: sizeRender }, + // { text: 'URL', dataIndex: 'access_url', flex: 1, renderer: linkRender }, + // { text: 'Thumb.', dataIndex: 'thumbnail_url', flex: 1, renderer: imgRender} ], dockedItems: [{ xtype: 'pagingtoolbar', diff --git a/php/epntap.php b/php/epntap.php index 98fb943..bdb4d93 100644 --- a/php/epntap.php +++ b/php/epntap.php @@ -8,20 +8,23 @@ $action = preg_replace("/[^a-zA-Z]+/", "", filter_var($_GET['action'], FILTER_SA switch ($action) { case 'resolver': - echo json_encode(resolver()); + $response = json_encode(resolver()); break; case 'getServices': - echo json_encode(getServices()); + $response = json_encode(getServices()); break; case 'getNbResults': - echo getNbResults(); + $response = getNbResults(); break; case 'getGranules': - echo json_encode(getGranules()); + $response = json_encode(getGranules()); break; default: - echo 'unknown action'; + $response = 'unknown action'; + break; } +// error_log('epntap response: ' . $response); +echo $response; function resolver() { $input = filter_var($_GET['input'], FILTER_SANITIZE_URL); @@ -41,13 +44,14 @@ function resolver() { function getServices() { $registriesURL = ["http://registry.euro-vo.org/regtap/tap", "http://dc.zah.uni-heidelberg.de/tap", "http://gavo.aip.de/tap", "http://reg.g-vo.org/tap"]; $columns = ['short_name', 'res_title', 'ivoid', 'access_url', 'table_name', 'content_type', 'creator_seq', 'content_level', 'reference_url', 'created', 'updated']; - $getServicesQuery = "SELECT DISTINCT " . implode(', ', $columns) . " FROM rr.resource + $query = "SELECT DISTINCT " . implode(', ', $columns) . " FROM rr.resource NATURAL JOIN rr.res_schema NATURAL JOIN rr.res_table NATURAL JOIN rr.interface NATURAL JOIN rr.res_detail NATURAL JOIN rr.capability WHERE standard_id='ivo://ivoa.net/std/tap' AND intf_type='vs:paramhttp' AND detail_xpath='/capability/dataModel/@ivo-id' AND 1=ivo_nocasematch(detail_value, 'ivo://vopdc.obspm/std/EpnCore%') AND table_name LIKE '%.epn_core' ORDER BY short_name, table_name"; + // error_log('getServices query: ' . $query); for($i=0; $i<count($registriesURL); $i++) { - $services = request($registriesURL[$i], $getServicesQuery); + $services = request($registriesURL[$i], $query); if(! array_key_exists("error", $services)) { for($j=0; $j<count($services); $j++) { $services[$j]['id'] = generateServiceId($services[$j]); @@ -78,6 +82,7 @@ function getNbResults() { $timeMax = filter_var($_GET['timeMax'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); $query = "SELECT COUNT(*) AS nb_rows FROM $tableName" . createFilter($targetName, $productTypes, $timeMin, $timeMax); + // error_log('getNbResults query: ' . $query); $result = request($url, $query); if(count($result) < 1) { return 'Too few returned raws.'; @@ -97,7 +102,7 @@ function getNbResults() { } function getGranules() { - error_log(json_encode($_GET)); + // error_log('getGranules GET: ' . json_encode($_GET)); $url = filter_var($_GET['url'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); $tableName = filter_var($_GET['tableName'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); $targetName = filter_var($_GET['targetName'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); @@ -108,13 +113,20 @@ function getGranules() { $limit = filter_var($_GET['limit'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); $nbRes = filter_var($_GET['nbRes'], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW); - // TODO find a way to handle 'non existing key errors' (and then add access_format) - $columns = "dataproduct_type, target_name, time_min, time_max, granule_uid, access_estsize, access_url, thumbnail_url"; $filter = createFilter($targetName, $productTypes, $timeMin, $timeMax); - $query = "SELECT TOP $limit $columns FROM $tableName $filter OFFSET $start"; + $query = "SELECT TOP $limit * FROM $tableName $filter OFFSET $start"; + // error_log('getGranules query: ' . $query); $rows = request($url, $query); - return ['success' => true, 'total' => $nbRes, 'rows' => $rows]; - // return $rows; + + $fields = array(); + $columns = array(); + foreach($rows[0] as $key => $value) { + $fields[] = ['name' => $key, 'type' => 'string']; + $columns[] = ['text' => ucfirst(str_replace('_', ' ', $key)), 'dataIndex' => $key]; + } + + $metadata = ['fields' => $fields, 'columns' => $columns, 'root' => 'data']; + return ['data' => $rows, 'total' => $nbRes, 'metaData' => $metadata]; } // ----- utils ----- -- libgit2 0.21.2