Commit a79b0198406e7a5a4b2265ff7d2ccf28a1c7c7a0

Authored by Nathanael Jourdane
1 parent 73c7e8a5

Add EPN-TAP module (draft).

js/app/AmdaApp.js
... ... @@ -97,6 +97,13 @@ Ext.define('amdaApp.AmdaApp', {
97 97 source : 'amdaDesktop.InteropModule',
98 98 useLauncher : true
99 99 },
  100 + epntap : {
  101 + id : 'epntap-win',
  102 + icon : 'icon-epntap',
  103 + title : 'EPN-TAP data',
  104 + source : 'amdaDesktop.EpnTapModule',
  105 + useLauncher : true
  106 + },
100 107 info : {
101 108 id : 'info-win',
102 109 icon : 'icon-information',
... ...
js/app/controllers/EpnTapModule.js 0 → 100644
... ... @@ -0,0 +1,85 @@
  1 +/**
  2 + * Project : AMDA-NG
  3 + * Name : EpnTapModule.js
  4 + * @class amdaDesktop.EpnTapModule
  5 + * @extends amdaDesktop.AmdaModule
  6 + * @brief EpnTap Module controller definition
  7 + * @author Nathanael Jourdane
  8 + */
  9 +
  10 +function onWindowLoaded() {
  11 +}
  12 +
  13 +function onSearchBtnClicked() {
  14 + var targetName = Ext.getCmp('targetNameCB').value;
  15 + var productType = Ext.getCmp('productTypeCB').value;
  16 + var startTime = Ext.getCmp('startTimeDF').rawValue;
  17 + var stopTime = Ext.getCmp('stopTimeDF').rawValue;
  18 +
  19 + for(let service of Ext.getCmp('servicesPanel').getStore().getRange()) {
  20 + var filter = Array(service.data.table_name, service.data.access_url, targetName, productType, startTime, stopTime);
  21 + AmdaAction.epnTapMgr('getServiceNbResults', filter, function(epnTapServices) {
  22 + service.set('nb_responses', epnTapServices);
  23 + // console.log(epnTapServices[1]);
  24 + });
  25 + }
  26 +}
  27 +
  28 +// var grid = Ext.getCmp('servicesPanel');
  29 +// var selection = grid.getSelectionModel();
  30 +// access_url = [];
  31 +// table_name = [];
  32 +// for(i=0 ; i<grid.store.getCount() ; i++) {
  33 +// if(selection.isSelected(i)) {
  34 +// table_name.push(grid.store.getAt(i).data.table_name);
  35 +// access_url.push(grid.store.getAt(i).data.access_url);
  36 +// }
  37 +//
  38 +// }
  39 +
  40 +function onServiceSelected(service) {
  41 + var filter = Array(service['table_name'], service['access_url'], Ext.getCmp('targetNameCB').value,
  42 + Ext.getCmp('productTypeCB').value, Ext.getCmp('startTimeDF').rawValue, Ext.getCmp('stopTimeDF').rawValue);
  43 +
  44 + AmdaAction.epnTapMgr('getGranules', filter, function(granules) {
  45 + console.log(granules);
  46 + });
  47 +}
  48 +
  49 +function onGranuleSelected(granule) {
  50 + console.log('selected granule: ' + granule.target_name);
  51 +}
  52 +
  53 +Ext.define('amdaDesktop.EpnTapModule', {
  54 +
  55 + extend: 'amdaDesktop.AmdaModule',
  56 +
  57 + requires: ['amdaUI.EpnTapUI'],
  58 + contentId : 'EpnTapUI',
  59 +
  60 + /** The alias name of the module view. */
  61 + uiType: 'panelEpnTap',
  62 +
  63 + /** The text displayed on the *help button* tooltip. */
  64 + helpTitle: 'Help on EPN-TAP Module',
  65 +
  66 + /** The name of the documentation file related to the module. */
  67 + helpFile : 'epnTapHelp',
  68 +
  69 + width : 600,
  70 + height: 550,
  71 +
  72 + /** @class Module initialisation. */
  73 + init: function() {
  74 + this.launcher = {
  75 + text: this.title,
  76 + iconCls: this.icon,
  77 + handler: this.createWindow,
  78 + scope: this
  79 + };
  80 + this.onWindowLoaded = onWindowLoaded;
  81 + this.onSearchBtnClicked = onSearchBtnClicked;
  82 + this.onGranuleSelected = onGranuleSelected;
  83 + this.onServiceSelected = onServiceSelected;
  84 + }
  85 +});
... ...
js/app/views/EpnTapUI.js 0 → 100644
... ... @@ -0,0 +1,243 @@
  1 +/**
  2 + * Project: AMDA-NG
  3 + * Name: EpnTapUI.js
  4 + * @class amdaUI.EpnTapUI
  5 + * @extends Ext.tab.Panel
  6 + * @brief client for EPN-TAP services (View)
  7 + * @author Nathanael JOURDANE
  8 + * 24/10/2016: file creation
  9 + */
  10 +
  11 +Ext.create('Ext.data.Store', {
  12 + storeId:'services_store',
  13 + fields: ['short_name', 'res_title', 'ivoid', 'access_url', 'table_name', 'content_type',
  14 + 'res_description', 'creator seq', 'content_level', 'reference_url', 'created', 'updated', 'nb_responses'],
  15 + proxy: {
  16 + type: 'ajax',
  17 + url: 'generic_data/EpnTapData/EpnTapServices.json',
  18 + reader: {type: 'json'}
  19 + },
  20 + autoLoad: true
  21 +});
  22 +
  23 +Ext.create('Ext.data.Store', {
  24 + storeId:'granules_store',
  25 + fields:['type', 'target_name', 'time_min', 'time_max'],
  26 + data: {'items': [
  27 + {'type': 'sp', 'target_name': 'mars', 'time_min': '01/01/2012', 'time_max': '02/01/2012'},
  28 + {'type': 'sp', 'target_name': 'mars', 'time_min': '01/01/2012', 'time_max': '02/01/2012'},
  29 + {'type': 'im', 'target_name': 'earth', 'time_min': '01/01/2012', 'time_max': '02/01/2012'},
  30 + {'type': 'im', 'target_name': 'earth', 'time_min': '01/01/2012', 'time_max': '02/01/2012'}
  31 + ]},
  32 + proxy: {
  33 + type: 'memory',
  34 + reader: { type: 'json', root: 'items' }
  35 + }
  36 +});
  37 +
  38 +Ext.create('Ext.data.Store', {
  39 + storeId:'productTypes_store',
  40 + fields: ['id', 'name'],
  41 + proxy: {
  42 + type: 'ajax',
  43 + url : 'generic_data/EpnTapData/EpnTapProductTypes.json',
  44 + reader: {type: 'json'}
  45 + },
  46 + autoLoad: true
  47 +});
  48 +
  49 +Ext.create('Ext.data.Store', {
  50 + storeId:'targetClasses_store',
  51 + fields: ['id', 'name'],
  52 + proxy: {
  53 + type: 'ajax',
  54 + url : 'generic_data/EpnTapData/EpnTapTargetClasses.json',
  55 + reader: {
  56 + type: 'json'
  57 + }
  58 + },
  59 + autoLoad: true
  60 +});
  61 +
  62 +Ext.create('Ext.data.Store', {
  63 + storeId: 'targetNames_store',
  64 + fields: ['n'],
  65 + proxy: {
  66 + type: 'ajax',
  67 + url : 'generic_data/EpnTapData/EpnTapTargetNames.json',
  68 + reader: {type: 'json'}
  69 + },
  70 + autoLoad: true
  71 +});
  72 +
  73 +var serviceFilterPanel = {
  74 + id: 'serviceFilterPanel',
  75 + xtype: 'panel',
  76 + region : 'north',
  77 + layout: { type: 'hbox', pack: 'start', align: 'stretch' },
  78 + defaults: { margin: 5 },
  79 + items: [{ // Left part
  80 + xtype : 'container',
  81 + layout: 'form',
  82 + flex: 2,
  83 + items: [{
  84 + id: 'productTypeCB',
  85 + xtype: 'combobox',
  86 + fieldLabel: 'Product type',
  87 + store: Ext.data.StoreManager.lookup('productTypes_store'),
  88 + queryMode: 'local',
  89 + displayField: 'name',
  90 + valueField: 'id',
  91 + name: 'productType',
  92 + editable: false,
  93 + allowBlank: false
  94 + }, {
  95 + id: 'targetClassCB',
  96 + xtype: 'combobox',
  97 + fieldLabel: 'Target class',
  98 + store: Ext.data.StoreManager.lookup('targetClasses_store'),
  99 + queryMode: 'local',
  100 + displayField: 'name',
  101 + valueField: 'id',
  102 + name: 'targetClass',
  103 + editable: false,
  104 + allowBlank: false
  105 + }, {
  106 + id: 'targetNameCB',
  107 + xtype: 'combobox',
  108 + fieldLabel: 'Target name',
  109 + store: Ext.data.StoreManager.lookup('targetNames_store'),
  110 + queryMode: 'local',
  111 + displayField: 'n',
  112 + valueField: 'n',
  113 + name: 'targetName',
  114 + allowBlank: false,
  115 + triggerAction: 'all',
  116 + typeAhead: true,
  117 + mode: 'remote',
  118 + minChars: 2,
  119 + forceSelection: true
  120 + // listeners: {
  121 + // scope: window,
  122 + // 'change': function(combobox, newValue, oldValue, eOpts) {
  123 + // if(newValue && newValue.length >= 3) {
  124 + // myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.epntap.id).onTargetNameUpdate(newValue);
  125 + // }
  126 + // }
  127 + // }
  128 + }]
  129 + }, { // Right part
  130 + xtype : 'container',
  131 + layout: 'form',
  132 + flex: 2,
  133 + items: [{
  134 + id: 'startTimeDF',
  135 + xtype: 'datefield',
  136 + fieldLabel: 'Start time',
  137 + name: 'start_time',
  138 + allowBlank:false
  139 + }, {
  140 + id: 'stopTimeDF',
  141 + xtype: 'datefield',
  142 + fieldLabel: 'Stop time',
  143 + name: 'stop_time',
  144 + allowBlank:false
  145 + }, {
  146 + id: 'searchServicesBtn',
  147 + xtype: 'button',
  148 + text: 'Search services',
  149 + handler: function() {
  150 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.epntap.id).onSearchBtnClicked();
  151 + }
  152 + }]
  153 + }]
  154 +}
  155 +
  156 +var servicesPanel = {
  157 + id: 'servicesPanel',
  158 + xtype : 'grid',
  159 + title: 'Services',
  160 + multiSelect: true,
  161 + store: Ext.data.StoreManager.lookup('services_store'),
  162 + flex: 1,
  163 + columns: [
  164 + { text: 'Service', dataIndex: 'short_name', flex: 3 },
  165 + { text: 'Results', dataIndex: 'nb_responses', flex: 1}
  166 + ],
  167 + listeners: {
  168 + 'cellclick': function(grid, td, cellIndex, record, tr, rowIndex, e, eOpts) {
  169 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.epntap.id).onServiceSelected(record.data);
  170 + }
  171 + }
  172 +}
  173 +
  174 +var granulesPanel = {
  175 + id: 'granulesPanel',
  176 + xtype : 'grid',
  177 + title: 'Granules',
  178 + store: Ext.data.StoreManager.lookup('granulesStore'),
  179 + flex: 3,
  180 + columns: [
  181 + { text: 'Type', dataIndex: 'type', flex: 1 },
  182 + { text: 'Target', dataIndex: 'target_name', flex: 1 },
  183 + { text: 'Time min', dataIndex: 'time_min', flex: 2 },
  184 + { text: 'Time max', dataIndex: 'time_max', flex: 2 }
  185 + ],
  186 + listeners: {
  187 + 'cellclick': function(grid, td, cellIndex, record, tr, rowIndex, e, eOpts) {
  188 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.epntap.id).onGranuleSelected(record.data);
  189 + }
  190 + }
  191 +}
  192 +
  193 +var mainPanel = {
  194 + id: 'mainPanel',
  195 + xtype: 'panel',
  196 + region: 'center',
  197 + height: 350,
  198 + layout: { type: 'hbox', pack: 'start', align: 'stretch' },
  199 + items: [ servicesPanel, granulesPanel ],
  200 + listeners: {
  201 + afterrender: function() {
  202 + myDesktopApp.getLoadedModule(myDesktopApp.dynamicModules.epntap.id).onWindowLoaded();
  203 + }
  204 + }
  205 +}
  206 +
  207 +var infoPanel = {
  208 + id: 'infoPanel',
  209 + xtype : 'panel',
  210 + region: 'south',
  211 + title: 'Information',
  212 + collapsible: true,
  213 + flex: 0,
  214 + height: 100,
  215 + autoHide: false,
  216 + bodyStyle: 'padding: 5px',
  217 + iconCls: 'icon-information',
  218 + loader: { autoLoad: true, url: helpDir + 'epnTapHOWTO' }
  219 +}
  220 +
  221 +Ext.define('amdaUI.EpnTapUI', {
  222 + extend: 'Ext.container.Container',
  223 + alias: 'widget.panelEpnTap',
  224 +
  225 + constructor: function(config) {
  226 + this.init(config);
  227 + this.callParent(arguments);
  228 + },
  229 +
  230 + init : function(config) {
  231 + var myConf = {
  232 + width: 600,
  233 + height: 550,
  234 + layout: 'border',
  235 + items: [
  236 + serviceFilterPanel,
  237 + mainPanel,
  238 + infoPanel
  239 + ]
  240 + };
  241 + Ext.apply(this, Ext.apply(arguments, myConf));
  242 + }
  243 +});
... ...
js/resources/images/64x64/epntap.png 0 → 100644

3.21 KB

php/classes/AmdaAction.php
... ... @@ -1334,7 +1334,10 @@ class AmdaAction {
1334 1334 $alreadyUsed = $mgr->isNameAlreadyUsed($obj->type, $obj->name);
1335 1335 return array('success' => true, 'alreadyUsed' => $alreadyUsed);
1336 1336 }
1337   -
  1337 +
  1338 + public function epnTapMgr($function_name, $args) {
  1339 + return (new EpnTapMgr)->call($function_name, $args);
  1340 + }
1338 1341 }
1339 1342 ?>
1340 1343  
... ...
php/classes/EpnTapMgr.php 0 → 100644
... ... @@ -0,0 +1,100 @@
  1 +<?php
  2 +/** @class EpnTapMgr
  3 +* @brief Manager to communicates with EPN-TAP services.
  4 +*/
  5 +
  6 +class EpnTapMgr {
  7 +
  8 + public function call($function_name, $args) {
  9 + switch($function_name) {
  10 + case 'getServiceNbResults':
  11 + if(count($args) == 6)
  12 + return $this->getServiceNbResults($args[0], $args[1], $args[2], $args[3], $args[4], $args[5]);
  13 + break;
  14 + case 'getGranules':
  15 + if(count($args) == 6)
  16 + return $this->getGranules($args[0], $args[1], $args[2], $args[3], $args[4], $args[5]);
  17 + break;
  18 + default:
  19 + return array('success' => false, 'message' => $function_name.' is an unknown function.');
  20 + break;
  21 + }
  22 + return array('success' => false, 'message' => 'The function do not have the required number of arguments');
  23 + }
  24 +
  25 + // dc.zah.uni-heidelberg.de/tap/sync?FORMAT=votable&LANG=ADQL&QUERY=SELECT DISTINCT table_name WHERE standard_id='ivo://ivoa.net/std/tap' AND intf_type='vs:paramhttp' AND detail_xpath='/capability/dataModel/@ivo-id' FROM&REQUEST=doQuery
  26 + // select distinct target_name from xxx.epn_core
  27 +
  28 + private function date2JD($date) {
  29 + list($month, $day, $year) = split('[/.-]', $date);
  30 +
  31 + if($month == 1 || $month == 2) {
  32 + $yearp = $year - 1;
  33 + $monthp = $month + 12;
  34 + } else {
  35 + $yearp = $year;
  36 + $monthp = $month;
  37 + }
  38 +
  39 + # this checks where we are in relation to October 15, 1582, the beginning
  40 + # of the Gregorian calendar.
  41 + if (($year < 1582) ||
  42 + ($year == 1582 && $month < 10) ||
  43 + ($year == 1582 && $month == 10 && $day < 15))
  44 + $j_day = 0;
  45 + else
  46 + $j_day = 2 - (int)($yearp / 100.0) + (int)((int)($yearp / 100.0) / 4.0);
  47 +
  48 + $j_day += $yearp < 0 ? (int)((365.25 * $yearp) - 0.75) : (int)(365.25 * $yearp);
  49 + $j_day += (int)(30.6001 * ($monthp + 1)) + $day + 1720994.5;
  50 +
  51 + return $j_day;
  52 + }
  53 +
  54 + private function getServiceNbResults($table_name, $access_url, $target_name, $dataproduct_type, $time_min, $time_max) {
  55 + $filter = array();
  56 + if($target_name)
  57 + array_push($filter, "target_name = '$target_name'");
  58 + if($dataproduct_type)
  59 + array_push($filter, "dataproduct_type = '$dataproduct_type'");
  60 + if($time_min)
  61 + array_push($filter, "time_min >= " . $this->date2JD($time_min));
  62 + if($time_max)
  63 + array_push($filter, "time_max >= " . $this->date2JD($time_max));
  64 +
  65 + $query = "SELECT COUNT(granule_uid) AS nb_results FROM $table_name"
  66 + . ($filter.length > 0 ? ' WHERE ' . join(' AND ', $filter) : '');
  67 +
  68 + $votMgr = new VOTableMgr;
  69 + $params = 'FORMAT=votable&LANG=ADQL&REQUEST=doQuery';
  70 + $url = $access_url . '/sync?' . $params . '&QUERY=' . urlencode($query);
  71 + $votMgr->load($url);
  72 + return $votMgr->isValidSchema() ? $votMgr->getSimpleInteger() : 0;
  73 + }
  74 +
  75 + static function getGranules($table_name, $access_url) {
  76 + $filter = array();
  77 + if($target_name)
  78 + array_push($filter, "target_name = '$target_name'");
  79 + if($dataproduct_type)
  80 + array_push($filter, "dataproduct_type = '$dataproduct_type'");
  81 + if($time_min)
  82 + array_push($filter, "time_min >= " . $this->date2JD($time_min));
  83 + if($time_max)
  84 + array_push($filter, "time_max >= " . $this->date2JD($time_max));
  85 +
  86 + $query = "SELECT dataproduct_type, target_name, time_min, time_max FROM $table_name"
  87 + . ($filter.length > 0 ? ' WHERE ' . join(' AND ', $filter) : '');
  88 +
  89 + $votMgr = new VOTableMgr;
  90 + $params = 'FORMAT=votable&LANG=ADQL&REQUEST=doQuery';
  91 + $url = $access_url . '/sync?' . $params . '&QUERY=' . urlencode($query);
  92 + $votMgr->load($url);
  93 + if($votMgr->isValidSchema()) {
  94 + return false;
  95 + } else {
  96 + return true;
  97 + }
  98 + }
  99 +}
  100 +?>
... ...
php/config.php
... ... @@ -137,6 +137,9 @@ define(&#39;PREDEFINED&#39;,BASE_PATH.&#39;amda_plus/predefined/&#39;);
137 137 define('PRO',BASE_PATH.'amda_plus/pro/');
138 138 define('specialGrpsXml',SpecialSettingsDir.'Groups.xml');
139 139  
  140 +// EPN-TAP data
  141 +define('EpnTapDataPath', DATAPATH.'EpnTapData/');
  142 +
140 143 //Help info dirs
141 144 define('HELPPATH', BASE_PATH."help/");
142 145 define('targetsSimu',HELPPATH.'simu/TargetsSimu.xml');
... ... @@ -380,7 +383,8 @@ $API = array(
380 383 ),
381 384 'isSharedObjectNameAlreadyUsed' => array(
382 385 'len'=>1
383   - )
  386 + ),
  387 + 'epnTapMgr' => array('len'=>2)
384 388 )
385 389 )
386 390 );
... ...