Commit 9c0c450920ae3ef86ff609af6ddf86a8266d449f

Authored by Goutte
1 parent 93ee5563

Add a loader to the whole page.

CHANGELOG.md
1   -## TODO
  1 +## Misc
2 2  
3   -- Support multiple models for each target
4   -- Play button to start time dimension
  3 +- [ ] Support multiple models for each target
  4 +- [ ] Play button to start time dimension (not very useful?)
5 5  
6 6 ## 1.0.0
7 7  
8 8 - [x] Cache generated CSVs on the server side
9 9 - [x] Cache generated CSVs on the client side
10   -- [x] Visits counter
  10 +- [x] Count visits
11 11 - [x] Zoom in on time series
  12 +- [x] Loader and targets loading animation
12 13 - [ ] Start/Stop datetime fields
13   -- [ ] Loader
14 14 - [ ] Download raw data (as CSV) for current time interval and targets
15 15 - [ ] Same via SAMP
16 16 - [ ] Credit the author of the pixel art planets
... ...
web/static/js/swapp.js
... ... @@ -60,7 +60,8 @@
60 60 console.info("Loaded CSV data of " + target.name + ".");
61 61 this$.createTimeSeries(target, data);
62 62 this$.orbits.initOrbiter(target.slug, target.config, data['hci']);
63   - return targetButton.removeClass('loading');
  63 + targetButton.removeClass('loading');
  64 + return this$.hideLoader();
64 65 }, function(error){
65 66 return console.error('Failed to load CSV data.', error);
66 67 });
... ... @@ -117,6 +118,9 @@
117 118 return ts.resize();
118 119 });
119 120 };
  121 + SpaceWeather.prototype.hideLoader = function(){
  122 + return $("#plots_loader").hide();
  123 + };
120 124 SpaceWeather.prototype.loadData = function(target_slug, started_at, stopped_at){
121 125 "Load the data as CSV for the specified target and interval,\nand return it in a Promise.";
122 126 var sw, promise;
... ... @@ -172,27 +176,38 @@
172 176 });
173 177 return timeSeries.forEach(function(ts){
174 178 ts.options['onMouseOver'] = function(){
175   - return timeSeries.forEach(function(ts2){
  179 + timeSeries.forEach(function(ts2){
176 180 return ts2.showCursor();
177 181 });
  182 + return true;
178 183 };
179 184 ts.options['onMouseOut'] = function(){
180   - return timeSeries.forEach(function(ts2){
  185 + timeSeries.forEach(function(ts2){
181 186 return ts2.hideCursor();
182 187 });
  188 + return true;
183 189 };
184 190 ts.options['onMouseMove'] = function(t){
185 191 var ref$;
186 192 timeSeries.forEach(function(ts2){
187 193 return ts2.moveCursor(t);
188 194 });
189   - return (ref$ = this$.orbits) != null ? ref$.moveToDate(t) : void 8;
  195 + if ((ref$ = this$.orbits) != null) {
  196 + ref$.moveToDate(t);
  197 + }
  198 + return true;
190 199 };
191 200 ts.options['onBrushEnd'] = function(sta, sto){
192   - return this$.resizeDomain(sta, sto);
  201 + this$.resizeDomain(sta, sto);
  202 + return true;
193 203 };
194 204 return ts.options['onDblClick'] = function(){
195   - return this$.resetZoom();
  205 + var ref$;
  206 + this$.resetZoom();
  207 + if ((ref$ = $("#zoom_controls_help")) != null) {
  208 + ref$.remove();
  209 + }
  210 + return true;
196 211 };
197 212 });
198 213 };
... ...
web/static/js/swapp.ls
... ... @@ -11,6 +11,10 @@
11 11 # templates, such as `home.html.jinja2`.
12 12  
13 13 # Note: We use Promises and ES6 whenever relevant.
  14 +# You also will need d3js v4 documentation : https://d3js.org/
  15 +# We're using a custom build of 4.9.1, one line changed, see d3-custom.js
  16 +# Event bubbling cannot trigger two rects unless we make an event dispatcher,
  17 +# and d3's brush is stopping propagation, as it should by default.
14 18  
15 19 ###############################################################################
16 20  
... ... @@ -81,6 +85,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
81 85 @createTimeSeries(target, data)
82 86 @orbits.initOrbiter(target.slug, target.config, data['hci'])
83 87 targetButton.removeClass('loading')
  88 + @hideLoader()
84 89 ,
85 90 (error) -> console.error('Failed to load CSV data.', error)
86 91 )
... ... @@ -117,6 +122,9 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
117 122 @orbits?.resize();
118 123 timeSeries.forEach((ts) -> ts.resize())
119 124  
  125 + hideLoader: ->
  126 + $("\#plots_loader").hide();
  127 +
120 128 loadData: (target_slug, started_at, stopped_at) ->
121 129 """
122 130 Load the data as CSV for the specified target and interval,
... ... @@ -145,7 +153,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
145 153 )
146 154 promise
147 155  
148   - timeSeries = [] # Not sure why this ain't an instance prop. Probably should.
  156 + timeSeries = [] # deprecated (was for scoping) ; use @property with ~>
149 157 createTimeSeries: (target, data) ->
150 158 @configuration['parameters'].forEach((parameter) ~>
151 159 container = @configuration['time_series_container']
... ... @@ -155,18 +163,18 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE
155 163 id, title, target, data[id], @parameters[id].active, container
156 164 ))
157 165 )
158   - timeSeries.forEach((ts) ~>
  166 + timeSeries.forEach((ts) ~> # returning true may be faster
159 167 ts.options['onMouseOver'] = ->
160   - timeSeries.forEach((ts2) -> ts2.showCursor())
  168 + timeSeries.forEach((ts2) -> ts2.showCursor()) ; true
161 169 ts.options['onMouseOut'] = ->
162   - timeSeries.forEach((ts2) -> ts2.hideCursor())
  170 + timeSeries.forEach((ts2) -> ts2.hideCursor()) ; true
163 171 ts.options['onMouseMove'] = (t) ~>
164 172 timeSeries.forEach((ts2) -> ts2.moveCursor(t))
165   - @orbits?.moveToDate(t)
  173 + @orbits?.moveToDate(t) ; true
166 174 ts.options['onBrushEnd'] = (sta, sto) ~>
167   - @resizeDomain(sta, sto)
  175 + @resizeDomain(sta, sto) ; true
168 176 ts.options['onDblClick'] = ~>
169   - @resetZoom()
  177 + @resetZoom() ; $("\#zoom_controls_help")?.remove() ; true
170 178 )
171 179  
172 180 enableParameter: (parameter_slug) ->
... ...
web/view/home.html.jinja2
... ... @@ -14,6 +14,16 @@
14 14 >
15 15 {%- endmacro %}
16 16  
  17 +
  18 +<div id="plots_loader">
  19 + <p class="loader-text">Loading Heliopropa&hellip;<br>This might take a while.</p>
  20 + <div id="plots_loader_img1" class="img"></div>
  21 + <div id="plots_loader_img2" class="img"></div>
  22 + <div id="plots_loader_img3" class="img"></div>
  23 + <div id="plots_loader_img4" class="img"></div>
  24 + <div id="plots_loader_img5" class="img"></div>
  25 +</div>
  26 +
17 27 <div class="mdl-layout mdl-js-layout mdl-layout--fixed-drawer">
18 28  
19 29 <div class="mdl-layout__drawer">
... ... @@ -72,7 +82,9 @@
72 82 <section id="orbits"></section>
73 83 </div>
74 84 <div class="mdl-cell mdl-cell--8-col">
75   - <section id="time_series"></section>
  85 + <section id="time_series">
  86 + <p id="zoom_controls_help" class="help mdl-cell--8-col">Drag to zoom in, double click to zoom out.</p>
  87 + </section>
76 88 </div>
77 89 </div>
78 90  
... ... @@ -89,6 +101,103 @@
89 101 {# background-color: #322e3f;#}
90 102 {# color: #e3e3e3;#}
91 103 }
  104 + #plots_wrapper {
  105 +{# position: relative;#}
  106 + }
  107 + #plots_loader {
  108 + position: absolute;
  109 + top: 0; left: 0; bottom: 0; right: 0;
  110 + height: 100%;
  111 + width: 100%;
  112 + background-color: #fff;
  113 + z-index: 1000;
  114 + }
  115 +
  116 + #plots_loader .loader-text {
  117 + width: 200px;
  118 + height: 30px;
  119 + position: absolute;
  120 + top: -240px; left: -32px; bottom: 0; right: 0;
  121 + margin: auto;
  122 + text-align: center;
  123 + font-size: 1.0em;
  124 + font-style: italic;
  125 + color: darkgrey;
  126 + }
  127 +
  128 + #plots_loader .img {
  129 + width: 100px;
  130 + height: 100px;
  131 + border-radius: 100%;
  132 + position: absolute;
  133 + border: 1px solid #6978ff;
  134 + animation: up 1s;
  135 + animation-iteration-count: infinite;
  136 + transition: 2s;
  137 + border-bottom: none;
  138 + border-right: none;
  139 + animation-timing-function: linear;
  140 + margin-left: -70px;
  141 + margin-top: -70px;
  142 + left: 50%;
  143 + top: 50%;
  144 + }
  145 +
  146 + @keyframes up {
  147 + from {
  148 + transform: rotate(0deg);
  149 + }
  150 + 50% {
  151 + transform: rotate(180deg);
  152 + }
  153 + 100% {
  154 + transform: rotate(360deg);
  155 + }
  156 + }
  157 +
  158 + #plots_loader #plots_loader_img2 {
  159 + width: 90px;
  160 + height: 90px;
  161 + left: 50.35%;
  162 + top: 50.7%;
  163 + animation-delay: .2s;
  164 + }
  165 +
  166 + #plots_loader #plots_loader_img3 {
  167 + width: 80px;
  168 + height: 80px;
  169 + left: 50.70%;
  170 + top: 51.4%;
  171 + animation-delay: .4s;
  172 + }
  173 +
  174 + #plots_loader #plots_loader_img4 {
  175 + width: 70px;
  176 + height: 70px;
  177 + left: 51.05%;
  178 + top: 52.1%;
  179 + animation-delay: .6s;
  180 + }
  181 +
  182 + #plots_loader #plots_loader_img5 {
  183 + width: 60px;
  184 + height: 60px;
  185 + left: 51.40%;
  186 + top: 52.8%;
  187 + animation-delay: .8s;
  188 + }
  189 +
  190 + #time_series .help {
  191 + position: absolute;
  192 + text-align: center;
  193 + font-size: 0.9em;
  194 + font-style: italic;
  195 + color: darkgrey;
  196 + display: none;
  197 + }
  198 + #time_series:hover .help {
  199 + display: block;
  200 + }
92 201 .axis path, .axis line {
93 202 fill: none;
94 203 {# stroke: #f4f4f4;#}
... ... @@ -288,7 +397,7 @@ jQuery().ready(function($){
288 397 var isLastTargetEnabled = function(target_slug) {
289 398 var s = 0;
290 399 $(".orbiters_filters .target:not(.locked)").each(function(i,p) {
291   - if ($(p).hasClass('active')) s++;
  400 + if ($(p).hasClass('active') && ! $(p).hasClass('loading')) s++;
292 401 });
293 402 return s < 2;
294 403 };
... ... @@ -304,7 +413,8 @@ jQuery().ready(function($){
304 413 }
305 414 return false;
306 415 });
307   - $(".orbiters_filters .target:not(.locked)").click(function(e){
  416 + $(".orbiters_filters .target:not(.locked)").on("click", function(e){
  417 + if ($(this).hasClass('loading')) return false;
308 418 var switch_on = ! $(this).hasClass('active');
309 419 var target_slug = $(this).attr('data-target-slug');
310 420 if (switch_on) {
... ...