Commit 6b149919736edf25616423447cfa6eef2a02d793

Authored by Goutte
1 parent 077980eb

Add a Download button.

@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 - [ ] Optimize CSV generation (with some vectorization using numpy) 4 - [ ] Optimize CSV generation (with some vectorization using numpy)
5 - [ ] Credit the author of the pixel art planets 5 - [ ] Credit the author of the pixel art planets
6 - [ ] Set the log level to _error_ in production (see `web/run.py`) 6 - [ ] Set the log level to _error_ in production (see `web/run.py`)
  7 +- [ ] Add a README to the download tarball
7 8
8 9
9 ## 1.0.0 10 ## 1.0.0
@@ -21,8 +22,9 @@ @@ -21,8 +22,9 @@
21 - [ ] Cache cleanup 22 - [ ] Cache cleanup
22 - [x] API at /cache/clear 23 - [x] API at /cache/clear
23 - [ ] CRON statement to call it 24 - [ ] CRON statement to call it
24 -- [ ] 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 - [ ] Same via SAMP 26 - [ ] Same via SAMP
  27 +- [ ] Add a warning for users with javascript disabled
26 28
27 29
28 ## 0.0.0 30 ## 0.0.0
@@ -6,19 +6,15 @@ The sources of the website available at https://spaceweatheronline.cdpp.eu @@ -6,19 +6,15 @@ The sources of the website available at https://spaceweatheronline.cdpp.eu
6 6
7 ## Web Server 7 ## Web Server
8 8
9 -Build and serve the space weather visualization webpages.  
10 -A flask webserver, serving d3.js visualizations.  
11 -  
12 -  
13 -## Bridge  
14 -  
15 -Gather NetCDF data from AMDA, and serve it as CSV to the javascript plotter. 9 +Build and serve heliopropa's visualizations.
  10 +It's a `flask` webserver, serving `d3.js` plots written in `livescript`.
  11 +It also gathers NetCDF data from AMDA, and serves it as CSV to the plotter.
16 12
17 13
18 ### Rationale 14 ### Rationale
19 15
20 -- Reading NetCDF from javascript is doable, but still very hacky.  
21 -- The bridge can handle pagination, collecting multiple NetCDF into one CSV. 16 +- Reading NetCDF from javascript is doable, but still *very* hacky.
  17 +- The bridge can handle pagination and collecting multiple NetCDF into one CSV.
22 18
23 19
24 # How 20 # How
@@ -27,6 +23,7 @@ Gather NetCDF data from AMDA, and serve it as CSV to the javascript plotter. @@ -27,6 +23,7 @@ Gather NetCDF data from AMDA, and serve it as CSV to the javascript plotter.
27 23
28 - `config.yml` : the main configuration file. 24 - `config.yml` : the main configuration file.
29 - `web/run.py` : the front controller, holding most of the code. 25 - `web/run.py` : the front controller, holding most of the code.
  26 +- `web/view/home.html.jinja2` : the HTML template.
30 27
31 28
32 ## Install 29 ## Install
web/static/js/swapp.js
@@ -58,6 +58,24 @@ @@ -58,6 +58,24 @@
58 url = url.replace('<stopped_at>', stopped_at); 58 url = url.replace('<stopped_at>', stopped_at);
59 return url; 59 return url;
60 }; 60 };
  61 + SpaceWeather.prototype.buildDownloadUrl = function(){
  62 + var ref$, started_at, stopped_at, targets, t, url;
  63 + ref$ = this.getDomain(), started_at = ref$[0], stopped_at = ref$[1];
  64 + targets = (function(){
  65 + var results$ = [];
  66 + for (t in this.targets) {
  67 + if (this.targets[t].active) {
  68 + results$.push(t);
  69 + }
  70 + }
  71 + return results$;
  72 + }.call(this)).sort().join('-');
  73 + url = this.configuration['api']['download'];
  74 + url = url.replace('<targets>', targets);
  75 + url = url.replace('<started_at>', started_at.format(API_TIME_FORMAT));
  76 + url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT));
  77 + return url;
  78 + };
61 SpaceWeather.prototype.addTarget = function(target){ 79 SpaceWeather.prototype.addTarget = function(target){
62 this.targets[target.slug] = target; 80 this.targets[target.slug] = target;
63 return this; 81 return this;
web/static/js/swapp.ls
@@ -88,6 +88,15 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE @@ -88,6 +88,15 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
88 url = url.replace('<stopped_at>', stopped_at) 88 url = url.replace('<stopped_at>', stopped_at)
89 url 89 url
90 90
  91 + buildDownloadUrl: ->
  92 + [started_at, stopped_at] = @getDomain()
  93 + targets = [t for t of @targets when @targets[t].active].sort().join('-')
  94 + url = @configuration['api']['download']
  95 + url = url.replace('<targets>', targets)
  96 + url = url.replace('<started_at>', started_at.format(API_TIME_FORMAT))
  97 + url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT))
  98 + url
  99 +
91 addTarget: (target) -> 100 addTarget: (target) ->
92 @targets[target.slug] = target 101 @targets[target.slug] = target
93 this 102 this
web/view/home.html.jinja2
@@ -88,6 +88,10 @@ @@ -88,6 +88,10 @@
88 <div class="mdl-grid"> 88 <div class="mdl-grid">
89 <div class="mdl-cell mdl-cell--4-col"> 89 <div class="mdl-cell mdl-cell--4-col">
90 <section id="orbits"></section> 90 <section id="orbits"></section>
  91 + <button id="download" class="mdl-button mdl-button--raised mdl-button--primary"
  92 + title="Download the CSV raw data for each target in a tarball.">
  93 + Download
  94 + </button>
91 </div> 95 </div>
92 <div class="mdl-cell mdl-cell--8-col"> 96 <div class="mdl-cell mdl-cell--8-col">
93 <section id="time_series"> 97 <section id="time_series">
@@ -117,7 +121,7 @@ @@ -117,7 +121,7 @@
117 {# position: relative;#} 121 {# position: relative;#}
118 } 122 }
119 #plots_loader { 123 #plots_loader {
120 - position: absolute; 124 + position: fixed;
121 top: 0; left: 0; bottom: 0; right: 0; 125 top: 0; left: 0; bottom: 0; right: 0;
122 height: 100%; 126 height: 100%;
123 width: 100%; 127 width: 100%;
@@ -199,6 +203,11 @@ @@ -199,6 +203,11 @@
199 animation-delay: .8s; 203 animation-delay: .8s;
200 } 204 }
201 205
  206 + #download {
  207 + display: block;
  208 + margin: 3em auto;
  209 + }
  210 +
202 #time_series .help { 211 #time_series .help {
203 position: absolute; 212 position: absolute;
204 text-align: center; 213 text-align: center;
@@ -329,7 +338,8 @@ var configuration = { @@ -329,7 +338,8 @@ var configuration = {
329 time_series_container: '#time_series', 338 time_series_container: '#time_series',
330 orbits_container: '#orbits', 339 orbits_container: '#orbits',
331 api : { 340 api : {
332 - 'data_for_interval': "{{ request.url_root }}<target>_<started_at>_<stopped_at>.csv" 341 + 'data_for_interval': "{{ request.url_root }}<target>_<started_at>_<stopped_at>.csv",
  342 + 'download': "{{ request.url_root }}<targets>_<started_at>_<stopped_at>.tar.gz"
333 }, 343 },
334 sun: { 344 sun: {
335 img: '{{ static('img/sun_128.png') }}' 345 img: '{{ static('img/sun_128.png') }}'
@@ -440,7 +450,23 @@ jQuery().ready(function($){ @@ -440,7 +450,23 @@ jQuery().ready(function($){
440 var stopped_at = moment($("#stopped_at").val()); 450 var stopped_at = moment($("#stopped_at").val());
441 sw.resizeDomain(started_at, stopped_at); 451 sw.resizeDomain(started_at, stopped_at);
442 return false; 452 return false;
443 - }) 453 + });
  454 + $('#download').on("click", function(e){
  455 + var url = sw.buildDownloadUrl();
  456 + $.ajax({
  457 + type: 'GET',
  458 + url: url,
  459 + processData: false,
  460 + success: function (data) {
  461 + window.location = url;
  462 + },
  463 + error: function (xhr) {
  464 + console.error('Cannot download.', xhr);
  465 + alert("Our apologies, there was an error while downloading.");
  466 + }
  467 + });
  468 + return false;
  469 + });
444 470
445 }); 471 });
446 </script> 472 </script>