Blame view

js/app/views/EpnTapUI.js 23 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',
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
65
66
67
	fields: ['id', 'name', 'type', 'parent', 'aliases'],
	proxy: {
		type: 'ajax',
68664dca   Nathanael Jourdane   make epntap php f...
68
		url: 'php/epntap.php',
50dd7220   Nathanael Jourdane   epntap.php works ...
69
70
71
72
73
74
		extraParams: { action: 'resolver' }
		// listeners: {
		// 	exception: function(proxy, response, operation) {
		// 		console.log('Error ', response); //TODO: Use ExtJs alert instead
		// 	}
		// }
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
75
	}
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
76
77
});

12c10cdb   Nathanael Jourdane   Get the list of s...
78
79
80
81
82
83
84
/**
`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...
85

12c10cdb   Nathanael Jourdane   Get the list of s...
86
87
88
89
90
91
92
93
94
- `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...
95
Ext.create('Ext.data.Store', {
12c10cdb   Nathanael Jourdane   Get the list of s...
96
	storeId: 'servicesStore',
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
97
	autoLoad: true,
12c10cdb   Nathanael Jourdane   Get the list of s...
98
99
100
101
102
103
104
105
106
107
108
109
110
	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...
111
		{name: 'nb_results', type: 'integer'},
016bdaae   Nathanael Jourdane   Fix bad rendering...
112
		{name: 'info', type: 'string'}
8d5634e3   Nathanael Jourdane   Use epn-tap store...
113
114
115
	],
	proxy: {
		type: 'ajax',
49401187   Nathanael Jourdane   epntap: Do not us...
116
		url: 'php/epntap.php',
8c2fa14d   Nathanael Jourdane   Update services g...
117
118
119
120
121
		extraParams : {action: 'getServices'}
	},
	sorters: [
		{property: 'nb_results', direction: 'DESC'},
		{property: 'short_name', direction: 'ASC'}
a8a12768   Nathanael Jourdane   Create the grid m...
122
123
124
125
	],
	listeners: {
		// load: function(record) { console.log(record); }
	}
8d5634e3   Nathanael Jourdane   Use epn-tap store...
126
127
});

b185823c   Nathanael Jourdane   Use IntervalUI mo...
128
/**
b185823c   Nathanael Jourdane   Use IntervalUI mo...
129
`granulesStore`: An ExtJS Store containing the list of granules of the selected service (on `servicesGrid`), which match
ba6dfa5e   Nathanael Jourdane   (regression bug) ...
130
with the granules filter (the selected data product type, target class and target name).
b185823c   Nathanael Jourdane   Use IntervalUI mo...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

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
147
// 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...
148
149
150
151
152
153

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

3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
154
Ext.create('Ext.data.Store', {
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
155
	storeId: 'granulesStore',
016bdaae   Nathanael Jourdane   Fix bad rendering...
156
	model: 'GranulesModel',
11f8b45b   Nathanael Jourdane   Use buffered scro...
157
	buffered: true,
87467502   Nathanael Jourdane   Replace page butt...
158
	autoload: false,
016bdaae   Nathanael Jourdane   Fix bad rendering...
159
160
	pageSize: 500,
	leadingBufferZone: 0,
87467502   Nathanael Jourdane   Replace page butt...
161
162
163
	proxy: {
		type: 'ajax',
		url: 'php/epntap.php',
11f8b45b   Nathanael Jourdane   Use buffered scro...
164
		reader: { type: 'json', root: 'data'},
6d616600   Nathanael Jourdane   Fix granules sorter
165
		simpleSortMode: true
016bdaae   Nathanael Jourdane   Fix bad rendering...
166
167
	},
	listeners: {
11f8b45b   Nathanael Jourdane   Use buffered scro...
168
		'beforeprefetch': function(store, operation) {
016bdaae   Nathanael Jourdane   Fix bad rendering...
169
			var service = Ext.data.StoreManager.lookup('servicesStore').getById(store.selectedService).data;
11f8b45b   Nathanael Jourdane   Use buffered scro...
170
171
172
173
174
175
176
177
178
179
180
			store.getProxy().extraParams = {
				'action': 'getGranules',
				'url': service['access_url'],
				'tableName': service['table_name'],
				'targetName': Ext.getCmp('epnTapTargetNameCB').rawValue,
				'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
181
		'prefetch': function(store, records, successful, operation) {
30cd92df   Roipoussiere   Fix merge conflicts
182
			// console.log('(prefetch) operation ' + (successful ? 'success' : 'failed') + ': ', operation);
6d616600   Nathanael Jourdane   Fix granules sorter
183
184
185
			// console.log(operation.params);
			// console.log(Ext.decode(operation.response.responseText));
		},
a8a12768   Nathanael Jourdane   Create the grid m...
186
		'metachange': function(store, meta) {
a5475297   Nathanael Jourdane   use a hash for me...
187
188
189
190
			if(meta.metaHash != store.metaHash) {
				Ext.getCmp('epnTapGranulesGrid').reconfigure(store, meta.columns);
				store.metaHash = meta.metaHash;
			}
a8a12768   Nathanael Jourdane   Create the grid m...
191
192
		}
	}
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
193
194
});

465b7a40   Nathanael Jourdane   Escape quotes in ...
195
196
197
/**
Error are not displayed here, use try/catch each time it's necessary.
*/
7211d9b5   Nathanael Jourdane   Move util.Format ...
198
199
Ext.define('App.util.Format', {
	override: 'Ext.util.Format',
465b7a40   Nathanael Jourdane   Escape quotes in ...
200
201
202

	// Utils

24fcdbc7   Nathanael Jourdane   Fix crash when ep...
203
204
205
	'prettify': function(data) {
		return data.charAt(0).toUpperCase() + data.replace(/_/g, ' ').substr(1).toLowerCase();
	},
120b2445   Nathanael Jourdane   epntap grids: che...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
	'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;
	},
	'cell': function(content, tooltip=null, tooltipTitle='') {
		content = content ? content : '-';
		if(tooltip !== '') {
			var ttAttr = " data-qtitle='" + tooltipTitle + "' data-qtip='" + (tooltip ? tooltip : content) + "'";
		}
		return "<div class=epntap_cell " + ttAttr + ">" + content + "</div>";
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
222
223
224

	// Services grid

120b2445   Nathanael Jourdane   epntap grids: che...
225
	'serviceTooltip': function(data) {
465b7a40   Nathanael Jourdane   Escape quotes in ...
226
227
228
229
230
		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...
231
		var infoColor = data.nb_results == -2 ? 'IndianRed' : 'green';
465b7a40   Nathanael Jourdane   Escape quotes in ...
232
		var info = data.info.length > 0 ? '<p style="color:' + infoColor + '">' + data.info + '</p>' : '';
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
233
234
235

		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 ...
236
237
238
239
		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...
240
241
			}
		}
120b2445   Nathanael Jourdane   epntap grids: che...
242
		return info + '<ul>' + details + '</ul>';
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
243
244
	},
	'service.text': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
245
		return Ext.util.Format.cell(data, Ext.util.Format.serviceTooltip(record.data), data);
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
246
247
248
249
250
251
252
253
254
255
	},
	'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...
256
		return Ext.util.Format.cell(value, Ext.util.Format.serviceTooltip(record.data), record.data.short_name);
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
257
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
258
259
260

	// Granules grid

465b7a40   Nathanael Jourdane   Escape quotes in ...
261
	'granule.text': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
262
		return Ext.util.Format.cell(data);
7211d9b5   Nathanael Jourdane   Move util.Format ...
263
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
264
	'granule.link': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
265
266
267
268
269
270
271
		var icon_b64 = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgaGVpZ2h0PSIxMDI0IiB3aWR0aD0iNzY4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik02NDAgNzY4SDEyOFYyNTcuOTA1OTk5OTk5OTk5OTVMMjU2IDI1NlYxMjhIMHY3NjhoNzY4VjU3Nkg2NDBWNzY4ek0zODQgMTI4bDEyOCAxMjhMMzIwIDQ0OGwxMjggMTI4IDE5Mi0xOTIgMTI4IDEyOFYxMjhIMzg0eiIvPjwvc3ZnPg==';
		var icon = '<img width="15px height="15px" src="' + icon_b64 + '">';
		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 ...
272
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
273
	'granule.img': function(data, metadata, record) {
120b2445   Nathanael Jourdane   epntap grids: che...
274
275
276
277
278
279
		img_url = Ext.util.Format.url(data);
		if(img_url) {
			icon = '<img style="max-width:100%; max-height:100%" alt="-" src="' + img_url + '">';
			img = '<img style="max-width:200px; max-height:200px" alt="-" src="' + img_url + '">';
		}
		return Ext.util.Format.cell(icon, img);
7211d9b5   Nathanael Jourdane   Move util.Format ...
280
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
281
	'granule.type': function(data, metadata, record) {
7211d9b5   Nathanael Jourdane   Move util.Format ...
282
		var productTypeDict = Ext.data.StoreManager.lookup('productTypesStore').data.map;
120b2445   Nathanael Jourdane   epntap grids: che...
283
		return Ext.util.Format.cell(productTypeDict[data].data.name);
7211d9b5   Nathanael Jourdane   Move util.Format ...
284
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
285
	'granule.size': function(data, metadata, record) {
7211d9b5   Nathanael Jourdane   Move util.Format ...
286
		var size = parseInt(data);
7211d9b5   Nathanael Jourdane   Move util.Format ...
287
288
289
290
291
292
293
294
		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...
295
		return Ext.util.Format.cell(txt);
7211d9b5   Nathanael Jourdane   Move util.Format ...
296
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
297
	'granule.proc_lvl': function(data, metadata, record) {
c7967cba   Nathanael Jourdane   Improve display f...
298
		var levels = {1: 'Raw', 2: 'Edited', 3: 'Calibrated', 4: 'Resampled', 5: 'Derived', 6: 'Ancillary'};
120b2445   Nathanael Jourdane   epntap grids: che...
299
		return Ext.util.Format.cell((data in levels) ? levels[data] : '<em>' + data + '</em>');
c7967cba   Nathanael Jourdane   Improve display f...
300
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
301
	'granule.date': function(data, metadata, record) {
07382ff2   Nathanael Jourdane   Format dates
302
303
304
305
306
307
308
309
310
311
		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...
312
313
		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 ...
314
	},
465b7a40   Nathanael Jourdane   Escape quotes in ...
315
	'granule.format': function(data, metadata, record) {
7211d9b5   Nathanael Jourdane   Move util.Format ...
316
317
318
319
320
321
322
323
324
325
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
		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...
364
		return Ext.util.Format.cell((data in mimetypeDict) ? '<p>' + mimetypeDict[data] + '</p>' : '<em>' + data + '</em>');
7211d9b5   Nathanael Jourdane   Move util.Format ...
365
366
367
	}
});

b185823c   Nathanael Jourdane   Use IntervalUI mo...
368
369
370
371
372
373
/**
`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 ...
374
Ext.define('amdaUI.EpnTapUI', {
b185823c   Nathanael Jourdane   Use IntervalUI mo...
375
	extend: 'Ext.panel.Panel',
78c2f505   Nathanael Jourdane   Improve granules ...
376
	alias: 'widget.panelEpnTap',
b185823c   Nathanael Jourdane   Use IntervalUI mo...
377
	requires: ['amdaUI.IntervalUI'],
78c2f505   Nathanael Jourdane   Improve granules ...
378

b185823c   Nathanael Jourdane   Use IntervalUI mo...
379
380
381
	/**
	Method constructor, which basically call the `init()` method to create the EpnTap panel.
	*/
78c2f505   Nathanael Jourdane   Improve granules ...
382
	constructor: function(config) {
78c2f505   Nathanael Jourdane   Improve granules ...
383
384
385
386
		this.init(config);
		this.callParent(arguments);
	},

10162678   Nathanael Jourdane   Fix the infoPanel...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
	/**
	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
405
					this.createGridsPanel()
10162678   Nathanael Jourdane   Fix the infoPanel...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
				]
			}]
		};
		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...
424
			xtype: 'form',
10162678   Nathanael Jourdane   Fix the infoPanel...
425
426
427
			id: 'epnTapServiceFilterPanel',
			layout: { type: 'hbox', pack: 'start', align: 'stretch' },
			region: 'north',
33db0a91   Nathanael Jourdane   Add Get button (wip)
428
			defaults: { margin: '5 0 5 5'},
10162678   Nathanael Jourdane   Fix the infoPanel...
429
430
			items: [{ // Left part
				xtype : 'container',
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
431
				flex: 1,
10162678   Nathanael Jourdane   Fix the infoPanel...
432
				items: [
10162678   Nathanael Jourdane   Fix the infoPanel...
433
					this.createTargetNameCB(),
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
434
					this.createProductTypeCB()
10162678   Nathanael Jourdane   Fix the infoPanel...
435
				]
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
436
437
438
			}, { // Middle part
				xtype : 'container',
				flex: 1,
10162678   Nathanael Jourdane   Fix the infoPanel...
439
440
441
				items: [
					this.createTimeSelector()
				]
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
442
443
			}, { // Right part
				xtype : 'container',
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
444
				items: [
33db0a91   Nathanael Jourdane   Add Get button (wip)
445
					this.createSendButton()
ebd733ce   Nathanael Jourdane   epntap: Reorder f...
446
447
				]

10162678   Nathanael Jourdane   Fix the infoPanel...
448
449
450
451
			}]
		};
	},

230b2236   Nathanael Jourdane   Add tooltip to pr...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
		/**
		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, ...',
				store: Ext.data.StoreManager.lookup('targetNamesStore'),
				queryMode: 'remote',
				queryParam: 'input',
				displayField: 'name',
				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...
477
						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...
478
479
480
481
482
483
484
485
486
487
488
489
490
					}
				},
				listeners: {
					render: function(cb) {
						new Ext.ToolTip({
							target: cb.getEl(),
							html: 'Start to type a text then select a target name (required).'
						});
					}
				}
			};
		},

10162678   Nathanael Jourdane   Fix the infoPanel...
491
492
493
494
495
	/**
	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...
496
	`epnTapGranulesGrid`.
10162678   Nathanael Jourdane   Fix the infoPanel...
497
498
499
500
501
502
	*/
	createProductTypeCB: function() {
		return {
			xtype: 'combobox',
			id: 'epnTapProductTypeCB',
			fieldLabel: 'Product type',
96550534   Nathanael Jourdane   epntap: Make prod...
503
			emptyText: 'Image, Time series, ...',
10162678   Nathanael Jourdane   Fix the infoPanel...
504
505
506
			store: Ext.data.StoreManager.lookup('productTypesStore'),
			queryMode: 'local',
			valueField: 'id',
96550534   Nathanael Jourdane   epntap: Make prod...
507
			multiSelect: true,
10162678   Nathanael Jourdane   Fix the infoPanel...
508
			displayField: 'name',
33db0a91   Nathanael Jourdane   Add Get button (wip)
509
			labelWidth: 71,
96550534   Nathanael Jourdane   epntap: Make prod...
510
			editable: false,
977e2c07   Nathanael Jourdane   Add tooltips on p...
511
512
513
514
515
			listConfig: {
				getInnerTpl: function() {
					return '<div data-qtitle="{name}" data-qwidth=200 data-qtip="<p>{desc}</p>">{name}</div>';
				}
			},
96550534   Nathanael Jourdane   epntap: Make prod...
516
			listeners: {
264edda7   Nathanael Jourdane   Set product types...
517
				change: function(cb, records) {
3345b95b   Nathanael Jourdane   nbResults refacto...
518
519
520
521
522
					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...
523
					}
230b2236   Nathanael Jourdane   Add tooltip to pr...
524
525
				},
				render: function(cb) {
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
526
					new Ext.ToolTip({
230b2236   Nathanael Jourdane   Add tooltip to pr...
527
528
						target: cb.getEl(),
						html: 'Select one or several data product types (required).'
8a0f1e9e   Nathanael Jourdane   Add autocompletio...
529
					});
ebdc15a7   Nathanael Jourdane   remove targetclas...
530
531
				}
			}
10162678   Nathanael Jourdane   Fix the infoPanel...
532
533
		};
	},
ebdc15a7   Nathanael Jourdane   remove targetclas...
534

10162678   Nathanael Jourdane   Fix the infoPanel...
535
536
537
538
539
540
541
542
543
	/**
	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...
544
			id: 'epnTapTimeSelector'
10162678   Nathanael Jourdane   Fix the infoPanel...
545
546
547
548
549
550
551
552
		};
	},

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

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

9655907c   Nathanael Jourdane   use a more extjs-...
567
568
569
570
	/************
	*** Grids ***
	************/

b185823c   Nathanael Jourdane   Use IntervalUI mo...
571
	/**
10162678   Nathanael Jourdane   Fix the infoPanel...
572
573
574
575
576
577
578
579
580
581
	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)
582
			height: 440,
10162678   Nathanael Jourdane   Fix the infoPanel...
583
584
585
586
587
588
589
590
591
592
593
594
			region: 'center',
			items: [{
				xtype: 'container',
				layout: { type: 'hbox', pack: 'start', align: 'stretch'},
				items: [
					this.createServicesGrid(),
					this.createGranulesGrid()
				]
			}]
		};
	},

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

9655907c   Nathanael Jourdane   use a more extjs-...
599
600
601
	For each service, this grid displays:
	- the service name;
	- the number of granules matching with the filter.
b185823c   Nathanael Jourdane   Use IntervalUI mo...
602

9655907c   Nathanael Jourdane   use a more extjs-...
603
604
605
606
607
608
609
	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...
610
	*/
9655907c   Nathanael Jourdane   use a more extjs-...
611
	createServicesGrid: function() {
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
612
613
		return {
			xtype: 'grid',
120b2445   Nathanael Jourdane   epntap grids: che...
614
			cls: 'epntap_grid',
9655907c   Nathanael Jourdane   use a more extjs-...
615
616
617
618
			id: 'epnTapServicesGrid',
			title: 'Services',
			store: Ext.data.StoreManager.lookup('servicesStore'),
			flex: 1,
9655907c   Nathanael Jourdane   use a more extjs-...
619
			columns: [
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
620
621
				{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-...
622
			],
9655907c   Nathanael Jourdane   use a more extjs-...
623
			viewConfig: {
9655907c   Nathanael Jourdane   use a more extjs-...
624
				getRowClass: function(record, index) {
49401187   Nathanael Jourdane   epntap: Do not us...
625
					var nb_res = record.get('nb_results');
3345b95b   Nathanael Jourdane   nbResults refacto...
626
					if(nb_res == 0 || nb_res == -1) {
9655907c   Nathanael Jourdane   use a more extjs-...
627
						return 'disabled_row';
3345b95b   Nathanael Jourdane   nbResults refacto...
628
629
					} else if (nb_res == -2) {
						return 'error_row';
8d5634e3   Nathanael Jourdane   Use epn-tap store...
630
					}
9655907c   Nathanael Jourdane   use a more extjs-...
631
				}
9655907c   Nathanael Jourdane   use a more extjs-...
632
			}
24fcdbc7   Nathanael Jourdane   Fix crash when ep...
633
		};
9655907c   Nathanael Jourdane   use a more extjs-...
634
	},
b185823c   Nathanael Jourdane   Use IntervalUI mo...
635

9655907c   Nathanael Jourdane   use a more extjs-...
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
	/**
	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-...
658
659
	*/
	createGranulesGrid: function() {
465b7a40   Nathanael Jourdane   Escape quotes in ...
660
661
		return {
			xtype: 'grid',
120b2445   Nathanael Jourdane   epntap grids: che...
662
			cls: 'epntap_grid',
9655907c   Nathanael Jourdane   use a more extjs-...
663
664
665
666
			id: 'epnTapGranulesGrid',
			title: 'Granules',
			store: Ext.data.StoreManager.lookup('granulesStore'),
			flex: 4,
016bdaae   Nathanael Jourdane   Fix bad rendering...
667
668
669
670
671
			plugins: {
				ptype: 'bufferedrenderer',
				trailingBufferZone: 20,
				leadingBufferZone: 50
			},
11f8b45b   Nathanael Jourdane   Use buffered scro...
672
			columns: []
465b7a40   Nathanael Jourdane   Escape quotes in ...
673
		};
3fc0b658   Nathanael Jourdane   Add EPN-TAP modul...
674
675
	}
});