Commit cad44b6d55940ae698ee8784942558100af12b88
1 parent
6491a1f1
Exists in
master
and in
2 other branches
Finish adding the SAMP button (finally!)
Showing
3 changed files
with
165 additions
and
17 deletions
Show diff stats
web/static/js/swapp.js
... | ... | @@ -30,7 +30,7 @@ |
30 | 30 | } |
31 | 31 | configs = res$; |
32 | 32 | configs.forEach(function(target_config){ |
33 | - return this$.targets[target_config.slug] = new Target(target_config.slug, target_config.name, target_config); | |
33 | + return this$.addTarget(new Target(target_config.slug, target_config.name, target_config)); | |
34 | 34 | }); |
35 | 35 | this.parameters = {}; |
36 | 36 | this.configuration['parameters'].forEach(function(p){ |
... | ... | @@ -42,7 +42,7 @@ |
42 | 42 | SpaceWeather.prototype.init = function(){ |
43 | 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 | 44 | var started_at, stopped_at, this$ = this; |
45 | - started_at = moment().subtract(6, 'month').hours(0).minutes(0).seconds(0); | |
45 | + started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0); | |
46 | 46 | stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0); |
47 | 47 | this.setStartAndStop(started_at, stopped_at); |
48 | 48 | this.loadAndCreatePlots(started_at, stopped_at); |
... | ... | @@ -76,10 +76,61 @@ |
76 | 76 | url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT)); |
77 | 77 | return url; |
78 | 78 | }; |
79 | + SpaceWeather.prototype.buildSampUrl = function(){ | |
80 | + var ref$, started_at, stopped_at, targets, t, parameters, p, url; | |
81 | + ref$ = this.getDomain(), started_at = ref$[0], stopped_at = ref$[1]; | |
82 | + targets = (function(){ | |
83 | + var results$ = []; | |
84 | + for (t in this.targets) { | |
85 | + if (this.targets[t].active) { | |
86 | + results$.push(t); | |
87 | + } | |
88 | + } | |
89 | + return results$; | |
90 | + }.call(this)).sort().join('-'); | |
91 | + parameters = (function(){ | |
92 | + var results$ = []; | |
93 | + for (p in this.parameters) { | |
94 | + if (this.parameters[p].active) { | |
95 | + results$.push(p); | |
96 | + } | |
97 | + } | |
98 | + return results$; | |
99 | + }.call(this)).sort().join('-'); | |
100 | + url = this.configuration['api']['samp']; | |
101 | + url = url.replace('<targets>', targets); | |
102 | + url = url.replace('<params>', parameters); | |
103 | + url = url.replace('<started_at>', started_at.format(API_TIME_FORMAT)); | |
104 | + url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT)); | |
105 | + return url; | |
106 | + }; | |
107 | + SpaceWeather.prototype.buildSampName = function(){ | |
108 | + var ref$, started_at, stopped_at, targets, t; | |
109 | + ref$ = this.getDomain(), started_at = ref$[0], stopped_at = ref$[1]; | |
110 | + targets = (function(){ | |
111 | + var i$, ref$, len$, results$ = []; | |
112 | + for (i$ = 0, len$ = (ref$ = this.getEnabledTargets()).length; i$ < len$; ++i$) { | |
113 | + t = ref$[i$]; | |
114 | + results$.push(t.name); | |
115 | + } | |
116 | + return results$; | |
117 | + }.call(this)).sort().join(', '); | |
118 | + return "Heliopropa for " + targets + " from " + started_at.format(API_TIME_FORMAT) + " to " + stopped_at.format(API_TIME_FORMAT) + "."; | |
119 | + }; | |
79 | 120 | SpaceWeather.prototype.addTarget = function(target){ |
80 | 121 | this.targets[target.slug] = target; |
81 | 122 | return this; |
82 | 123 | }; |
124 | + SpaceWeather.prototype.getEnabledTargets = function(){ | |
125 | + var slug, ref$, target, results$ = []; | |
126 | + for (slug in ref$ = this.targets) { | |
127 | + target = ref$[slug]; | |
128 | + if (target.active) { | |
129 | + results$.push(target); | |
130 | + } | |
131 | + } | |
132 | + return results$; | |
133 | + }; | |
83 | 134 | SpaceWeather.prototype.enableTarget = function(target_slug){ |
84 | 135 | var this$ = this; |
85 | 136 | this.time_series.forEach(function(ts){ |
... | ... | @@ -270,6 +321,17 @@ |
270 | 321 | }); |
271 | 322 | return this.time_series; |
272 | 323 | }; |
324 | + SpaceWeather.prototype.getEnabledParameters = function(){ | |
325 | + var i$, ref$, len$, p, slug, results$ = []; | |
326 | + for (i$ = 0, len$ = (ref$ = this.parameters).length; i$ < len$; ++i$) { | |
327 | + p = i$; | |
328 | + slug = ref$[i$]; | |
329 | + if (p.active) { | |
330 | + results$.push(p); | |
331 | + } | |
332 | + } | |
333 | + return results$; | |
334 | + }; | |
273 | 335 | SpaceWeather.prototype.enableParameter = function(parameter_slug){ |
274 | 336 | var this$ = this; |
275 | 337 | if (!(parameter_slug in this.parameters)) { | ... | ... |
web/static/js/swapp.ls
... | ... | @@ -11,7 +11,7 @@ |
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/ | |
14 | +# You also WILL NEED d3js v4 documentation : https://d3js.org/ | |
15 | 15 | # We're using a custom build of 4.9.1, one line changed, see d3-custom.js |
16 | 16 | # Event bubbling cannot trigger two rects unless we make an event dispatcher, |
17 | 17 | # and d3's brush is stopping propagation, as it should by default. |
... | ... | @@ -56,13 +56,13 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE |
56 | 56 | """ # HelioPropa by CDPP (mushed 'cause we need to escape backslashes) |
57 | 57 | @targets = {} |
58 | 58 | configs = [@configuration.targets[k] for k of @configuration.targets] |
59 | - configs.forEach((target_config) ~> | |
60 | - @targets[target_config.slug] = new Target(target_config.slug, target_config.name, target_config) | |
61 | - ) | |
59 | + configs.forEach (target_config) ~> | |
60 | + @addTarget(new Target(target_config.slug, target_config.name, target_config)) | |
61 | + | |
62 | 62 | @parameters = {} |
63 | - @configuration['parameters'].forEach((p) ~> | |
64 | - @parameters[p['id']] = p | |
65 | - ) | |
63 | + @configuration['parameters'].forEach (p) ~> | |
64 | + @parameters[p['id']] = p | |
65 | + | |
66 | 66 | @orbiter = null # our Orbiter defined below |
67 | 67 | @time_series = [] # a List of TimeSeries objects |
68 | 68 | |
... | ... | @@ -74,7 +74,7 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE |
74 | 74 | """ |
75 | 75 | # Default time interval is from two weeks ago to one week ahead. |
76 | 76 | # We set the h/m/s to zero to benefit from a daily cache. |
77 | - started_at = moment().subtract(6, 'month').hours(0).minutes(0).seconds(0) | |
77 | + started_at = moment().subtract(1, 'year').hours(0).minutes(0).seconds(0) | |
78 | 78 | stopped_at = moment().add(1, 'week').hours(0).minutes(0).seconds(0) |
79 | 79 | @setStartAndStop(started_at, stopped_at) |
80 | 80 | @loadAndCreatePlots(started_at, stopped_at) |
... | ... | @@ -97,6 +97,22 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE |
97 | 97 | url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT)) |
98 | 98 | url |
99 | 99 | |
100 | + buildSampUrl: -> | |
101 | + [started_at, stopped_at] = @getDomain() | |
102 | + targets = [t for t of @targets when @targets[t].active].sort().join('-') | |
103 | + parameters = [p for p of @parameters when @parameters[p].active].sort().join('-') | |
104 | + url = @configuration['api']['samp'] | |
105 | + url = url.replace('<targets>', targets) | |
106 | + url = url.replace('<params>', parameters) | |
107 | + url = url.replace('<started_at>', started_at.format(API_TIME_FORMAT)) | |
108 | + url = url.replace('<stopped_at>', stopped_at.format(API_TIME_FORMAT)) | |
109 | + url | |
110 | + | |
111 | + buildSampName: -> | |
112 | + [started_at, stopped_at] = @getDomain() | |
113 | + targets = [t.name for t in @getEnabledTargets()].sort().join(', ') | |
114 | + "Heliopropa for #{targets} from #{started_at.format(API_TIME_FORMAT)} to #{stopped_at.format(API_TIME_FORMAT)}." | |
115 | + | |
100 | 116 | addTarget: (target) -> |
101 | 117 | @targets[target.slug] = target |
102 | 118 | this |
... | ... | @@ -106,6 +122,9 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE |
106 | 122 | # enableTarget(slug) |
107 | 123 | # this |
108 | 124 | |
125 | + getEnabledTargets: -> | |
126 | + [target for slug, target of @targets when target.active] | |
127 | + | |
109 | 128 | enableTarget: (target_slug) -> |
110 | 129 | @time_series.forEach((ts) ~> ts.show() if ts.target.slug == target_slug && @parameters[ts.parameter].active) |
111 | 130 | @targets[target_slug].active = true |
... | ... | @@ -237,6 +256,9 @@ https://gitlab.irap.omp.eu/CDPP/SPACEWEATHERONLINE |
237 | 256 | ) |
238 | 257 | @time_series |
239 | 258 | |
259 | + getEnabledParameters: -> | |
260 | + [p for slug, p in @parameters when p.active] | |
261 | + | |
240 | 262 | enableParameter: (parameter_slug) -> |
241 | 263 | if parameter_slug not of @parameters then console.error("Unknown parameter #{parameter_slug}.") |
242 | 264 | @parameters[parameter_slug].active = true | ... | ... |
web/view/home.html.jinja2
... | ... | @@ -118,10 +118,16 @@ |
118 | 118 | <div class="mdl-grid"> |
119 | 119 | <div class="mdl-cell mdl-cell--4-col mdl-cell--8-col-tablet mdl-cell--4-col-phone"> |
120 | 120 | <section id="orbits"></section> |
121 | - <button id="download" class="mdl-button mdl-button--raised mdl-button--primary" | |
122 | - title="Download the CSV raw data for each target in a tarball."> | |
123 | - Download | |
124 | - </button> | |
121 | + <div class="plots-actions plots-buttons"> | |
122 | + <button id="download" class="mdl-button mdl-button--raised mdl-button--primary" | |
123 | + title="Download the CSV raw data for each target in a tarball."> | |
124 | + Download | |
125 | + </button> | |
126 | + <button id="samp" class="samp mdl-button mdl-button--raised mdl-button--primary mdl-button--disabled" | |
127 | + title="Send the data to a connected SAMP hub."> | |
128 | + SAMP | |
129 | + </button> | |
130 | + </div> | |
125 | 131 | </div> |
126 | 132 | <div class="mdl-cell mdl-cell--8-col mdl-cell--8-col-tablet mdl-cell--4-col-phone"> |
127 | 133 | <section id="time_series"> |
... | ... | @@ -234,10 +240,13 @@ |
234 | 240 | animation-delay: .8s; |
235 | 241 | } |
236 | 242 | |
237 | - #download { | |
238 | - display: block; | |
243 | + .plots-buttons { | |
244 | + text-align: center; | |
239 | 245 | margin: 3em auto; |
240 | 246 | } |
247 | + .plots-buttons button { | |
248 | + margin: auto 1em; | |
249 | + } | |
241 | 250 | |
242 | 251 | #time_series svg { |
243 | 252 | cursor: crosshair; |
... | ... | @@ -526,7 +535,8 @@ var configuration = { |
526 | 535 | orbits_container: '#orbits', |
527 | 536 | api : { |
528 | 537 | 'data_for_interval': "{{ request.url_root }}<target>_<started_at>_<stopped_at>.csv", |
529 | - 'download': "{{ request.url_root }}<targets>_<started_at>_<stopped_at>.tar.gz" | |
538 | + 'download': "{{ request.url_root }}<targets>_<started_at>_<stopped_at>.tar.gz", | |
539 | + 'samp': "{{ request.url_root }}<targets>_<params>_<started_at>_<stopped_at>.nc" | |
530 | 540 | }, |
531 | 541 | sun: { |
532 | 542 | img: '{{ static('img/sun_128.png') }}' |
... | ... | @@ -655,4 +665,58 @@ jQuery().ready(function($){ |
655 | 665 | |
656 | 666 | }); |
657 | 667 | </script> |
668 | + | |
669 | +{#### SAMP ###################################################################} | |
670 | +<script type="text/javascript"> | |
671 | + jQuery().ready(function ($) { | |
672 | + // Flag to know when a hub is connected or not | |
673 | + var isConnected = false; | |
674 | + | |
675 | + // Show SAMP button(s) depending on whether the hub is available or not. | |
676 | + var onHubAvailability = function (isHubRunning) { | |
677 | + $(".samp").each(function (index, element) { | |
678 | + if (isHubRunning) { | |
679 | + isConnected = true; | |
680 | + $(element).removeClass('disabled mdl-button--disabled'); | |
681 | + } else { | |
682 | + isConnected = false; | |
683 | + $(element).addClass('disabled mdl-button--disabled'); | |
684 | + } | |
685 | + }); | |
686 | + }; | |
687 | + | |
688 | + // Update the document about the presence of any SAMP hub every 10 sec. | |
689 | + var connector = new samp.Connector("Sender"); | |
690 | + connector.onHubAvailability(onHubAvailability, 10000); | |
691 | + window.onunload = function () { | |
692 | + connector.unregister(); | |
693 | + }; | |
694 | + | |
695 | + // Clicking on a SAMP button sends the CDF file to the connected hub. | |
696 | + $("#samp").click(function (event) { | |
697 | + event.stopPropagation(); | |
698 | + if ($(this).hasClass('disabled')) { return; } | |
699 | + // pitfall : connector.connection is ALWAYS undefined here | |
700 | + if ( ! isConnected) { // so we use a bool flag instead | |
701 | + alert("We do not detect any connected SAMP hub.\n" + | |
702 | + "Wait some more, or try refreshing this page?"); | |
703 | + return; | |
704 | + } | |
705 | + var name = sw.buildSampName(); | |
706 | + var url = sw.buildSampUrl(); | |
707 | + console.log(name, url); | |
708 | + connector.runWithConnection(function (connection) { | |
709 | + var msg = new samp.Message("table.load.cdf", { | |
710 | + "name": name, | |
711 | + "url": url // absolute URL required | |
712 | + }); | |
713 | + connection.notifyAll([msg]); | |
714 | + }, function (error) { | |
715 | + var msg = 'Error: ' + error; | |
716 | + console.error(msg); | |
717 | + alert(msg); // let's yell at the user as well | |
718 | + }); | |
719 | + }); | |
720 | + }); | |
721 | +</script> | |
658 | 722 | {% endblock %} | ... | ... |