Phi: start work on weather dialog
This commit is contained in:
parent
d96b7097f5
commit
b6bbc0aeca
13 changed files with 422 additions and 9 deletions
|
@ -9,13 +9,13 @@ require.config({
|
||||||
leaflet : '3rdparty/leaflet-0.7.3/leaflet',
|
leaflet : '3rdparty/leaflet-0.7.3/leaflet',
|
||||||
text : '3rdparty/require/text',
|
text : '3rdparty/require/text',
|
||||||
flot : '3rdparty/flot/jquery.flot',
|
flot : '3rdparty/flot/jquery.flot',
|
||||||
fgcommand: 'lib/fgcommand',
|
fgcommand : 'lib/fgcommand',
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
require([
|
require([
|
||||||
'knockout', 'jquery', 'themeswitch'
|
'knockout', 'jquery', 'themeswitch'
|
||||||
], function(ko,jquery) {
|
], function(ko, jquery) {
|
||||||
|
|
||||||
function KnockProps(aliases) {
|
function KnockProps(aliases) {
|
||||||
|
|
||||||
|
@ -105,8 +105,8 @@ require([
|
||||||
var p = (self.props[prop] = ko.pureComputed({
|
var p = (self.props[prop] = ko.pureComputed({
|
||||||
read : target,
|
read : target,
|
||||||
write : function(newValue) {
|
write : function(newValue) {
|
||||||
if( newValue == target() )
|
if (newValue == target())
|
||||||
return;
|
return;
|
||||||
target(newValue);
|
target(newValue);
|
||||||
target.notifySubscribers(newValue);
|
target.notifySubscribers(newValue);
|
||||||
}
|
}
|
||||||
|
@ -116,8 +116,8 @@ require([
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.write = function(prop,value) {
|
this.write = function(prop, value) {
|
||||||
var path = this.aliases[prop] || "";
|
var path = this.aliases[prop] || "";
|
||||||
if (path.length == 0) {
|
if (path.length == 0) {
|
||||||
console.log("can't write " + prop + ": unknown alias.");
|
console.log("can't write " + prop + ": unknown alias.");
|
||||||
|
@ -126,10 +126,24 @@ require([
|
||||||
this.ws.send(JSON.stringify({
|
this.ws.send(JSON.stringify({
|
||||||
command : 'set',
|
command : 'set',
|
||||||
node : path,
|
node : path,
|
||||||
value: value
|
value : value
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.propsToObject = function(prop, map, result) {
|
||||||
|
result = result || {}
|
||||||
|
prop.children.forEach(function(prop) {
|
||||||
|
var target = map[prop.name] || null;
|
||||||
|
if (target) {
|
||||||
|
if (typeof (result[target]) === 'function') {
|
||||||
|
result[target](prop.value);
|
||||||
|
} else {
|
||||||
|
result[target] = prop.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ko.extenders.fgprop = function(target, prop) {
|
ko.extenders.fgprop = function(target, prop) {
|
||||||
|
@ -227,6 +241,10 @@ require([
|
||||||
"gnd-temp", "/environment/config/boundary/entry/temperature-degc"
|
"gnd-temp", "/environment/config/boundary/entry/temperature-degc"
|
||||||
], [
|
], [
|
||||||
"gnd-dewp", "/environment/config/boundary/entry/dewpoint-degc"
|
"gnd-dewp", "/environment/config/boundary/entry/dewpoint-degc"
|
||||||
|
], [
|
||||||
|
"metar", "/environment/metar/data"
|
||||||
|
], [
|
||||||
|
"metar-valid", "/environment/metar/valid"
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ define([
|
||||||
// or
|
// or
|
||||||
// if some other part of your code calls ko.removeNode(element)
|
// if some other part of your code calls ko.removeNode(element)
|
||||||
var plot = ko.utils.domData.set(element, "flotchart-plot", null);
|
var plot = ko.utils.domData.set(element, "flotchart-plot", null);
|
||||||
// TODO: unsubscribe from data and options observables?
|
// TODO: unsubscribe from data and options observables!!
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
7
webgui/topics/Environment/Weather.html
Normal file
7
webgui/topics/Environment/Weather.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<h3>Basic Troposphere Weather Conditions</h3>
|
||||||
|
|
||||||
|
<div data-bind="foreach: topics, buttonset: { refreshOn: topics }">
|
||||||
|
<input type="radio" name="mygroup" data-bind="attr: { id: $data }, click: $parent.selectTopic" />
|
||||||
|
<label data-bind="attr: { 'for': $data }, text: $data"></label>
|
||||||
|
</div>
|
||||||
|
<div data-bind="component: { name: selectedComponent }"></div>
|
52
webgui/topics/Environment/Weather.js
Normal file
52
webgui/topics/Environment/Weather.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
define([
|
||||||
|
'knockout', 'text!./Weather.html', 'kojqui/buttonset'
|
||||||
|
], function(ko, htmlString) {
|
||||||
|
|
||||||
|
ko.components.register('Environment/Weather/METAR', {
|
||||||
|
require : 'topics/Environment/Weather/METAR'
|
||||||
|
});
|
||||||
|
|
||||||
|
ko.components.register('Environment/Weather/Clouds', {
|
||||||
|
require : 'topics/Environment/Weather/CloudsLayers'
|
||||||
|
});
|
||||||
|
|
||||||
|
ko.components.register('Environment/Weather/Boundary', {
|
||||||
|
require : 'topics/Environment/Weather/Boundary'
|
||||||
|
});
|
||||||
|
|
||||||
|
ko.components.register('Environment/Weather/Aloft', {
|
||||||
|
require : 'topics/Environment/Weather/Aloft'
|
||||||
|
});
|
||||||
|
|
||||||
|
function ViewModel(params) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.topics = [
|
||||||
|
'METAR',
|
||||||
|
'Clouds',
|
||||||
|
'Boundary',
|
||||||
|
'Aloft',
|
||||||
|
];
|
||||||
|
|
||||||
|
self.selectedTopic = ko.observable();
|
||||||
|
|
||||||
|
self.selectedComponent = ko.pureComputed(function() {
|
||||||
|
return "Environment/Weather/" + self.selectedTopic();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.selectTopic = function(topic) {
|
||||||
|
self.selectedTopic(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.selectTopic(self.topics[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModel.prototype.dispose = function() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return component definition
|
||||||
|
return {
|
||||||
|
viewModel : ViewModel,
|
||||||
|
template : htmlString
|
||||||
|
};
|
||||||
|
});
|
26
webgui/topics/Environment/Weather/Aloft.html
Normal file
26
webgui/topics/Environment/Weather/Aloft.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<table class="ui-widget-content ui-corner-all">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Altitude (ft)</th>
|
||||||
|
<th colspan="2">Wind (dir/kt)</th>
|
||||||
|
<th>Vis (m)</th>
|
||||||
|
<th>Temp (°C)</th>
|
||||||
|
<th>Dewp (°C)</th>
|
||||||
|
<th>Turbulence</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-bind="foreach: layerData">
|
||||||
|
<tr>
|
||||||
|
<td><input data-bind="spinner: { value: altitude }" style="width: 4em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: windDir }" style="width: 2em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: windSpeed }" style="width: 1.5em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: visibility }" style="width: 4em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: temperature }" style="width: 1.5em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: dewpoint }" style="width: 1.5em;"></td>
|
||||||
|
<td><select
|
||||||
|
data-bind="value: turbulenceValue, selectmenu: {}, options: turbulence, optionsValue: 'id', optionsText: 'text'"
|
||||||
|
style="width: 10em;"></select></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
36
webgui/topics/Environment/Weather/Aloft.js
Normal file
36
webgui/topics/Environment/Weather/Aloft.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
define([
|
||||||
|
'jquery', 'knockout', 'text!./Aloft.html', './LayerData', 'kojqui/selectmenu'
|
||||||
|
], function(jquery, ko, htmlString, layerData ) {
|
||||||
|
|
||||||
|
function ViewModel(params) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.layerData = ko.observableArray([]);
|
||||||
|
|
||||||
|
jquery.get('/json/environment/config/aloft?d=2', null, function(data) {
|
||||||
|
|
||||||
|
var assemble = function(data) {
|
||||||
|
var l = [];
|
||||||
|
data.children.forEach(function(prop) {
|
||||||
|
if (prop.name === 'entry') {
|
||||||
|
var layer = new layerData();
|
||||||
|
l.push(ko.utils.knockprops.propsToObject(prop, layer.PropertyMap, layer ));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return l.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.layerData(assemble(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ViewModel.prototype.dispose = function() {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Return component definition
|
||||||
|
return {
|
||||||
|
viewModel : ViewModel,
|
||||||
|
template : htmlString
|
||||||
|
};
|
||||||
|
});
|
26
webgui/topics/Environment/Weather/Boundary.html
Normal file
26
webgui/topics/Environment/Weather/Boundary.html
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<table class="ui-widget-content ui-corner-all">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Altitude (ft)</th>
|
||||||
|
<th colspan="2">Wind (dir/kt)</th>
|
||||||
|
<th>Vis (m)</th>
|
||||||
|
<th>Temp (°C)</th>
|
||||||
|
<th>Dewp (°C)</th>
|
||||||
|
<th>Turbulence</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-bind="foreach: layerData">
|
||||||
|
<tr>
|
||||||
|
<td><input data-bind="spinner: { value: altitude }" style="width: 4em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: windDir }" style="width: 2em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: windSpeed }" style="width: 1.5em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: visibility }" style="width: 4em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: temperature }" style="width: 1.5em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: dewpoint }" style="width: 1.5em;"></td>
|
||||||
|
<td><select
|
||||||
|
data-bind="value: turbulenceValue, selectmenu: {}, options: turbulence, optionsValue: 'id', optionsText: 'text'"
|
||||||
|
style="width: 10em;"></select></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
36
webgui/topics/Environment/Weather/Boundary.js
Normal file
36
webgui/topics/Environment/Weather/Boundary.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
define([
|
||||||
|
'jquery', 'knockout', 'text!./Boundary.html', './LayerData', 'kojqui/selectmenu'
|
||||||
|
], function(jquery, ko, htmlString, layerData ) {
|
||||||
|
|
||||||
|
function ViewModel(params) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.layerData = ko.observableArray([]);
|
||||||
|
|
||||||
|
jquery.get('/json/environment/config/boundary?d=2', null, function(data) {
|
||||||
|
|
||||||
|
var assemble = function(data) {
|
||||||
|
var l = [];
|
||||||
|
data.children.forEach(function(prop) {
|
||||||
|
if (prop.name === 'entry') {
|
||||||
|
var layer = new layerData();
|
||||||
|
l.push(ko.utils.knockprops.propsToObject(prop, layer.PropertyMap, layer ));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return l.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.layerData(assemble(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ViewModel.prototype.dispose = function() {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Return component definition
|
||||||
|
return {
|
||||||
|
viewModel : ViewModel,
|
||||||
|
template : htmlString
|
||||||
|
};
|
||||||
|
});
|
18
webgui/topics/Environment/Weather/CloudLayers.html
Normal file
18
webgui/topics/Environment/Weather/CloudLayers.html
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<table class="ui-widget-content ui-corner-all">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Coverage</th>
|
||||||
|
<th>Base (ft)</th>
|
||||||
|
<th>Tops (ft)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody data-bind="foreach: cloudLayers">
|
||||||
|
<tr>
|
||||||
|
<td><select
|
||||||
|
data-bind="value: coverageId, selectmenu: {}, options: coverage, optionsValue: 'id', optionsText: 'text'"
|
||||||
|
style="width: 11em;"></select></td>
|
||||||
|
<td><input data-bind="spinner: { value: base, disabled: coverageId() == 4 }" style="width: 4em;"></td>
|
||||||
|
<td><input data-bind="spinner: { value: tops, disabled: coverageId() == 4 }" style="width: 4em;"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
74
webgui/topics/Environment/Weather/CloudsLayers.js
Normal file
74
webgui/topics/Environment/Weather/CloudsLayers.js
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
define([
|
||||||
|
'jquery', 'knockout', 'text!./CloudLayers.html', 'kojqui/selectmenu'
|
||||||
|
], function(jquery, ko, htmlString) {
|
||||||
|
|
||||||
|
function ViewModel(params) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
function CloudLayer() {
|
||||||
|
var self = this;
|
||||||
|
self.index = 0;
|
||||||
|
self.base = ko.observable(0);
|
||||||
|
self.coverage = [
|
||||||
|
{
|
||||||
|
id : 4,
|
||||||
|
text : 'clear'
|
||||||
|
}, {
|
||||||
|
id : 3,
|
||||||
|
text : 'few'
|
||||||
|
}, {
|
||||||
|
id : 2,
|
||||||
|
text : 'scattered'
|
||||||
|
}, {
|
||||||
|
id : 1,
|
||||||
|
text : 'broken'
|
||||||
|
}, {
|
||||||
|
id : 0,
|
||||||
|
text : 'overcast'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
self.thickness = ko.observable(0);
|
||||||
|
self.coverageId = ko.observable(0);
|
||||||
|
self.tops = ko.pureComputed(function() {
|
||||||
|
return self.base() + self.thickness();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cloudLayers = ko.observableArray([]);
|
||||||
|
|
||||||
|
jquery.get('/json/environment/clouds?d=2', null, function(data) {
|
||||||
|
|
||||||
|
var assemble = function(data) {
|
||||||
|
|
||||||
|
var PropertyMap = {
|
||||||
|
"index" : "index",
|
||||||
|
"elevation-ft" : "base",
|
||||||
|
"coverage-type" : "coverageId",
|
||||||
|
"thickness-ft" : "thickness",
|
||||||
|
};
|
||||||
|
|
||||||
|
var cloudLayers = [];
|
||||||
|
data.children.forEach(function(prop) {
|
||||||
|
if (prop.name === 'layer') {
|
||||||
|
var layer = new CloudLayer();
|
||||||
|
cloudLayers.push(ko.utils.knockprops.propsToObject(prop, PropertyMap, layer));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return cloudLayers.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.cloudLayers(assemble(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewModel.prototype.dispose = function() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return component definition
|
||||||
|
return {
|
||||||
|
viewModel : ViewModel,
|
||||||
|
template : htmlString
|
||||||
|
};
|
||||||
|
});
|
43
webgui/topics/Environment/Weather/LayerData.js
Normal file
43
webgui/topics/Environment/Weather/LayerData.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
define([
|
||||||
|
'knockout',
|
||||||
|
], function(ko) {
|
||||||
|
|
||||||
|
function LayerData() {
|
||||||
|
var self = this;
|
||||||
|
self.index = 0;
|
||||||
|
self.altitude = ko.observable(0);
|
||||||
|
self.windDir = ko.observable(0);
|
||||||
|
self.windSpeed = ko.observable(0);
|
||||||
|
self.visibility = ko.observable(0);
|
||||||
|
self.temperature = ko.observable(0);
|
||||||
|
self.dewpoint = ko.observable(0);
|
||||||
|
self.turbulence = [
|
||||||
|
{
|
||||||
|
id : 0,
|
||||||
|
text : 'none'
|
||||||
|
}, {
|
||||||
|
id : 1,
|
||||||
|
text : 'light'
|
||||||
|
}, {
|
||||||
|
id : 2,
|
||||||
|
text : 'moderate'
|
||||||
|
}, {
|
||||||
|
id : 3,
|
||||||
|
text : 'severe'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
self.turbulenceValue = ko.observable(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerData.prototype.PropertyMap = {
|
||||||
|
"index": "index",
|
||||||
|
"elevation-ft": "altitude",
|
||||||
|
"wind-from-heading-deg": "windDir",
|
||||||
|
"wind-speed-kt": "windSpeed",
|
||||||
|
"visibility-m": "visibility",
|
||||||
|
"temperature-degc": "temperature",
|
||||||
|
"dewpoint-degc": "dewpoint",
|
||||||
|
};
|
||||||
|
|
||||||
|
return LayerData;
|
||||||
|
});
|
9
webgui/topics/Environment/Weather/METAR.html
Normal file
9
webgui/topics/Environment/Weather/METAR.html
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<div id="weather-scenarios" data-bind="foreach: scenarios">
|
||||||
|
<h3 data-bind="text: name"></h3>
|
||||||
|
<p>
|
||||||
|
<button data-bind="button: { }, click: $parent.selectScenario ">Select</button><br />
|
||||||
|
<span data-bind="text: description"></span><br />
|
||||||
|
<span style="font-weight: bold">METAR: </span>
|
||||||
|
<span style="font-style: italic" data-bind="text: metar"></span>
|
||||||
|
</p>
|
||||||
|
</div>
|
68
webgui/topics/Environment/Weather/METAR.js
Normal file
68
webgui/topics/Environment/Weather/METAR.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
define([
|
||||||
|
'jquery', 'knockout', 'text!./METAR.html', 'jquery-ui/accordion', 'kojqui/button'
|
||||||
|
], function(jquery, ko, htmlString) {
|
||||||
|
|
||||||
|
function WeatherScenarioVM() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.index = 0;
|
||||||
|
self.name = "unnamed";
|
||||||
|
self.metar = ko.observable("NIL");
|
||||||
|
self.description = "NIL";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var WeatherScenarioMapping = {
|
||||||
|
"index" : "index",
|
||||||
|
"description" : "description",
|
||||||
|
"name" : "name",
|
||||||
|
"metar" : "metar"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ViewModel(params) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.scenarios = ko.observableArray([]);
|
||||||
|
self.selectScenario = function(foo) {
|
||||||
|
console.log(foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
jquery.get('/json/environment/weather-scenarios?d=2', null, function(data) {
|
||||||
|
|
||||||
|
var assemble = function(data) {
|
||||||
|
var scenarios = [];
|
||||||
|
data.children.forEach(function(prop) {
|
||||||
|
if (prop.name === 'scenario') {
|
||||||
|
var scenario = new WeatherScenarioVM();
|
||||||
|
scenarios.push(ko.utils.knockprops.propsToObject(prop, WeatherScenarioMapping, scenario));
|
||||||
|
|
||||||
|
// listen to the metar property for the live data scenario
|
||||||
|
if (scenario.name == "Live data") {
|
||||||
|
scenario.metar = ko.observable().extend({
|
||||||
|
fgprop : 'metar'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return scenarios;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.scenarios(assemble(data));
|
||||||
|
jquery("#weather-scenarios").accordion({
|
||||||
|
collapsible : true,
|
||||||
|
heightStyle : "content",
|
||||||
|
active : false,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ViewModel.prototype.dispose = function() {
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Return component definition
|
||||||
|
return {
|
||||||
|
viewModel : ViewModel,
|
||||||
|
template : htmlString
|
||||||
|
};
|
||||||
|
});
|
Loading…
Add table
Reference in a new issue