diff --git a/htdocs/generalsettings.html b/htdocs/generalsettings.html index 3367ed8..4731a02 100644 --- a/htdocs/generalsettings.html +++ b/htdocs/generalsettings.html @@ -5,10 +5,8 @@ - - - + diff --git a/htdocs/lib/settings/Input.js b/htdocs/lib/settings/Input.js new file mode 100644 index 0000000..4686aac --- /dev/null +++ b/htdocs/lib/settings/Input.js @@ -0,0 +1,114 @@ +function Input(name, value, options) { + this.name = name; + this.value = value; + this.options = options; + this.label = options && options.label || name; +}; + +Input.prototype.getClasses = function() { + return ['form-control', 'form-control-sm']; +} + +Input.prototype.bootstrapify = function(input) { + this.getClasses().forEach(input.addClass.bind(input)); + return [ + '
', + '', + '
', + $.map(input, function(el) { + return el.outerHTML; + }).join(''), + '
', + '
' + ].join(''); +}; + +function TextInput() { + Input.apply(this, arguments); +}; + +TextInput.prototype = new Input(); + +TextInput.prototype.render = function() { + return this.bootstrapify($('')); +} + +function NumberInput() { + Input.apply(this, arguments); +}; + +NumberInput.prototype = new Input(); + +NumberInput.prototype.render = function() { + return this.bootstrapify($('')); +}; + +function SoapyGainInput() { + Input.apply(this, arguments); +} + +SoapyGainInput.prototype = new Input(); + +SoapyGainInput.prototype.getClasses = function() { + return []; +}; + +SoapyGainInput.prototype.render = function(){ + var markup = $( + '
' + + '
Gain mode
' + + '
' + + '' + + '
' + + '
' + + '
' + + '
Gain
' + + '
' + + '' + + '
' + + '
' + + this.options.gains.map(function(g){ + return '
' + + '
' + g + '
' + + '
' + + '' + + '
' + + '
'; + }).join('') + ); + var el = $(this.bootstrapify(markup)) + var setMode = function(mode){ + el.find('.option').hide(); + el.find('.gain-mode-' + mode).show(); + }; + el.on('change', 'select', function(){ + var mode = $(this).val(); + setMode(mode); + }); + setMode('auto'); + return el; +}; + +function ProfileInput() { + Input.apply(this, arguments); +}; + +ProfileInput.prototype = new Input(); + +ProfileInput.prototype.render = function() { + return $('

Profiles

'); +}; + +function SchedulerInput() { + Input.apply(this, arguments); +}; + +SchedulerInput.prototype = new Input(); + +SchedulerInput.prototype.render = function() { + return $('

Scheduler

'); +}; diff --git a/htdocs/lib/settings/SdrDevice.js b/htdocs/lib/settings/SdrDevice.js new file mode 100644 index 0000000..f8acada --- /dev/null +++ b/htdocs/lib/settings/SdrDevice.js @@ -0,0 +1,226 @@ +function SdrDevice(el, data) { + this.el = el; + this.data = data; + this.inputs = {}; + this.render(); + + var self = this; + el.on('click', '.fieldselector .btn', function() { + var key = el.find('.fieldselector select').val(); + self.data[key] = self.getInitialValue(key); + self.render(); + }); +}; + +SdrDevice.create = function(el) { + var data = JSON.parse(decodeURIComponent(el.data('config'))); + var type = data.type; + var constructor = SdrDevice.types[type] || SdrDevice; + return new constructor(el, data); +}; + +SdrDevice.prototype.getData = function() { + return $.extend(new Object(), this.getDefaults(), this.data); +}; + +SdrDevice.prototype.getDefaults = function() { + var defaults = {} + $.each(this.getMappings(), function(k, v) { + if (!v.includeInDefault) return; + defaults[k] = 'initialValue' in v ? v['initialValue'] : false; + }); + return defaults; +}; + +SdrDevice.prototype.getMappings = function() { + return { + "name": { + constructor: TextInput, + inputOptions: { + label: "Name" + }, + initialValue: "", + includeInDefault: true + }, + "type": { + constructor: TextInput, + inputOptions: { + label: "Type" + }, + initialValue: '', + includeInDefault: true + }, + "ppm": { + constructor: NumberInput, + inputOptions: { + label: "PPM" + }, + initialValue: 0 + }, + "profiles": { + constructor: ProfileInput, + inputOptions: { + label: "Profiles" + }, + initialValue: [], + includeInDefault: true, + position: 100 + }, + "scheduler": { + constructor: SchedulerInput, + inputOptions: { + label: "Scheduler", + }, + initialValue: {}, + position: 101 + }, + "rf_gain": { + constructor: TextInput, + inputOptions: { + label: "Gain", + }, + initialValue: 0 + } + }; +}; + +SdrDevice.prototype.getMapping = function(key) { + var mappings = this.getMappings(); + return mappings[key]; +}; + +SdrDevice.prototype.getInputClass = function(key) { + var mapping = this.getMapping(key); + return mapping && mapping.constructor || TextInput; +}; + +SdrDevice.prototype.getInitialValue = function(key) { + var mapping = this.getMapping(key); + return mapping && ('initialValue' in mapping) ? mapping['initialValue'] : false; +}; + +SdrDevice.prototype.getPosition = function(key) { + var mapping = this.getMapping(key); + return mapping && mapping.position || 10; +}; + +SdrDevice.prototype.getInputOptions = function(key) { + var mapping = this.getMapping(key); + return mapping && mapping.inputOptions || {}; +}; + +SdrDevice.prototype.getLabel = function(key) { + var options = this.getInputOptions(key); + return options && options.label || key; +}; + +SdrDevice.prototype.render = function() { + var self = this; + self.el.empty(); + var data = this.getData(); + Object.keys(data).sort(function(a, b){ + return self.getPosition(a) - self.getPosition(b); + }).forEach(function(key){ + var value = data[key]; + var inputClass = self.getInputClass(key); + var input = new inputClass(key, value, self.getInputOptions(key)); + self.inputs[key] = input; + self.el.append(input.render()); + }); + self.el.append(this.renderFieldSelector()); +}; + +SdrDevice.prototype.renderFieldSelector = function() { + var self = this; + return '
' + + '

Add new configuration options

' + + '
' + + '
' + + '
' + + '
Add to config
' + + '
' + + '
' + + '

'; +}; + +RtlSdrDevice = function() { + SdrDevice.apply(this, arguments); +}; + +RtlSdrDevice.prototype = Object.create(SdrDevice.prototype); +RtlSdrDevice.prototype.constructor = RtlSdrDevice; + +RtlSdrDevice.prototype.getMappings = function() { + var mappings = SdrDevice.prototype.getMappings.apply(this, arguments); + return $.extend(new Object(), mappings, { + "device": { + constructor: TextInput, + inputOptions:{ + label: "Serial number" + }, + initialValue: "" + } + }); +}; + +SoapySdrDevice = function() { + SdrDevice.apply(this, arguments); +}; + +SoapySdrDevice.prototype = Object.create(SdrDevice.prototype); +SoapySdrDevice.prototype.constructor = SoapySdrDevice; + +SoapySdrDevice.prototype.getMappings = function() { + var mappings = SdrDevice.prototype.getMappings.apply(this, arguments); + return $.extend(new Object(), mappings, { + "device": { + constructor: TextInput, + inputOptions:{ + label: "Soapy device selector" + }, + initialValue: "" + } + }); +}; + +SdrplaySdrDevice = function() { + SoapySdrDevice.apply(this, arguments); +}; + +SdrplaySdrDevice.prototype = Object.create(SoapySdrDevice.prototype); +SdrplaySdrDevice.prototype.constructor = SdrplaySdrDevice; + +SdrplaySdrDevice.prototype.getMappings = function() { + var mappings = SoapySdrDevice.prototype.getMappings.apply(this, arguments); + return $.extend(new Object(), mappings, { + "rf_gain": { + constructor: SoapyGainInput, + initialValue: 0, + inputOptions: { + label: "Gain", + gains: ['RFGR', 'IFGR'] + } + } + }); +}; + +SdrDevice.types = { + 'rtl_sdr': RtlSdrDevice, + 'sdrplay': SdrplaySdrDevice +}; + +$.fn.sdrdevice = function() { + return this.map(function(){ + var el = $(this); + if (!el.data('sdrdevice')) { + el.data('sdrdevice', SdrDevice.create(el)); + } + return el.data('sdrdevice'); + }); +}; diff --git a/htdocs/sdrsettings.html b/htdocs/sdrsettings.html index 89e6a8f..74aa8b7 100644 --- a/htdocs/sdrsettings.html +++ b/htdocs/sdrsettings.html @@ -5,9 +5,7 @@ - - - + diff --git a/htdocs/settings.html b/htdocs/settings.html index 39cecf9..80dce91 100644 --- a/htdocs/settings.html +++ b/htdocs/settings.html @@ -5,9 +5,7 @@ - - - + diff --git a/htdocs/settings.js b/htdocs/settings.js index bf9a03c..e95e2fe 100644 --- a/htdocs/settings.js +++ b/htdocs/settings.js @@ -1,345 +1,3 @@ -function Input(name, value, options) { - this.name = name; - this.value = value; - this.options = options; - this.label = options && options.label || name; -}; - -Input.prototype.getClasses = function() { - return ['form-control', 'form-control-sm']; -} - -Input.prototype.bootstrapify = function(input) { - this.getClasses().forEach(input.addClass.bind(input)); - return [ - '
', - '', - '
', - $.map(input, function(el) { - return el.outerHTML; - }).join(''), - '
', - '
' - ].join(''); -}; - -function TextInput() { - Input.apply(this, arguments); -}; - -TextInput.prototype = new Input(); - -TextInput.prototype.render = function() { - return this.bootstrapify($('')); -} - -function NumberInput() { - Input.apply(this, arguments); -}; - -NumberInput.prototype = new Input(); - -NumberInput.prototype.render = function() { - return this.bootstrapify($('')); -}; - -function SoapyGainInput() { - Input.apply(this, arguments); -} - -SoapyGainInput.prototype = new Input(); - -SoapyGainInput.prototype.getClasses = function() { - return []; -}; - -SoapyGainInput.prototype.render = function(){ - var markup = $( - '
' + - '
Gain mode
' + - '
' + - '' + - '
' + - '
' + - '
' + - '
Gain
' + - '
' + - '' + - '
' + - '
' + - this.options.gains.map(function(g){ - return '
' + - '
' + g + '
' + - '
' + - '' + - '
' + - '
'; - }).join('') - ); - var el = $(this.bootstrapify(markup)) - var setMode = function(mode){ - el.find('.option').hide(); - el.find('.gain-mode-' + mode).show(); - }; - el.on('change', 'select', function(){ - var mode = $(this).val(); - setMode(mode); - }); - setMode('auto'); - return el; -}; - -function ProfileInput() { - Input.apply(this, arguments); -}; - -ProfileInput.prototype = new Input(); - -ProfileInput.prototype.render = function() { - return $('

Profiles

'); -}; - -function SchedulerInput() { - Input.apply(this, arguments); -}; - -SchedulerInput.prototype = new Input(); - -SchedulerInput.prototype.render = function() { - return $('

Scheduler

'); -}; - -function SdrDevice(el, data) { - this.el = el; - this.data = data; - this.inputs = {}; - this.render(); - - var self = this; - el.on('click', '.fieldselector .btn', function() { - var key = el.find('.fieldselector select').val(); - self.data[key] = self.getInitialValue(key); - self.render(); - }); -}; - -SdrDevice.create = function(el) { - var data = JSON.parse(decodeURIComponent(el.data('config'))); - var type = data.type; - var constructor = SdrDevice.types[type] || SdrDevice; - return new constructor(el, data); -}; - -SdrDevice.prototype.getData = function() { - return $.extend(new Object(), this.getDefaults(), this.data); -}; - -SdrDevice.prototype.getDefaults = function() { - var defaults = {} - $.each(this.getMappings(), function(k, v) { - if (!v.includeInDefault) return; - defaults[k] = 'initialValue' in v ? v['initialValue'] : false; - }); - return defaults; -}; - -SdrDevice.prototype.getMappings = function() { - return { - "name": { - constructor: TextInput, - inputOptions: { - label: "Name" - }, - initialValue: "", - includeInDefault: true - }, - "type": { - constructor: TextInput, - inputOptions: { - label: "Type" - }, - initialValue: '', - includeInDefault: true - }, - "ppm": { - constructor: NumberInput, - inputOptions: { - label: "PPM" - }, - initialValue: 0 - }, - "profiles": { - constructor: ProfileInput, - inputOptions: { - label: "Profiles" - }, - initialValue: [], - includeInDefault: true, - position: 100 - }, - "scheduler": { - constructor: SchedulerInput, - inputOptions: { - label: "Scheduler", - }, - initialValue: {}, - position: 101 - }, - "rf_gain": { - constructor: TextInput, - inputOptions: { - label: "Gain", - }, - initialValue: 0 - } - }; -}; - -SdrDevice.prototype.getMapping = function(key) { - var mappings = this.getMappings(); - return mappings[key]; -}; - -SdrDevice.prototype.getInputClass = function(key) { - var mapping = this.getMapping(key); - return mapping && mapping.constructor || TextInput; -}; - -SdrDevice.prototype.getInitialValue = function(key) { - var mapping = this.getMapping(key); - return mapping && ('initialValue' in mapping) ? mapping['initialValue'] : false; -}; - -SdrDevice.prototype.getPosition = function(key) { - var mapping = this.getMapping(key); - return mapping && mapping.position || 10; -}; - -SdrDevice.prototype.getInputOptions = function(key) { - var mapping = this.getMapping(key); - return mapping && mapping.inputOptions || {}; -}; - -SdrDevice.prototype.getLabel = function(key) { - var options = this.getInputOptions(key); - return options && options.label || key; -}; - -SdrDevice.prototype.render = function() { - var self = this; - self.el.empty(); - var data = this.getData(); - Object.keys(data).sort(function(a, b){ - return self.getPosition(a) - self.getPosition(b); - }).forEach(function(key){ - var value = data[key]; - var inputClass = self.getInputClass(key); - var input = new inputClass(key, value, self.getInputOptions(key)); - self.inputs[key] = input; - self.el.append(input.render()); - }); - self.el.append(this.renderFieldSelector()); -}; - -SdrDevice.prototype.renderFieldSelector = function() { - var self = this; - return '
' + - '

Add new configuration options

' + - '
' + - '
' + - '
' + - '
Add to config
' + - '
' + - '
' + - '

'; -}; - -RtlSdrDevice = function() { - SdrDevice.apply(this, arguments); -}; - -RtlSdrDevice.prototype = Object.create(SdrDevice.prototype); -RtlSdrDevice.prototype.constructor = RtlSdrDevice; - -RtlSdrDevice.prototype.getMappings = function() { - var mappings = SdrDevice.prototype.getMappings.apply(this, arguments); - return $.extend(new Object(), mappings, { - "device": { - constructor: TextInput, - inputOptions:{ - label: "Serial number" - }, - initialValue: "" - } - }); -}; - -SoapySdrDevice = function() { - SdrDevice.apply(this, arguments); -}; - -SoapySdrDevice.prototype = Object.create(SdrDevice.prototype); -SoapySdrDevice.prototype.constructor = SoapySdrDevice; - -SoapySdrDevice.prototype.getMappings = function() { - var mappings = SdrDevice.prototype.getMappings.apply(this, arguments); - return $.extend(new Object(), mappings, { - "device": { - constructor: TextInput, - inputOptions:{ - label: "Soapy device selector" - }, - initialValue: "" - } - }); -}; - -SdrplaySdrDevice = function() { - SoapySdrDevice.apply(this, arguments); -}; - -SdrplaySdrDevice.prototype = Object.create(SoapySdrDevice.prototype); -SdrplaySdrDevice.prototype.constructor = SdrplaySdrDevice; - -SdrplaySdrDevice.prototype.getMappings = function() { - var mappings = SoapySdrDevice.prototype.getMappings.apply(this, arguments); - return $.extend(new Object(), mappings, { - "rf_gain": { - constructor: SoapyGainInput, - initialValue: 0, - inputOptions: { - label: "Gain", - gains: ['RFGR', 'IFGR'] - } - } - }); -}; - -SdrDevice.types = { - 'rtl_sdr': RtlSdrDevice, - 'sdrplay': SdrplaySdrDevice -}; - -$.fn.sdrdevice = function() { - return this.map(function(){ - var el = $(this); - if (!el.data('sdrdevice')) { - el.data('sdrdevice', SdrDevice.create(el)); - } - return el.data('sdrdevice'); - }); -}; - $(function(){ $(".map-input").each(function(el) { var $el = $(this); diff --git a/owrx/controllers/assets.py b/owrx/controllers/assets.py index 59a532f..a8b9d4e 100644 --- a/owrx/controllers/assets.py +++ b/owrx/controllers/assets.py @@ -87,6 +87,13 @@ class CompiledAssetsController(Controller): "lib/Header.js", "map.js", ], + "settings.js": [ + "lib/jquery-3.2.1.min.js", + "lib/Header.js", + "lib/settings/Input.js", + "lib/settings/SdrDevice.js", + "settings.js", + ] } def indexAction(self):