Commit 6b149919736edf25616423447cfa6eef2a02d793
1 parent
077980eb
Exists in
master
and in
2 other branches
Add a Download button.
Showing
5 changed files
with
65 additions
and
13 deletions
Show diff stats
CHANGELOG.md
... | ... | @@ -4,6 +4,7 @@ |
4 | 4 | - [ ] Optimize CSV generation (with some vectorization using numpy) |
5 | 5 | - [ ] Credit the author of the pixel art planets |
6 | 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 | 10 | ## 1.0.0 |
... | ... | @@ -21,8 +22,9 @@ |
21 | 22 | - [ ] Cache cleanup |
22 | 23 | - [x] API at /cache/clear |
23 | 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 | 26 | - [ ] Same via SAMP |
27 | +- [ ] Add a warning for users with javascript disabled | |
26 | 28 | |
27 | 29 | |
28 | 30 | ## 0.0.0 | ... | ... |
README.md
... | ... | @@ -6,19 +6,15 @@ The sources of the website available at https://spaceweatheronline.cdpp.eu |
6 | 6 | |
7 | 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 | 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 | 20 | # How |
... | ... | @@ -27,6 +23,7 @@ Gather NetCDF data from AMDA, and serve it as CSV to the javascript plotter. |
27 | 23 | |
28 | 24 | - `config.yml` : the main configuration file. |
29 | 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 | 29 | ## Install | ... | ... |
web/static/js/swapp.js
... | ... | @@ -58,6 +58,24 @@ |
58 | 58 | url = url.replace('<stopped_at>', stopped_at); |
59 | 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 | 79 | SpaceWeather.prototype.addTarget = function(target){ |
62 | 80 | this.targets[target.slug] = target; |
63 | 81 | return this; | ... | ... |
web/static/js/swapp.ls
... | ... | @@ -88,6 +88,15 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE |
88 | 88 | url = url.replace('<stopped_at>', stopped_at) |
89 | 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 | 100 | addTarget: (target) -> |
92 | 101 | @targets[target.slug] = target |
93 | 102 | this | ... | ... |
web/view/home.html.jinja2
... | ... | @@ -88,6 +88,10 @@ |
88 | 88 | <div class="mdl-grid"> |
89 | 89 | <div class="mdl-cell mdl-cell--4-col"> |
90 | 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 | 95 | </div> |
92 | 96 | <div class="mdl-cell mdl-cell--8-col"> |
93 | 97 | <section id="time_series"> |
... | ... | @@ -117,7 +121,7 @@ |
117 | 121 | {# position: relative;#} |
118 | 122 | } |
119 | 123 | #plots_loader { |
120 | - position: absolute; | |
124 | + position: fixed; | |
121 | 125 | top: 0; left: 0; bottom: 0; right: 0; |
122 | 126 | height: 100%; |
123 | 127 | width: 100%; |
... | ... | @@ -199,6 +203,11 @@ |
199 | 203 | animation-delay: .8s; |
200 | 204 | } |
201 | 205 | |
206 | + #download { | |
207 | + display: block; | |
208 | + margin: 3em auto; | |
209 | + } | |
210 | + | |
202 | 211 | #time_series .help { |
203 | 212 | position: absolute; |
204 | 213 | text-align: center; |
... | ... | @@ -329,7 +338,8 @@ var configuration = { |
329 | 338 | time_series_container: '#time_series', |
330 | 339 | orbits_container: '#orbits', |
331 | 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 | 344 | sun: { |
335 | 345 | img: '{{ static('img/sun_128.png') }}' |
... | ... | @@ -440,7 +450,23 @@ jQuery().ready(function($){ |
440 | 450 | var stopped_at = moment($("#stopped_at").val()); |
441 | 451 | sw.resizeDomain(started_at, stopped_at); |
442 | 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 | 472 | </script> | ... | ... |