Blame view

js/app/views/EpnTapUI.js 23.5 KB
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
1
2
3
4
5
/**
 * Project: AMDA-NG
 * Name: EpnTapUI.js
 * @class amdaUI.EpnTapUI
 * @extends Ext.tab.Panel
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
6
7
8
9
 * @author Nathanael JOURDANE
 * 24/10/2016: file creation
 */

016bdaae   Nathanael Jourdane   Fix bad rendering...
10
Ext.require(['Ext.grid.plugin.BufferedRenderer']);
b185823c   Nathanael Jourdane   Use IntervalUI mo...
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
`productTypesStore`: An ExtJS Store containing the list of the different data product types defined on all granules, on
all available EPN-TAP services (defined in `generic_data/EpnTapData/metadata.json`, updated periodically with a cron
script).

This list is used to fill the `productTypeCB` combo box, which is initilized in `EpnTapModule` at the panel creation.

- `id`: the data product type IDs, according to the EPN-TAP specification (see
		https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=1148225);
- `name`: the data product name, according to the EPN-TAP specification (ibid).

These IDs and names are hard-defined in the JSon file `generic_data/EpnTapData/dataproduct_types.json`.

Notes:
- if a granule contains a data product type which is not conform to the EPN-TAP definition (ibid), it is not displayed
in this store and an information message is displayed on the JavaScript console during the panel creation.
- if a data product type is not present in any of the granules from the EPN-TAP services, it is not present in this
store.
b185823c   Nathanael Jourdane   Use IntervalUI mo...
29
*/
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
30
Ext.create('Ext.data.Store', {
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
31
32
	storeId: 'productTypesStore',
	autoLoad: true,
977e2c07   Nathanael Jourdane   Add tooltips on p...
33
	fields: ['id', 'name', 'desc'],
ebdc15a7   Nathanael Jourdane   remove targetclas...
34
	data: [
977e2c07   Nathanael Jourdane   Add tooltips on p...
35
36
37
38
39
40
41
42
43
44
45
46
47
48
		{'id': 'all', 'name': '--All--', 'desc': 'Select all produt types.'},
		{'id': 'clear', 'name': '--Clear--', 'desc': 'Clear the selection.'},
		{'id': 'im', 'name': 'Image', 'desc': '2D series of values depending on 2 spatial axes, with measured parameters.'},
		{'id': 'ma', 'name': 'Map', 'desc': '2D series of values depending on 2 spatial axes, with derived parameters.'},
		{'id': 'sp', 'name': 'Spectrum', 'desc': '1D series of values depending on a spectral axis (or Frequency, Energy, Mass,...).'},
		{'id': 'ds', 'name': 'Dynamic spectrum', 'desc': '2D series of values depending on time and on a spectral axis (Frequency, Energy, Mass,...), FoV is homogeneous.'},
		{'id': 'sc', 'name': 'Spectral cube', 'desc': '3D series of values depending on 2 spatial axes and on a spectral axis (Frequency, Energy, Mass,..).'},
		{'id': 'pr', 'name': 'Profile', 'desc': '1D series of values depending on a spatial axis.'},
		{'id': 'vo', 'name': 'Volume', 'desc': '3D series of values depending on 3 spatial axes (spatial coordinates or tabulated values in a volumic grid).'},
		{'id': 'mo', 'name': 'Movie', 'desc': '3D series of values depending on 2 spatial axes and on time.'},
		// {'id': 'cu', 'name': 'Cube', 'desc': '.'},
		{'id': 'ts', 'name': 'Time series', 'desc': '1D series of values depending on time.'},
		{'id': 'ca', 'name': 'Catalogue', 'desc': '1D list of elements.'},
		{'id': 'ci', 'name': 'Catalogue item', 'desc': '0D list of elements.'}
ebdc15a7   Nathanael Jourdane   remove targetclas...
49
	]
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
50
51
});

b185823c   Nathanael Jourdane   Use IntervalUI mo...
52
53
54
55
56
57
58
59
60
61
62
/**
`targetNamesStore`: An ExtJS Store containing the list of the different target names defined on all granules, on
all available EPN-TAP services (defined in `generic_data/EpnTapData/metadata.json`, updated periodically with a cron
script), which match with the selected data product and target class.

This list is used to fill the `targetNameCB` combo box, which is updated by `EpnTapModule` each time a new target class
(or, by transitivity, product type) is selected.

- `id`: the target name in lowercase, with the underscore between each word;
- `name`: the target name, capitalized with spaces between each word (done `EpnTapModule.prettify()`).
*/
68664dca   Nathanael Jourdane   make epntap php f...
63
Ext.create('Ext.data.Store', {
7055f5d6   Nathanael Jourdane   Code refactoring
64
	storeId: 'targetNamesStore',
b5d477c6   Nathanael Jourdane   Allow multiple va...
65
	fields: ['id', 'text', 'name', 'type', 'parent', 'aliases'],
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
66
67
	proxy: {
		type: 'ajax',
68664dca   Nathanael Jourdane   make epntap php f...
68
		url: 'php/epntap.php',
50dd7220   Nathanael Jourdane   epntap.php works ...
69
		extraParams: { action: 'resolver' }
600add6e   Nathanael Jourdane   Display error if ...
70
71
72
73
74
75
76
77
78
	},
	errorDisplayed: false,
	listeners: {
		load: function(store, records, successful) {
			if(!successful && !store.errorDisplayed) {
				Ext.Msg.alert('Error', 'Can not load results from the resolver. Please enter target names manually.');
				store.errorDisplayed = true;
			}
		}
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
79
	}
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
80
81
});

12c10cdb   Nathanael Jourdane   Get the list of s...
82
83
84
85
86
87
88
/**
`servicesStore`: An ExtJS Store containing the list of the EPN-TAP services (defined in
`generic_data/EpnTapData/metadata.json`, updated periodically with a cron script), which contains at least one granule
matching with the granules filter (the selected data product type, target class and target name).

This list is used to fill the `servicesGrid` table, which is updated by `EpnTapModule` each time a new target name
(or, by transitivity, target class or product type) is selected.
8d5634e3   Nathanael Jourdane   Use epn-tap store...
89

12c10cdb   Nathanael Jourdane   Get the list of s...
90
91
92
93
94
95
96
97
98
- `id`: the database name of the service, according to the `table_name` column from the `rr.res_table` in the
		registry database;
- `nbResults`: the number of granules matching with the granules filter for this service;
- `shortName`: the service short name, according to the `short_name` column from the `rr.resource` table in the registry
		database;
- `title`: the service title, according to the `res_title` column from the `rr.resource` table in the registry database;
- `accessURL`: the service access URL, according to the `access_url` column from the `rr.interface` table in the
		registry database.
*/
8d5634e3   Nathanael Jourdane   Use epn-tap store...
99
Ext.create('Ext.data.Store', {
12c10cdb   Nathanael Jourdane   Get the list of s...
100
	storeId: 'servicesStore',
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
101
	autoLoad: true,
12c10cdb   Nathanael Jourdane   Get the list of s...
102
103
104
105
106
107
108
109
110
111
112
113
114
	fields: [
		{name: 'id', type: 'string'},
		{name: 'short_name', type: 'string'},
		{name: 'res_title', type: 'string'},
		{name: 'ivoid', type: 'string'},
		{name: 'access_url', type: 'string'},
		{name: 'table_name', type: 'string'},
		{name: 'content_type', type: 'string'},
		{name: 'creator_seq', type: 'string'},
		{name: 'content_level', type: 'string'},
		{name: 'reference_url', type: 'string'},
		{name: 'created', type: 'date', dateFormat: 'c'},
		{name: 'updated', type: 'date', dateFormat: 'c'},
d6674d39   Nathanael Jourdane   Add error and inf...
115
		{name: 'nb_results', type: 'integer'},
016bdaae   Nathanael Jourdane   Fix bad rendering...
116
		{name: 'info', type: 'string'}
8d5634e3   Nathanael Jourdane   Use epn-tap store...
117
118
119
	],
	proxy: {
		type: 'ajax',
49401187   Nathanael Jourdane   epntap: Do not us...
120
		url: 'php/epntap.php',
8c2fa14d   Nathanael Jourdane   Update services g...
121
122
123
124
125
		extraParams : {action: 'getServices'}
	},
	sorters: [
		{property: 'nb_results', direction: 'DESC'},
		{property: 'short_name', direction: 'ASC'}
a8a12768   Nathanael Jourdane   Create the grid m...
126
127
	],
	listeners: {
053ffdb4   Nathanael Jourdane   bugFix targetName...
128
		// beforeload: function(s, operation) { console.log(operation); },
600add6e   Nathanael Jourdane   Display error if ...
129
130
131
132
133
		load: function(store, records, successful) {
			if(!successful) {
				Ext.Msg.alert('Error', 'Can not get epntap services from registries.');
			}
		}
a8a12768   Nathanael Jourdane   Create the grid m...
134
	}
8d5634e3   Nathanael Jourdane   Use epn-tap store...
135
136
});

b185823c   Nathanael Jourdane   Use IntervalUI mo...
137
/**
b185823c   Nathanael Jourdane   Use IntervalUI mo...
138
`granulesStore`: An ExtJS Store containing the list of granules of the selected service (on `servicesGrid`), which match
ba6dfa5e   Nathanael Jourdane   (regression bug) ...
139
with the granules filter (the selected data product type, target class and target name).
b185823c   Nathanael Jourdane   Use IntervalUI mo...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

This list is used to fill the `granulesGrid` table, which is updated by `EpnTapModule` each time a new service is
selected.

- `num`: the line number, according to the order of the query response and the current page (see `currentPageLb`);
- `dataproduct_type`: the dataproduct_type EPN-TAP parameter, as defined in
	https://voparis-confluence.obspm.fr/display/VES/EPN-TAP+V2.0+parameters.
- `target_name`: the target_name EPN-TAP parameter (ibid);
- `time_min`: the time_min EPN-TAP parameter (ibid);
- `time_max`: the time_max EPN-TAP parameter (ibid);
- `access_format`: the access_format EPN-TAP parameter (ibid);
- `granule_uid`: the granule_uid EPN-TAP parameter (ibid);
- `access_estsize`: the access_estsize EPN-TAP parameter (ibid);
- `access_url`: the access_url EPN-TAP parameter (ibid);
- `thumbnail_url`: the thumbnail_url EPN-TAP parameter (ibid).
*/
6d616600   Nathanael Jourdane   Fix granules sorter
156
// TODO: Add granules filter (see http://docs.sencha.com/extjs/4.0.7/#!/example/grid-filtering/grid-filter-local.html)
016bdaae   Nathanael Jourdane   Fix bad rendering...
157
158
159
160
161
162

Ext.define('GranulesModel', {
	extend: 'Ext.data.Model'
	// columns are created dynamically
});

3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
163
Ext.create('Ext.data.Store', {
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
164
	storeId: 'granulesStore',
016bdaae   Nathanael Jourdane   Fix bad rendering...
165
	model: 'GranulesModel',
11f8b45b   Nathanael Jourdane   Use buffered scro...
166
	buffered: true,
87467502   Nathanael Jourdane   Replace page butt...
167
	autoload: false,
016bdaae   Nathanael Jourdane   Fix bad rendering...
168
169
	pageSize: 500,
	leadingBufferZone: 0,
87467502   Nathanael Jourdane   Replace page butt...
170
171
172
	proxy: {
		type: 'ajax',
		url: 'php/epntap.php',
11f8b45b   Nathanael Jourdane   Use buffered scro...
173
		reader: { type: 'json', root: 'data'},
6d616600   Nathanael Jourdane   Fix granules sorter
174
		simpleSortMode: true
016bdaae   Nathanael Jourdane   Fix bad rendering...
175
176
	},
	listeners: {
11f8b45b   Nathanael Jourdane   Use buffered scro...
177
		'beforeprefetch': function(store, operation) {
016bdaae   Nathanael Jourdane   Fix bad rendering...
178
			var service = Ext.data.StoreManager.lookup('servicesStore').getById(store.selectedService).data;
11f8b45b   Nathanael Jourdane   Use buffered scro...
179
180
181
182
			store.getProxy().extraParams = {
				'action': 'getGranules',
				'url': service['access_url'],
				'tableName': service['table_name'],
b5d477c6   Nathanael Jourdane   Allow multiple va...
183
				'targetNames': Ext.getCmp('epnTapTargetNameCB').rawValue,
11f8b45b   Nathanael Jourdane   Use buffered scro...
184
185
186
187
188
189
				'productTypes': Ext.getCmp('epnTapProductTypeCB').value.join(';'),
				'timeMin': Ext.Date.format(Ext.getCmp('epnTapTimeSelector').getStartTime(), 'd/m/Y H:i:s'),
				'timeMax': Ext.Date.format(Ext.getCmp('epnTapTimeSelector').getStopTime(), 'd/m/Y H:i:s'),
				'nbRes': service['nb_results']
			};
		},
6d616600   Nathanael Jourdane   Fix granules sorter
190
		'prefetch': function(store, records, successful, operation) {
30cd92df   Roipoussiere   Fix merge conflicts
191
			// console.log('(prefetch) operation ' + (successful ? 'success' : 'failed') + ': ', operation);
6d616600   Nathanael Jourdane   Fix granules sorter
192
193
194
			// console.log(operation.params);
			// console.log(Ext.decode(operation.response.responseText));
		},
a8a12768   Nathanael Jourdane   Create the grid m...
195
		'metachange': function(store, meta) {
a5475297   Nathanael Jourdane   use a hash for me...
196
197
198
199
			if(meta.metaHash != store.metaHash) {
				Ext.getCmp('epnTapGranulesGrid').reconfigure(store, meta.columns);
				store.metaHash = meta.metaHash;
			}
a8a12768   Nathanael Jourdane   Create the grid m...
200
201
		}
	}
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
202
203
});

465b7a40   Nathanael Jourdane   Escape quotes in ...
204
205
206
/**
Error are not displayed here, use try/catch each time it's necessary.
*/
7211d9b5   Nathanael Jourdane   Move util.Format ...
207
208
Ext.define('App.util.Format', {
	override: 'Ext.util.Format',
465b7a40   Nathanael Jourdane   Escape quotes in ...
209
210
211

	// Utils

24fcdbc7   Nathanael Jourdane   Fix crash when ep...
212
213
214
	'prettify': function(data) {
		return data.charAt(0).toUpperCase() + data.replace(/_/g, ' ').substr(1).toLowerCase();
	},
120b2445   Nathanael Jourdane   epntap grids: che...
215
216
217
218
219
220
221
222
223
	'url': function(data) {
		var url_pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
				'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.?)+[a-z]{2,}|'+ // domain name
				'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
				'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
				'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
				'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
		return url_pattern.test(data) ? data : null;
	},
3f51339d   Nathanael Jourdane   Make granules cel...
224
225
	'cell': function(content, tooltip, tooltipTitle) {
		var ttAttr = "";
120b2445   Nathanael Jourdane   epntap grids: che...
226
		if(tooltip !== '') {
3f51339d   Nathanael Jourdane   Make granules cel...
227
228
			var ttTitle = tooltipTitle ? " data-qtitle='" + tooltipTitle + "'" : "";
			ttAttr = ttTitle + "' data-qtip='" + (tooltip ? tooltip : (content ? content : 'No value.')) + "'";
120b2445   Nathanael Jourdane   epntap grids: che...
229
		}
3f51339d   Nathanael Jourdane   Make granules cel...
230
		return "<div class=epntap_cell " + ttAttr + ">" + (content ? content : '-') + "</div>";
120b2445   Nathanael Jourdane   epntap grids: che...
231
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
232
233
234

	// Services grid

120b2445   Nathanael Jourdane   epntap grids: che...
235
	'serviceTooltip': function(data) {
465b7a40   Nathanael Jourdane   Escape quotes in ...
236
237
238
239
240
		for (var key in data) {
			if(typeof data[key] == 'string' && data[key] != '') {
				data[key] = data[key].replace(/'/g, '&#39;').replace(/"/g, '&#34;');
			}
		}
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
241
		var infoColor = data.nb_results == -2 ? 'IndianRed' : 'green';
465b7a40   Nathanael Jourdane   Escape quotes in ...
242
		var info = data.info.length > 0 ? '<p style="color:' + infoColor + '">' + data.info + '</p>' : '';
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
243
244
245

		var colums = ['res_title', 'ivoid', 'access_url', 'table_name', 'content_type', 'creator_seq', 'content_level', 'reference_url', 'created', 'updated'];
		var details = '';
465b7a40   Nathanael Jourdane   Escape quotes in ...
246
247
248
249
		for (var key in colums) {
			if(data[colums[key]] !== '') {
				var val = colums[key] === 'content_level' ? data[colums[key]].replace(/#/g, ', ') : data[colums[key]];
				details += '<li><b>' + Ext.util.Format.prettify(colums[key]) + '</b>: ' + val + '</li>';
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
250
251
			}
		}
120b2445   Nathanael Jourdane   epntap grids: che...
252
		return info + '<ul>' + details + '</ul>';
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
253
254
	},
	'service.text': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
255
		return Ext.util.Format.cell(data, Ext.util.Format.serviceTooltip(record.data), data);
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
256
257
258
259
260
261
262
263
264
265
	},
	'service.number': function(data, metadata, record) {
		value = '' + data;
		if(data < 0) {
			value = '-';
		} else if(data >= 1000*1000) {
			value = (data/(1000*1000)).toPrecision(3) + 'm';
		} else if(data >= 1000) {
			value = (data/1000).toPrecision(3) + 'k';
		}
120b2445   Nathanael Jourdane   epntap grids: che...
266
		return Ext.util.Format.cell(value, Ext.util.Format.serviceTooltip(record.data), record.data.short_name);
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
267
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
268
269
270

	// Granules grid

465b7a40   Nathanael Jourdane   Escape quotes in ...
271
	'granule.text': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
272
		return Ext.util.Format.cell(data);
7211d9b5   Nathanael Jourdane   Move util.Format ...
273
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
274
	'granule.link': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
275
		var icon_b64 = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgaGVpZ2h0PSIxMDI0IiB3aWR0aD0iNzY4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik02NDAgNzY4SDEyOFYyNTcuOTA1OTk5OTk5OTk5OTVMMjU2IDI1NlYxMjhIMHY3NjhoNzY4VjU3Nkg2NDBWNzY4ek0zODQgMTI4bDEyOCAxMjhMMzIwIDQ0OGwxMjggMTI4IDE5Mi0xOTIgMTI4IDEyOFYxMjhIMzg0eiIvPjwvc3ZnPg==';
97ef04b4   Nathanael Jourdane   granules grid: se...
276
		var icon = '<img style="width:15px;" alt="link" src="' + icon_b64 + '">';
120b2445   Nathanael Jourdane   epntap grids: che...
277
278
279
280
281
		url = Ext.util.Format.url(data);
		if(url) {
			txt = '<a style="font-size:150%" target="_blank" href="' + url + '">' + icon + '</a>';
		}
		return Ext.util.Format.cell(txt, url);
7211d9b5   Nathanael Jourdane   Move util.Format ...
282
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
283
	'granule.img': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
284
285
286
		img_url = Ext.util.Format.url(data);
		if(img_url) {
			icon = '<img style="max-width:100%; max-height:100%" alt="-" src="' + img_url + '">';
97ef04b4   Nathanael Jourdane   granules grid: se...
287
			img = '<img style="max-width:200px; max-height:200px" src="' + img_url + '">';
120b2445   Nathanael Jourdane   epntap grids: che...
288
289
		}
		return Ext.util.Format.cell(icon, img);
7211d9b5   Nathanael Jourdane   Move util.Format ...
290
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
291
	'granule.type': function(data, metadata, record) {
7211d9b5   Nathanael Jourdane   Move util.Format ...
292
		var productTypeDict = Ext.data.StoreManager.lookup('productTypesStore').data.map;
120b2445   Nathanael Jourdane   epntap grids: che...
293
		return Ext.util.Format.cell(productTypeDict[data].data.name);
7211d9b5   Nathanael Jourdane   Move util.Format ...
294
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
295
	'granule.size': function(data, metadata, record) {
7211d9b5   Nathanael Jourdane   Move util.Format ...
296
		var size = parseInt(data);
7211d9b5   Nathanael Jourdane   Move util.Format ...
297
298
299
300
301
302
303
304
		if (isNaN(size)) {
		} else if (size >= 1024*1024) {
			txt = (size/(1024*1024)).toPrecision(3) + 'Go';
		} else if (size >= 1024) {
			txt = (size/1024).toPrecision(3) + 'Mo';
		} else {
			txt = size + 'Ko';
		}
120b2445   Nathanael Jourdane   epntap grids: che...
305
		return Ext.util.Format.cell(txt);
7211d9b5   Nathanael Jourdane   Move util.Format ...
306
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
307
	'granule.proc_lvl': function(data, metadata, record) {
c7967cba   Nathanael Jourdane   Improve display f...
308
		var levels = {1: 'Raw', 2: 'Edited', 3: 'Calibrated', 4: 'Resampled', 5: 'Derived', 6: 'Ancillary'};
120b2445   Nathanael Jourdane   epntap grids: che...
309
		return Ext.util.Format.cell((data in levels) ? levels[data] : '<em>' + data + '</em>');
c7967cba   Nathanael Jourdane   Improve display f...
310
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
311
	'granule.date': function(data, metadata, record) {
07382ff2   Nathanael Jourdane   Format dates
312
313
314
315
316
317
318
319
320
321
		if(isNaN(data)) {
			return '';
		}
		var f = Number(data) + 1401 + Math.floor((Math.floor((4 * Number(data) + 274277) / 146097) * 3) / 4) - 38;
		var e = 4 * f + 3;
		var g = Math.floor((e % 1461) / 4);
		var h = 5 * g + 2;
		var D = Math.floor((h % 153) / 5) + 1;
		var M = ((Math.floor(h / 153) + 2) % 12) + 1;
		var Y = Math.floor(e / 1461) - 4716 + Math.floor((12 + 2 - M) / 12);
120b2445   Nathanael Jourdane   epntap grids: che...
322
323
		var date = new Date(Y, M-1, D);
		return Ext.util.Format.cell(Ext.Date.format(date, 'Y/m/d'), Ext.Date.format(date, 'F j, Y, g:i a'));
7211d9b5   Nathanael Jourdane   Move util.Format ...
324
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
325
	'granule.format': function(data, metadata, record) {
7211d9b5   Nathanael Jourdane   Move util.Format ...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
		var mimetypeDict = {
			'application/fits': 'fits',
			'application/x-pds': 'pds',
			'image/x-pds': 'pds',
			'application/gml+xml': 'gml',
			'application/json': 'json',
			'application/octet-stream': 'bin, idl, envi or matlab',
			'application/pdf': 'pdf',
			'application/postscript': 'ps',
			'application/vnd.geo+json': 'geojson',
			'application/vnd.google-earth.kml+xml': 'kml',
			'application/vnd.google-earth.kmz': 'kmz',
			'application/vnd.ms-excel': 'xls',
			'application/x-asdm': 'asdm',
			'application/x-cdf': 'cdf',
			'application/x-cdf-istp': 'cdf',
			'application/x-cdf-pds4': 'cdf',
			'application/x-cef1': 'cef1',
			'application/x-cef2': 'cef2',
			'application/x-directory': 'dir',
			'application/x-fits-bintable': 'bintable',
			'application/x-fits-euro3d': 'euro3d',
			'application/x-fits-mef': 'mef',
			'application/x-geotiff': 'geotiff',
			'application/x-hdf': 'hdf',
			'application/x-netcdf': 'nc',
			'application/x-netcdf4': 'nc',
			'application/x-tar': 'tar',
			'application/x-tar-gzip': 'gtar',
			'application/x-votable+xml': 'votable',
			'application/x-votable+xml;content=datalink': 'votable',
			'application/zip': 'zip',
			'image/fits': 'fits',
			'image/gif': 'gif',
			'image/jpeg': 'jpeg',
			'image/png': 'png',
			'image/tiff': 'tiff',
			'image/x-fits-gzip': 'fits',
			'image/x-fits-hcompress': 'fits',
			'text/csv': 'csv',
			'text/html': 'html',
			'text/plain': 'txt',
			'text/tab-separated-values': 'tsv',
			'text/xml': 'xml',
			'video/mpeg': 'mpeg',
			'video/quicktime': 'mov',
			'video/x-msvideo': 'avi'
		};
120b2445   Nathanael Jourdane   epntap grids: che...
374
		return Ext.util.Format.cell((data in mimetypeDict) ? '<p>' + mimetypeDict[data] + '</p>' : '<em>' + data + '</em>');
7211d9b5   Nathanael Jourdane   Move util.Format ...
375
376
377
	}
});

b185823c   Nathanael Jourdane   Use IntervalUI mo...
378
379
380
381
382
383
/**
`EpnTapUI`: The view of the AMDA EPN-TAP module, allowing the user to query and display granules information from
EPN-TAP services.

Note: The controller part of this module is defined in `js/app/controller/EpnTapModule`.
*/
78c2f505   Nathanael Jourdane   Improve granules ...
384
Ext.define('amdaUI.EpnTapUI', {
b185823c   Nathanael Jourdane   Use IntervalUI mo...
385
	extend: 'Ext.panel.Panel',
78c2f505   Nathanael Jourdane   Improve granules ...
386
	alias: 'widget.panelEpnTap',
b185823c   Nathanael Jourdane   Use IntervalUI mo...
387
	requires: ['amdaUI.IntervalUI'],
78c2f505   Nathanael Jourdane   Improve granules ...
388

b185823c   Nathanael Jourdane   Use IntervalUI mo...
389
390
391
	/**
	Method constructor, which basically call the `init()` method to create the EpnTap panel.
	*/
78c2f505   Nathanael Jourdane   Improve granules ...
392
	constructor: function(config) {
78c2f505   Nathanael Jourdane   Improve granules ...
393
394
395
396
		this.init(config);
		this.callParent(arguments);
	},

10162678   Nathanael Jourdane   Fix the infoPanel...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
	/**
	Create all the EpnTapPanel UI elements, and apply the AMDA module `config` (which includes the created items).

	When the panel is correctly rendered, the panel triggers `EpnTapModule.onWindowLoaded()`.

	Note: All the UI elements creation are defined as functions in this init method and not as methods in order to make
	them private (ie. to avoid `EpnTapUI.createServicesGrid();`, which doesn't make sense).
	*/
	init: function(config) {
		var myConf = {
			id: 'epntapTab',
			title: 'EPN-TAP',
			layout: 'fit',
			items: [{
				xtype: 'container',
				layout: { type: 'vbox', pack: 'start', align: 'stretch'},
				items: [
					this.createServiceFilterPanel(),
cc6e16eb   Nathanael Jourdane   Remove info panel
415
					this.createGridsPanel()
10162678   Nathanael Jourdane   Fix the infoPanel...
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
				]
			}]
		};
		Ext.apply(this, Ext.apply(arguments, myConf));
	},

	/***************************
	*** Service filter panel ***
	***************************/

	/**
	Create `epnTapServiceFilterPanel`, an ExtJS Panel containing two containers:
	- the left container, containing the combo boxes (for product type, target class and target name)
		and the navigation panel;
	- the right container, containing the time selector.
	*/
	createServiceFilterPanel: function() {
		return {
30281591   Nathanael Jourdane   [WIP] Send reques...
434
			xtype: 'form',
10162678   Nathanael Jourdane   Fix the infoPanel...
435
436
437
			id: 'epnTapServiceFilterPanel',
			layout: { type: 'hbox', pack: 'start', align: 'stretch' },
			region: 'north',
33db0a91   Nathanael Jourdane   Add Get button (wip)
438
			defaults: { margin: '5 0 5 5'},
10162678   Nathanael Jourdane   Fix the infoPanel...
439
440
			items: [{ // Left part
				xtype : 'container',
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
441
				flex: 1,
10162678   Nathanael Jourdane   Fix the infoPanel...
442
				items: [
10162678   Nathanael Jourdane   Fix the infoPanel...
443
					this.createTargetNameCB(),
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
444
					this.createProductTypeCB()
10162678   Nathanael Jourdane   Fix the infoPanel...
445
				]
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
446
447
448
			}, { // Middle part
				xtype : 'container',
				flex: 1,
10162678   Nathanael Jourdane   Fix the infoPanel...
449
450
451
				items: [
					this.createTimeSelector()
				]
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
452
453
			}, { // Right part
				xtype : 'container',
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
454
				items: [
33db0a91   Nathanael Jourdane   Add Get button (wip)
455
					this.createSendButton()
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
456
457
				]

10162678   Nathanael Jourdane   Fix the infoPanel...
458
459
460
461
			}]
		};
	},

230b2236   Nathanael Jourdane   Add tooltip to pr...
462
463
464
465
466
467
468
469
470
471
472
473
474
		/**
		Create `epnTapTargetNameCB`, an ExtJS ComboBox, containing a list of target names corresponding to the selected
		target class, as defined in `targetNamesStore`, which is initilized by `EpnTapModule`.

		The selection of a target name triggers `EpnTapModule.onTargetNameCBChanged()`, which basically updates
		`granulesGrid`.
		*/
		createTargetNameCB: function() {
			return {
				xtype: 'combobox',
				id: 'epnTapTargetNameCB',
				fieldLabel: 'Target name',
				emptyText: 'Earth, Saturn, 67P, ...',
b5d477c6   Nathanael Jourdane   Allow multiple va...
475
				tooltip: 'Start to type a text, then select a target name (required). Several values are allowed, separated by a semicolon.',
230b2236   Nathanael Jourdane   Add tooltip to pr...
476
477
478
				store: Ext.data.StoreManager.lookup('targetNamesStore'),
				queryMode: 'remote',
				queryParam: 'input',
b5d477c6   Nathanael Jourdane   Allow multiple va...
479
				displayField: 'text',
230b2236   Nathanael Jourdane   Add tooltip to pr...
480
481
482
483
484
485
486
487
				valueField: 'id',
				margin: '15 0 5 0',
				labelWidth: 71,
				minWidth: 20,
				minChars: 2,
				hideTrigger: true,
				listConfig: {
					getInnerTpl: function() {
977e2c07   Nathanael Jourdane   Add tooltips on p...
488
						return '<div data-qtitle="{name}" data-qtip="<p>type: {type}</p><p>parent: {parent}</p><p>aliases:</p><ul>{aliases}</ul>">{name}</div>';
230b2236   Nathanael Jourdane   Add tooltip to pr...
489
490
491
492
					}
				},
				listeners: {
					render: function(cb) {
b5d477c6   Nathanael Jourdane   Allow multiple va...
493
						new Ext.ToolTip({ target: cb.getEl(), html: '<div style="width:200px">' + cb.tooltip + '</div>'});
230b2236   Nathanael Jourdane   Add tooltip to pr...
494
495
496
497
498
					}
				}
			};
		},

10162678   Nathanael Jourdane   Fix the infoPanel...
499
500
501
502
503
	/**
	Create `epnTapProductTypeCB`, an ExtJS ComboBox, containing a list of product types as defined in
	`epnTapProductTypesStore`, which is initilized by `EpnTapModule`.

	The selection of a produt type triggers `EpnTapModule.onProductTypeCBChanged()`, which basically update
ebdc15a7   Nathanael Jourdane   remove targetclas...
504
	`epnTapGranulesGrid`.
10162678   Nathanael Jourdane   Fix the infoPanel...
505
506
507
508
509
510
	*/
	createProductTypeCB: function() {
		return {
			xtype: 'combobox',
			id: 'epnTapProductTypeCB',
			fieldLabel: 'Product type',
96550534   Nathanael Jourdane   epntap: Make prod...
511
			emptyText: 'Image, Time series, ...',
b5d477c6   Nathanael Jourdane   Allow multiple va...
512
			tooltip: 'Select one or several data product types (required).',
10162678   Nathanael Jourdane   Fix the infoPanel...
513
514
515
			store: Ext.data.StoreManager.lookup('productTypesStore'),
			queryMode: 'local',
			valueField: 'id',
96550534   Nathanael Jourdane   epntap: Make prod...
516
			multiSelect: true,
10162678   Nathanael Jourdane   Fix the infoPanel...
517
			displayField: 'name',
33db0a91   Nathanael Jourdane   Add Get button (wip)
518
			labelWidth: 71,
96550534   Nathanael Jourdane   epntap: Make prod...
519
			editable: false,
977e2c07   Nathanael Jourdane   Add tooltips on p...
520
521
522
523
524
			listConfig: {
				getInnerTpl: function() {
					return '<div data-qtitle="{name}" data-qwidth=200 data-qtip="<p>{desc}</p>">{name}</div>';
				}
			},
96550534   Nathanael Jourdane   epntap: Make prod...
525
			listeners: {
264edda7   Nathanael Jourdane   Set product types...
526
				change: function(cb, records) {
3345b95b   Nathanael Jourdane   nbResults refacto...
527
528
529
530
531
					var val = cb.value[cb.value.length - 1];
					if(val === 'all') {
						cb.select(cb.store.getRange().slice(2));
					} else if (val === 'clear') {
						cb.reset();
96550534   Nathanael Jourdane   epntap: Make prod...
532
					}
230b2236   Nathanael Jourdane   Add tooltip to pr...
533
534
				},
				render: function(cb) {
b5d477c6   Nathanael Jourdane   Allow multiple va...
535
					new Ext.ToolTip({ target: cb.getEl(), html: '<div style="width:200px">' + cb.tooltip + '</div>'});
ebdc15a7   Nathanael Jourdane   remove targetclas...
536
537
				}
			}
10162678   Nathanael Jourdane   Fix the infoPanel...
538
539
		};
	},
ebdc15a7   Nathanael Jourdane   remove targetclas...
540

10162678   Nathanael Jourdane   Fix the infoPanel...
541
542
543
544
545
546
547
548
549
	/**
	Create `epnTapTimeSelector`, an IntervalUI object, allowing the user to select a time interval (by filling two
	dates and/or a duration).

	See `js/app/views/IntervalUI.js` for more information about this component.
	*/
	createTimeSelector: function() {
		return {
			xtype: 'intervalSelector',
0de2b2fd   Nathanael Jourdane   fix and improve i...
550
			id: 'epnTapTimeSelector'
10162678   Nathanael Jourdane   Fix the infoPanel...
551
552
553
554
555
556
557
558
		};
	},

	/***********************
	*** Navigation panel ***
	***********************/

	/**
33db0a91   Nathanael Jourdane   Add Get button (wip)
559
560
561
562
563
564
	The button used to send the query.
	*/
	createSendButton: function() {
		return {
			xtype: 'button',
			id: 'epnTapGetBtn',
f7556592   Nathanael Jourdane   clear granules gr...
565
			text: 'Get services',
33db0a91   Nathanael Jourdane   Add Get button (wip)
566
567
			disabled: true,
			width: 140,
87467502   Nathanael Jourdane   Replace page butt...
568
569
			height: 50,
			margin: 10
33db0a91   Nathanael Jourdane   Add Get button (wip)
570
571
572
		}
	},

9655907c   Nathanael Jourdane   use a more extjs-...
573
574
575
576
	/************
	*** Grids ***
	************/

b185823c   Nathanael Jourdane   Use IntervalUI mo...
577
	/**
10162678   Nathanael Jourdane   Fix the infoPanel...
578
579
580
581
582
583
584
585
586
587
	Create `epnTapGridsPanel`, an ExtJS Panel, containing `epnTapServicesGrid` and `epnTapGranulesGrid`.

	After the rendering of the grids, it triggers `epnTapModule.onWindowLoaded()`, which basically fill
	`epnTapServicesGrid` for the first time.
	*/
	createGridsPanel: function() {
		return {
			xtype: 'panel',
			id: 'epnTapGridsPanel',
			layout: 'fit',
33db0a91   Nathanael Jourdane   Add Get button (wip)
588
			height: 440,
10162678   Nathanael Jourdane   Fix the infoPanel...
589
590
591
592
593
594
595
596
597
598
599
600
			region: 'center',
			items: [{
				xtype: 'container',
				layout: { type: 'hbox', pack: 'start', align: 'stretch'},
				items: [
					this.createServicesGrid(),
					this.createGranulesGrid()
				]
			}]
		};
	},

10162678   Nathanael Jourdane   Fix the infoPanel...
601
	/**
9655907c   Nathanael Jourdane   use a more extjs-...
602
603
	Create `epnTapServicesGrid`, an ExtJS grid containing the EPN-TAP services matching with the filter form
	(`serviceFilterPanel`).
b185823c   Nathanael Jourdane   Use IntervalUI mo...
604

9655907c   Nathanael Jourdane   use a more extjs-...
605
606
607
	For each service, this grid displays:
	- the service name;
	- the number of granules matching with the filter.
b185823c   Nathanael Jourdane   Use IntervalUI mo...
608

9655907c   Nathanael Jourdane   use a more extjs-...
609
610
611
612
613
614
615
	Other informations are available through an ExtJS Tooltip, on each row:
	- short name;
	- title;
	- access URL.

	A click on a service triggers `EpnTapModule.onServiceSelected()`, which basically fills `GranulesGrid` by the
	service granules.
b185823c   Nathanael Jourdane   Use IntervalUI mo...
616
	*/
9655907c   Nathanael Jourdane   use a more extjs-...
617
	createServicesGrid: function() {
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
618
619
		return {
			xtype: 'grid',
120b2445   Nathanael Jourdane   epntap grids: che...
620
			cls: 'epntap_grid',
9655907c   Nathanael Jourdane   use a more extjs-...
621
622
623
624
			id: 'epnTapServicesGrid',
			title: 'Services',
			store: Ext.data.StoreManager.lookup('servicesStore'),
			flex: 1,
9655907c   Nathanael Jourdane   use a more extjs-...
625
			columns: [
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
626
627
				{text: 'Name', dataIndex: 'short_name', flex: 1, renderer: 'service.text'},
				{text: 'Nb res.', dataIndex: 'nb_results', width: 50, renderer: 'service.number'}
9655907c   Nathanael Jourdane   use a more extjs-...
628
			],
9655907c   Nathanael Jourdane   use a more extjs-...
629
			viewConfig: {
9655907c   Nathanael Jourdane   use a more extjs-...
630
				getRowClass: function(record, index) {
49401187   Nathanael Jourdane   epntap: Do not us...
631
					var nb_res = record.get('nb_results');
3345b95b   Nathanael Jourdane   nbResults refacto...
632
					if(nb_res == 0 || nb_res == -1) {
9655907c   Nathanael Jourdane   use a more extjs-...
633
						return 'disabled_row';
3345b95b   Nathanael Jourdane   nbResults refacto...
634
635
					} else if (nb_res == -2) {
						return 'error_row';
8d5634e3   Nathanael Jourdane   Use epn-tap store...
636
					}
9655907c   Nathanael Jourdane   use a more extjs-...
637
				}
9655907c   Nathanael Jourdane   use a more extjs-...
638
			}
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
639
		};
9655907c   Nathanael Jourdane   use a more extjs-...
640
	},
b185823c   Nathanael Jourdane   Use IntervalUI mo...
641

9655907c   Nathanael Jourdane   use a more extjs-...
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
	/**
	Create `epnTapGranulesGrid`, an ExtJS grid containing the granules of the selected service in
	`epnTapServicesGrid`.

	For each granule, this grid displays:
	- the row number;
	- the dataproduct type;
	- the target name;
	- the min and max times;
	- the format;
	- the UID (granule identifier);
	- the estimated size;
	- the URL;
	- the thumbnail.

	Each of these information are displayed in a specific rendering to improve user experience.
	For more information about these parameters, see https://voparis-confluence.obspm.fr/display/VES/EPN-TAP+V2.0+parameters.

	Other informations are available through an ExtJS Tooltip on each row:
	- currently only the granule thumbnail, in full size.

	A click on a granule triggers `EpnTapModule.onGranuleSelected()`.
9655907c   Nathanael Jourdane   use a more extjs-...
664
665
	*/
	createGranulesGrid: function() {
465b7a40   Nathanael Jourdane   Escape quotes in ...
666
667
		return {
			xtype: 'grid',
120b2445   Nathanael Jourdane   epntap grids: che...
668
			cls: 'epntap_grid',
9655907c   Nathanael Jourdane   use a more extjs-...
669
670
671
672
			id: 'epnTapGranulesGrid',
			title: 'Granules',
			store: Ext.data.StoreManager.lookup('granulesStore'),
			flex: 4,
016bdaae   Nathanael Jourdane   Fix bad rendering...
673
674
675
676
677
			plugins: {
				ptype: 'bufferedrenderer',
				trailingBufferZone: 20,
				leadingBufferZone: 50
			},
11f8b45b   Nathanael Jourdane   Use buffered scro...
678
			columns: []
465b7a40   Nathanael Jourdane   Escape quotes in ...
679
		};
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
680
681
	}
});