Commit 6491a1f1006f76a7f044a2656f2bd426b49edaf2

Authored by Goutte
1 parent 3faa136f

Fix up the bugs listed by Vincent.

@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 - [ ] Cache cleanup 21 - [ ] Cache cleanup
22 - [x] API at /cache/clear 22 - [x] API at /cache/clear
23 - [ ] CRON statement to call it 23 - [ ] CRON statement to call it
  24 +- [ ] Cache warmup
24 - [x] Download raw data (tarball of CSV) for current time interval and targets 25 - [x] Download raw data (tarball of CSV) for current time interval and targets
25 - [ ] Download raw data as NetCDF for current everything, via SAMP 26 - [ ] Download raw data as NetCDF for current everything, via SAMP
26 - [x] Add a warning for users with javascript disabled 27 - [x] Add a warning for users with javascript disabled
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 # The HTML metadata in the page header. 5 # The HTML metadata in the page header.
6 # Don't put double quotes (") in any of these fields. 6 # Don't put double quotes (") in any of these fields.
7 meta: 7 meta:
8 - title: Space Weather 8 + title: Heliopropa ⋅ Solar System Weather
9 keywords: 9 keywords:
10 - science 10 - science
11 - cdpp 11 - cdpp
@@ -15,6 +15,16 @@ meta: @@ -15,6 +15,16 @@ meta:
15 # Will be shown by search engines below the title of the page. 15 # Will be shown by search engines below the title of the page.
16 description: Space weather predictions around solar celestial bodies. 16 description: Space weather predictions around solar celestial bodies.
17 17
  18 +# The top bar
  19 +header:
  20 + title: CDPP / Heliopropa
  21 + links:
  22 + - text: Model
  23 + href: "https://onlinelibrary.wiley.com/doi/10.1029/2004JA010959/abstract"
  24 + - text: Horizon 2020
  25 + href: "https://ec.europa.eu/programmes/horizon2020/"
  26 +
  27 +
18 28
19 # A list of authors that will appear in the HTML metadata and possibly in the 29 # A list of authors that will appear in the HTML metadata and possibly in the
20 # authorship page as well. The order does not matter, it will be shuffled. 30 # authorship page as well. The order does not matter, it will be shuffled.
@@ -283,7 +283,7 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at): @@ -283,7 +283,7 @@ def retrieve_amda_netcdf(orbiter, what, started_at, stopped_at):
283 # innermost loop of `get_data_for_target`. 283 # innermost loop of `get_data_for_target`.
284 # The javascript knows the targets' properties under these names. 284 # The javascript knows the targets' properties under these names.
285 PROPERTIES = ('time', 'vrad', 'vtan', 'vlen', 'magn', 'temp', 'pdyn', 'dens', 285 PROPERTIES = ('time', 'vrad', 'vtan', 'vlen', 'magn', 'temp', 'pdyn', 'dens',
286 - 'angl', 'xhci', 'yhci') 286 + 'angl', 'xhee', 'yhee')
287 287
288 # The parameters that the users can handle. 288 # The parameters that the users can handle.
289 # The slug must be one of the properties above. 289 # The slug must be one of the properties above.
@@ -371,12 +371,12 @@ def get_data_for_target(target_config, started_at, stopped_at): @@ -371,12 +371,12 @@ def get_data_for_target(target_config, started_at, stopped_at):
371 (target_config['name'], orbit_file)) 371 (target_config['name'], orbit_file))
372 cdf_handle = Dataset(orbit_file, "r", format="NETCDF4") 372 cdf_handle = Dataset(orbit_file, "r", format="NETCDF4")
373 times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms 373 times = cdf_handle.variables['Time'] # YYYY DOY HH MM SS .ms
374 - data_hci = cdf_handle.variables['HCI']  
375 - for time, datum_hci in zip(times, data_hci): 374 + data_hee = cdf_handle.variables['HEE']
  375 + for time, datum_hee in zip(times, data_hee):
376 dtime = datetime_from_list(time) 376 dtime = datetime_from_list(time)
377 if started_at <= dtime <= stopped_at: 377 if started_at <= dtime <= stopped_at:
378 dkey = dtime.strftime(precision) 378 dkey = dtime.strftime(precision)
379 - orbit_data[dkey] = datum_hci 379 + orbit_data[dkey] = datum_hee
380 cdf_handle.close() 380 cdf_handle.close()
381 381
382 all_data = {} # keys are datetime as str, values tuples of data 382 all_data = {} # keys are datetime as str, values tuples of data
@@ -401,16 +401,16 @@ def get_data_for_target(target_config, started_at, stopped_at): @@ -401,16 +401,16 @@ def get_data_for_target(target_config, started_at, stopped_at):
401 dtime = datetime_from_list(time) 401 dtime = datetime_from_list(time)
402 if started_at <= dtime <= stopped_at: 402 if started_at <= dtime <= stopped_at:
403 dkey = dtime.strftime(precision) 403 dkey = dtime.strftime(precision)
404 - x_hci = None  
405 - y_hci = None 404 + x_hee = None
  405 + y_hee = None
406 if dkey in orbit_data: 406 if dkey in orbit_data:
407 - x_hci = orbit_data[dkey][0]  
408 - y_hci = orbit_data[dkey][1] 407 + x_hee = orbit_data[dkey][0]
  408 + y_hee = orbit_data[dkey][1]
409 all_data[dkey] = ( 409 all_data[dkey] = (
410 dtime.strftime("%Y-%m-%dT%H:%M:%S+00:00"), 410 dtime.strftime("%Y-%m-%dT%H:%M:%S+00:00"),
411 vrad, vtan, sqrt(vrad * vrad + vtan * vtan), 411 vrad, vtan, sqrt(vrad * vrad + vtan * vtan),
412 datum_b, datum_t, datum_n, datum_p, datum_d, 412 datum_b, datum_t, datum_n, datum_p, datum_d,
413 - x_hci, y_hci 413 + x_hee, y_hee
414 ) 414 )
415 cdf_handle.close() 415 cdf_handle.close()
416 416
@@ -726,14 +726,14 @@ def download_targets_netcdf(targets, params, started_at, stopped_at): @@ -726,14 +726,14 @@ def download_targets_netcdf(targets, params, started_at, stopped_at):
726 nc_var[:] = values 726 nc_var[:] = values
727 727
728 # ORBIT # 728 # ORBIT #
729 - nc_x = nc_group.createVariable('xhci', 'f8', (dimension,)) 729 + nc_x = nc_group.createVariable('xhee', 'f8', (dimension,))
730 nc_x.units = 'Au' 730 nc_x.units = 'Au'
731 - nc_y = nc_group.createVariable('yhci', 'f8', (dimension,)) 731 + nc_y = nc_group.createVariable('yhee', 'f8', (dimension,))
732 nc_y.units = 'Au' 732 nc_y.units = 'Au'
733 values_x = [] 733 values_x = []
734 values_y = [] 734 values_y = []
735 - index_x = available_params.index('xhci')  
736 - index_y = available_params.index('yhci') 735 + index_x = available_params.index('xhee')
  736 + index_y = available_params.index('yhee')
737 for dkey in dkeys: 737 for dkey in dkeys:
738 dval = data[dkey] 738 dval = data[dkey]
739 values_x.append(dval[index_x]) 739 values_x.append(dval[index_x])
web/static/js/swapp.js
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 SpaceWeather.prototype.init = function(){ 42 SpaceWeather.prototype.init = function(){
43 "This is called by the inline bootstrap javascript code.\nThis ain't in the constructor because it might return a Promise later on.\n(for the loader, for example)"; 43 "This is called by the inline bootstrap javascript code.\nThis ain't in the constructor because it might return a Promise later on.\n(for the loader, for example)";
44 var started_at, stopped_at, this$ = this; 44 var started_at, stopped_at, this$ = this;
45 - started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0); 45 + started_at = moment().subtract(6, 'month').hours(0).minutes(0).seconds(0);
46 stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0); 46 stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0);
47 this.setStartAndStop(started_at, stopped_at); 47 this.setStartAndStop(started_at, stopped_at);
48 this.loadAndCreatePlots(started_at, stopped_at); 48 this.loadAndCreatePlots(started_at, stopped_at);
@@ -126,7 +126,7 @@ @@ -126,7 +126,7 @@
126 console.debug("Requested CSV for " + target_slug + "...", csv); 126 console.debug("Requested CSV for " + target_slug + "...", csv);
127 timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z'); 127 timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');
128 data = { 128 data = {
129 - 'hci': [] 129 + 'hee': []
130 }; 130 };
131 configuration['parameters'].forEach(function(parameter){ 131 configuration['parameters'].forEach(function(parameter){
132 return data[parameter['id']] = []; 132 return data[parameter['id']] = [];
@@ -148,11 +148,11 @@ @@ -148,11 +148,11 @@
148 y: parseFloat(d[id]) 148 y: parseFloat(d[id])
149 }); 149 });
150 }); 150 });
151 - if (d['xhci'] && d['yhci']) {  
152 - return data['hci'].push({ 151 + if (d['xhee'] && d['yhee']) {
  152 + return data['hee'].push({
153 t: dtime, 153 t: dtime,
154 - x: parseFloat(d['xhci']),  
155 - y: parseFloat(d['yhci']) 154 + x: parseFloat(d['xhee']),
  155 + y: parseFloat(d['yhee'])
156 }); 156 });
157 } 157 }
158 }); 158 });
@@ -180,12 +180,11 @@ @@ -180,12 +180,11 @@
180 console.info("Loading CSV data of " + target.name + "…"); 180 console.info("Loading CSV data of " + target.name + "…");
181 targetButton = $(".targets-filters .target." + target.slug); 181 targetButton = $(".targets-filters .target." + target.slug);
182 targetButton.addClass('loading'); 182 targetButton.addClass('loading');
183 - targetButton.removeClass('failed');  
184 - targetButton.removeClass('empty'); 183 + targetButton.removeClass('failed empty');
185 return this$.loadData(target.slug, started_at, stopped_at).then(function(data){ 184 return this$.loadData(target.slug, started_at, stopped_at).then(function(data){
186 console.info("Loaded CSV data of " + target.name + ".", data); 185 console.info("Loaded CSV data of " + target.name + ".", data);
187 this$.createTimeSeries(target, data); 186 this$.createTimeSeries(target, data);
188 - this$.orbits.initOrbiter(target.slug, target.config, data['hci']); 187 + this$.orbits.initOrbiter(target.slug, target.config, data['hee']);
189 targetButton.removeClass('loading'); 188 targetButton.removeClass('loading');
190 if (target.active) { 189 if (target.active) {
191 return this$.hideLoader(); 190 return this$.hideLoader();
@@ -392,7 +391,7 @@ @@ -392,7 +391,7 @@
392 }); 391 });
393 }; 392 };
394 TimeSeries.prototype.init = function(){ 393 TimeSeries.prototype.init = function(){
395 - var clipId, dx, this$ = this; 394 + var formatMillisecond, formatSecond, formatMinute, formatHour, formatDay, formatWeek, formatMonth, formatYear, multiFormat, clipId, dx, this$ = this;
396 console.info("Initializing plot of " + this + "…"); 395 console.info("Initializing plot of " + this + "…");
397 this.margin = { 396 this.margin = {
398 top: 30, 397 top: 30,
@@ -402,7 +401,40 @@ @@ -402,7 +401,40 @@
402 }; 401 };
403 this.xScale = d3.scaleTime().domain(this.xDataExtent); 402 this.xScale = d3.scaleTime().domain(this.xDataExtent);
404 this.yScale = d3.scaleLinear().domain(this.yDataExtent); 403 this.yScale = d3.scaleLinear().domain(this.yDataExtent);
405 - this.xAxis = d3.axisBottom().ticks(7); 404 + formatMillisecond = d3.timeFormat(".%L");
  405 + formatSecond = d3.timeFormat(":%S");
  406 + formatMinute = d3.timeFormat("%I:%M");
  407 + formatHour = d3.timeFormat("%I:%M");
  408 + formatDay = d3.timeFormat("%a %d");
  409 + formatWeek = d3.timeFormat("%b %d");
  410 + formatMonth = d3.timeFormat("%B");
  411 + formatYear = d3.timeFormat("%Y");
  412 + multiFormat = function(date){
  413 + if (date > d3.timeSecond(date)) {
  414 + return formatMillisecond(date);
  415 + }
  416 + if (date > d3.timeMinute(date)) {
  417 + return formatSecond(date);
  418 + }
  419 + if (date > d3.timeHour(date)) {
  420 + return formatMinute(date);
  421 + }
  422 + if (date > d3.timeDay(date)) {
  423 + return formatHour(date);
  424 + }
  425 + if (date > d3.timeMonth(date)) {
  426 + if (date > d3.timeWeek(date)) {
  427 + return formatDay(date);
  428 + } else {
  429 + return formatWeek(date);
  430 + }
  431 + }
  432 + if (date > d3.timeYear(date)) {
  433 + return formatMonth(date);
  434 + }
  435 + return formatYear(date);
  436 + };
  437 + this.xAxis = d3.axisBottom().tickFormat(multiFormat).ticks(7);
406 this.yAxis = d3.axisLeft().ticks(10); 438 this.yAxis = d3.axisLeft().ticks(10);
407 this.line = d3.line().x(function(d){ 439 this.line = d3.line().x(function(d){
408 return this$.xScale(d.x); 440 return this$.xScale(d.x);
@@ -563,7 +595,7 @@ @@ -563,7 +595,7 @@
563 TimeSeries.prototype.bisectDate = d3.bisector(function(d){ 595 TimeSeries.prototype.bisectDate = d3.bisector(function(d){
564 return d.x; 596 return d.x;
565 }).left; 597 }).left;
566 - TimeSeries.prototype.timeFormat = d3.timeFormat("%Y-%m-%d %Hh"); 598 + TimeSeries.prototype.timeFormat = d3.timeFormat("%Y-%m-%d %H:%M");
567 TimeSeries.prototype.moveCursor = function(x0){ 599 TimeSeries.prototype.moveCursor = function(x0){
568 var i, d0, d1, d, xx, yy, mirrored, dx, transform; 600 var i, d0, d1, d, xx, yy, mirrored, dx, transform;
569 i = this.bisectDate(this.data, x0, 1); 601 i = this.bisectDate(this.data, x0, 1);
@@ -634,7 +666,7 @@ @@ -634,7 +666,7 @@
634 this.yAxisTitle.append('tspan').attr('dy', '-3px').text(' (AU)'); 666 this.yAxisTitle.append('tspan').attr('dy', '-3px').text(' (AU)');
635 this.yAxisTitle.attr('transform', 'rotate(-90)'); 667 this.yAxisTitle.attr('transform', 'rotate(-90)');
636 this.sun = this.plotWrapper.append("svg:image").attr('xlink:href', this.options.sun.img).attr('width', '32px').attr('height', '32px'); 668 this.sun = this.plotWrapper.append("svg:image").attr('xlink:href', this.options.sun.img).attr('width', '32px').attr('height', '32px');
637 - this.sun.append('svg:title').text("Sol"); 669 + this.sun.append('svg:title').text("Sun");
638 $(this.svg.node()).hide(); 670 $(this.svg.node()).hide();
639 return this.resize(); 671 return this.resize();
640 }; 672 };
@@ -651,6 +683,7 @@ @@ -651,6 +683,7 @@
651 this.yScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]); 683 this.yScale = d3.scaleLinear().domain([-1 * this.extremum, this.extremum]);
652 orbit_ellipse = this.plotWrapper.append("svg:ellipse").classed('orbit orbit_ellipse', true); 684 orbit_ellipse = this.plotWrapper.append("svg:ellipse").classed('orbit orbit_ellipse', true);
653 orbiter = this.plotWrapper.append("svg:image").attr('xlink:href', config['img']).attr('width', '32px').attr('height', '32px'); 685 orbiter = this.plotWrapper.append("svg:image").attr('xlink:href', config['img']).attr('width', '32px').attr('height', '32px');
  686 + orbiter.append('svg:title').text(config.name);
654 orbit_line = d3.line().x(function(d){ 687 orbit_line = d3.line().x(function(d){
655 return this$.xScale(d.x); 688 return this$.xScale(d.x);
656 }).y(function(d){ 689 }).y(function(d){
web/static/js/swapp.ls
@@ -74,7 +74,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE @@ -74,7 +74,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
74 """ 74 """
75 # Default time interval is from two weeks ago to one week ahead. 75 # Default time interval is from two weeks ago to one week ahead.
76 # We set the h/m/s to zero to benefit from a daily cache. 76 # We set the h/m/s to zero to benefit from a daily cache.
77 - started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0) 77 + started_at = moment().subtract(6, 'month').hours(0).minutes(0).seconds(0)
78 stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0) 78 stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0)
79 @setStartAndStop(started_at, stopped_at) 79 @setStartAndStop(started_at, stopped_at)
80 @loadAndCreatePlots(started_at, stopped_at) 80 @loadAndCreatePlots(started_at, stopped_at)
@@ -138,7 +138,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE @@ -138,7 +138,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
138 d3.csv(url, (csv) -> 138 d3.csv(url, (csv) ->
139 console.debug("Requested CSV for #{target_slug}...", csv) 139 console.debug("Requested CSV for #{target_slug}...", csv)
140 timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z') 140 timeFormat = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z')
141 - data = { 'hci': [] } 141 + data = { 'hee': [] }
142 configuration['parameters'].forEach((parameter) -> 142 configuration['parameters'].forEach((parameter) ->
143 data[parameter['id']] = [] 143 data[parameter['id']] = []
144 ) 144 )
@@ -150,9 +150,9 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE @@ -150,9 +150,9 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
150 id = parameter['id'] 150 id = parameter['id']
151 data[id].push({x: dtime, y: parseFloat(d[id])}) 151 data[id].push({x: dtime, y: parseFloat(d[id])})
152 ) 152 )
153 - if d['xhci'] and d['yhci']  
154 - data['hci'].push({  
155 - t: dtime, x: parseFloat(d['xhci']), y: parseFloat(d['yhci']) 153 + if d['xhee'] and d['yhee']
  154 + data['hee'].push({
  155 + t: dtime, x: parseFloat(d['xhee']), y: parseFloat(d['yhee'])
156 }) 156 })
157 ) 157 )
158 resolve data 158 resolve data
@@ -175,13 +175,12 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE @@ -175,13 +175,12 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
175 console.info "Loading CSV data of #{target.name}…" 175 console.info "Loading CSV data of #{target.name}…"
176 targetButton = $(".targets-filters .target.#{target.slug}") 176 targetButton = $(".targets-filters .target.#{target.slug}")
177 targetButton.addClass('loading') 177 targetButton.addClass('loading')
178 - targetButton.removeClass('failed')  
179 - targetButton.removeClass('empty') # fixme 178 + targetButton.removeClass('failed empty')
180 @loadData(target.slug, started_at, stopped_at).then( 179 @loadData(target.slug, started_at, stopped_at).then(
181 (data) ~> 180 (data) ~>
182 console.info "Loaded CSV data of #{target.name}.", data 181 console.info "Loaded CSV data of #{target.name}.", data
183 @createTimeSeries(target, data) 182 @createTimeSeries(target, data)
184 - @orbits.initOrbiter(target.slug, target.config, data['hci']) 183 + @orbits.initOrbiter(target.slug, target.config, data['hee'])
185 targetButton.removeClass('loading') 184 targetButton.removeClass('loading')
186 if target.active then @hideLoader() else @disableTarget(target.slug) 185 if target.active then @hideLoader() else @disableTarget(target.slug)
187 , 186 ,
@@ -341,8 +340,28 @@ export class TimeSeries @@ -341,8 +340,28 @@ export class TimeSeries
341 @xScale = d3.scaleTime().domain(@xDataExtent) 340 @xScale = d3.scaleTime().domain(@xDataExtent)
342 @yScale = d3.scaleLinear().domain(@yDataExtent) 341 @yScale = d3.scaleLinear().domain(@yDataExtent)
343 342
  343 + formatMillisecond = d3.timeFormat(".%L")
  344 + formatSecond = d3.timeFormat(":%S")
  345 + formatMinute = d3.timeFormat("%I:%M")
  346 + formatHour = d3.timeFormat("%I:%M")
  347 + formatDay = d3.timeFormat("%a %d")
  348 + formatWeek = d3.timeFormat("%b %d")
  349 + formatMonth = d3.timeFormat("%B")
  350 + formatYear = d3.timeFormat("%Y")
  351 +
  352 + multiFormat = (date) ->
  353 + if date > d3.timeSecond(date) then return formatMillisecond(date)
  354 + if date > d3.timeMinute(date) then return formatSecond(date)
  355 + if date > d3.timeHour(date) then return formatMinute(date)
  356 + if date > d3.timeDay(date) then return formatHour(date)
  357 + if date > d3.timeMonth(date)
  358 + if date > d3.timeWeek(date) then return formatDay(date)
  359 + else return formatWeek(date)
  360 + if date > d3.timeYear(date) then return formatMonth(date)
  361 + return formatYear(date)
  362 +
344 @xAxis = d3.axisBottom() 363 @xAxis = d3.axisBottom()
345 -# .tickFormat(d3.timeFormat("%Y-%m-%d")) 364 + .tickFormat(multiFormat)
346 .ticks(7) 365 .ticks(7)
347 @yAxis = d3.axisLeft() 366 @yAxis = d3.axisLeft()
348 .ticks(10) 367 .ticks(10)
@@ -554,7 +573,7 @@ export class TimeSeries @@ -554,7 +573,7 @@ export class TimeSeries
554 @focus.style("display", "none") 573 @focus.style("display", "none")
555 574
556 bisectDate: d3.bisector((d) -> d.x).left # /!\ complex 575 bisectDate: d3.bisector((d) -> d.x).left # /!\ complex
557 - timeFormat: d3.timeFormat("%Y-%m-%d %Hh") 576 + timeFormat: d3.timeFormat("%Y-%m-%d %H:%M")
558 577
559 moveCursor: (x0) -> 578 moveCursor: (x0) ->
560 i = @bisectDate(@data, x0, 1) 579 i = @bisectDate(@data, x0, 1)
@@ -610,7 +629,7 @@ export class Orbits @@ -610,7 +629,7 @@ export class Orbits
610 left: 60 629 left: 60
611 } 630 }
612 631
613 - @data = {} # slug => HCI array 632 + @data = {} # slug => HEE array
614 @orbiters = {} # slug => config 633 @orbiters = {} # slug => config
615 @orbitersElements = {} 634 @orbitersElements = {}
616 @extremum = 1 635 @extremum = 1
@@ -647,7 +666,7 @@ export class Orbits @@ -647,7 +666,7 @@ export class Orbits
647 @sun = @plotWrapper.append("svg:image") 666 @sun = @plotWrapper.append("svg:image")
648 .attr('xlink:href', @options.sun.img) 667 .attr('xlink:href', @options.sun.img)
649 .attr('width', '32px').attr('height', '32px') 668 .attr('width', '32px').attr('height', '32px')
650 - @sun.append('svg:title').text("Sol") 669 + @sun.append('svg:title').text("Sun")
651 670
652 $(@svg.node()).hide(); # we'll show it later when there'll be data 671 $(@svg.node()).hide(); # we'll show it later when there'll be data
653 @resize() 672 @resize()
@@ -668,6 +687,7 @@ export class Orbits @@ -668,6 +687,7 @@ export class Orbits
668 orbiter = @plotWrapper.append("svg:image") 687 orbiter = @plotWrapper.append("svg:image")
669 .attr('xlink:href', config['img']) 688 .attr('xlink:href', config['img'])
670 .attr('width', '32px').attr('height', '32px') 689 .attr('width', '32px').attr('height', '32px')
  690 + orbiter.append('svg:title').text(config.name)
671 691
672 orbit_line = d3.line() 692 orbit_line = d3.line()
673 .x((d) ~> @xScale(d.x)) 693 .x((d) ~> @xScale(d.x))
web/view/home.html.jinja2
@@ -325,19 +325,19 @@ @@ -325,19 +325,19 @@
325 cursor: not-allowed; 325 cursor: not-allowed;
326 } 326 }
327 .targets-filters .target.loading { 327 .targets-filters .target.loading {
328 - -webkit-animation-name: spin; 328 + -webkit-animation-name: keyframes_rotate;
329 -webkit-animation-duration: 4000ms; 329 -webkit-animation-duration: 4000ms;
330 -webkit-animation-iteration-count: infinite; 330 -webkit-animation-iteration-count: infinite;
331 -webkit-animation-timing-function: linear; 331 -webkit-animation-timing-function: linear;
332 - -moz-animation-name: spin; 332 + -moz-animation-name: keyframes_rotate;
333 -moz-animation-duration: 4000ms; 333 -moz-animation-duration: 4000ms;
334 -moz-animation-iteration-count: infinite; 334 -moz-animation-iteration-count: infinite;
335 -moz-animation-timing-function: linear; 335 -moz-animation-timing-function: linear;
336 - -ms-animation-name: spin; 336 + -ms-animation-name: keyframes_rotate;
337 -ms-animation-duration: 4000ms; 337 -ms-animation-duration: 4000ms;
338 -ms-animation-iteration-count: infinite; 338 -ms-animation-iteration-count: infinite;
339 -ms-animation-timing-function: linear; 339 -ms-animation-timing-function: linear;
340 - animation-name: spin; 340 + animation-name: keyframes_rotate;
341 animation-duration: 4000ms; 341 animation-duration: 4000ms;
342 animation-iteration-count: infinite; 342 animation-iteration-count: infinite;
343 animation-timing-function: linear; 343 animation-timing-function: linear;
web/view/layout.html.jinja2
@@ -42,7 +42,7 @@ @@ -42,7 +42,7 @@
42 <!-- Navigation. We hide it in small screens. --> 42 <!-- Navigation. We hide it in small screens. -->
43 <nav class="mdl-navigation mdl-layout--large-screen-only"> 43 <nav class="mdl-navigation mdl-layout--large-screen-only">
44 <a class="mdl-navigation__link" href="https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE">v{{ version }}</a> 44 <a class="mdl-navigation__link" href="https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE">v{{ version }}</a>
45 - <a class="mdl-navigation__link" href="#">Model</a> 45 + <a class="mdl-navigation__link" href="https://onlinelibrary.wiley.com/doi/10.1029/2004JA010959/abstract">Model</a>
46 <a class="mdl-navigation__link" href="https://ec.europa.eu/programmes/horizon2020/">Horizon 2020</a> 46 <a class="mdl-navigation__link" href="https://ec.europa.eu/programmes/horizon2020/">Horizon 2020</a>
47 </nav> 47 </nav>
48 </div> 48 </div>