From ab50f3841ea3b88868519ecf1df4539b77f1fc13 Mon Sep 17 00:00:00 2001 From: coulisse Date: Sun, 19 Feb 2023 22:47:28 +0100 Subject: [PATCH] changed api method from get to post --- CITATION.cff | 4 +- README.md | 2 +- cfg/webapp_log_config.ini | 2 +- docs/CHANGELOG.md | 5 +- static/html/offline.html | 10 +- static/js/dev/callsign_inline.js | 19 +- static/js/dev/callsign_search.js | 1 - static/js/dev/plot.js | 456 +++++++++++++++------------ static/js/dev/table.js | 86 ++--- static/js/rel/callsign_inline.min.js | 2 +- static/js/rel/callsign_search.min.js | 2 +- static/js/rel/plot.min.js | 2 +- static/js/rel/table.min.js | 2 +- static/pwa/manifest.webmanifest | 2 +- static/pwa/service-worker.js | 10 +- templates/_base.html | 12 +- templates/callsign.html | 2 +- templates/index.html | 4 +- templates/plots.html | 2 +- webapp.py | 74 +++-- 20 files changed, 388 insertions(+), 311 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index bc69d71..ee32b6f 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -24,5 +24,5 @@ keywords: - dxcluster - spiderweb license: GPL-3.0 -version: v2.4.2 -date-released: 2023-02-18 +version: v2.4.4 +date-released: 2023-02-19 diff --git a/README.md b/README.md index 11dd827..333b7d1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![CodeFactor](https://www.codefactor.io/repository/github/coulisse/spiderweb/badge)](https://www.codefactor.io/repository/github/coulisse/spiderweb) -- **Release:** v2.4.2 +- **Release:** v2.4.4 - **Author:** Corrado Gerbaldo - [IU1BOW](https://www.qrz.com/db/IU1BOW) - **Mail:** - **Licensing:** Gpl V3.0 see [LICENSE](LICENSE) file. diff --git a/cfg/webapp_log_config.ini b/cfg/webapp_log_config.ini index 843a930..9584aad 100644 --- a/cfg/webapp_log_config.ini +++ b/cfg/webapp_log_config.ini @@ -12,7 +12,7 @@ level=INFO handlers=stream_handler,file_handler [logger_webapp] -level=DEBUG +level=INFO handlers=stream_handler,file_handler qualname=webapp propagate=0 diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index e120e9d..f714c37 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,9 +1,10 @@ ### Change log -Date: 18/02/2023 -Release: v2.4.2 +Date: 19/02/2023 +Release: v2.4.4 - replaced multipart form post with url encoded for security reasons - fixed bands and continents in band activity chart - upgraded Werkzeug to 2.2.3 +- changed some api call from get to post method in order to not caching it Date: 11/02/2023 Release: v2.4.2 diff --git a/static/html/offline.html b/static/html/offline.html index 7bbaeb2..a5877a6 100644 --- a/static/html/offline.html +++ b/static/html/offline.html @@ -16,7 +16,7 @@ - + @@ -96,23 +96,23 @@ © Copyleft: IU1BOW - Spiderweb - v2.4.2 + v2.4.4 - + - + - + diff --git a/static/js/dev/callsign_inline.js b/static/js/dev/callsign_inline.js index f590563..7004f08 100644 --- a/static/js/dev/callsign_inline.js +++ b/static/js/dev/callsign_inline.js @@ -5,9 +5,22 @@ //var my_adxo_events=jQuery.parseJSON(my_adxo_events_json.replaceAll("\t","")); var my_adxo_events = JSON.parse(my_adxo_events_json.replaceAll('\t', '')); -//var qryString = 'spotlist?c=' + my_callsign; -var qryString = 'spotlist?c=' + callsign; -fetch(qryString) + +//var qryString = 'spotlist?c=' + callsign; +let params = {}; +params['callsign']=callsign; + +//let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content"); + +fetch('spotlist', { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify( params ) +}) .then((response) => response.json()) .then((data) => { try { diff --git a/static/js/dev/callsign_search.js b/static/js/dev/callsign_search.js index c3f18e7..028244b 100644 --- a/static/js/dev/callsign_search.js +++ b/static/js/dev/callsign_search.js @@ -9,7 +9,6 @@ function myCallsignSearch(event) { //construct query parameters if (callsign.replace(/\s/g, '').length > 0) { location.href = ('/callsign.html?c=').concat((callsign.trim()).toUpperCase()); - console.log(location.href); //form.action="index.html"; } diff --git a/static/js/dev/plot.js b/static/js/dev/plot.js index 9e90795..a06529c 100644 --- a/static/js/dev/plot.js +++ b/static/js/dev/plot.js @@ -1,25 +1,25 @@ class plot_base { //refresh = function(){ - refresh() { + refresh() { } /** - * Chart creator - * - * @constructor - * @param {String} chart_id The HTML id where place chart - * @param {string} end_point This is backend end-point for chart datas - */ - constructor(chart_id,end_point) { + * Chart creator + * + * @constructor + * @param {String} chart_id The HTML id where place chart + * @param {string} end_point This is backend end-point for chart datas + */ + constructor(chart_id, end_point) { // Initialize the echarts instance based on the prepared dom let chartDom = document.getElementById(chart_id); - this.end_point=end_point; + this.end_point = end_point; this.myChart = echarts.init(chartDom); //resize - let chart = echarts.init(document.querySelector('#'+chart_id), null); - window.addEventListener('resize',function(){ + let chart = echarts.init(document.querySelector('#' + chart_id), null); + window.addEventListener('resize', function () { chart.resize(); }); } @@ -33,13 +33,13 @@ class plot_base { class band_activity extends plot_base { /** - * refresh and populate chart - * - * @param {string} region This is the continent name (EU,AF,NA...) of the selected - */ + * refresh and populate chart + * + * @param {string} region This is the continent name (EU,AF,NA...) of the selected + */ //refresh = function(this.myChart, end_point, region, bands, continents){ //refresh = function(region){ - refresh (region) { + refresh(region) { super.refresh(); console.log('refresh band_activity'); if (typeof region !== 'undefined') { @@ -47,12 +47,25 @@ class band_activity extends plot_base { } // Asynchronous Data Loading - fetch(this.end_point+'?continent='+this.selectedContinent) - .then((response) => response.json()) + //fetch(this.end_point + '?continent=' + this.selectedContinent) + const params = { + continent: this.selectedContinent + }; + + fetch(this.end_point, { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify( params ) + }) + .then((response) => response.json()) .then((data) => { // Fill in the data - var last_refresh=get_last_refresh(data); - var dataMap=Array.from(data['band activity']).map(function (item) { + var last_refresh = get_last_refresh(data); + var dataMap = Array.from(data['band activity']).map(function (item) { return [item[1], item[0], item[2] || '-']; }); //options @@ -60,29 +73,29 @@ class band_activity extends plot_base { tooltip: { position: 'top', formatter: function (p) { - var format = p.seriesName +' on ' + p.name +' band: '+''+p.data[2]+''; + var format = p.seriesName + ' on ' + p.name + ' band: ' + '' + p.data[2] + ''; return format; - } + } }, title: { - text:'Band activity', + text: 'Band activity', subtext: last_refresh, top: 'top', - left:'left' - }, + left: 'left' + }, toolbox: { show: true, showTitle: false, orient: 'vertical', right: 'right', - top : 'bottom', + top: 'bottom', feature: { mark: { show: true }, dataView: { show: true, readOnly: true }, restore: { show: true }, saveAsImage: { show: true } } - }, + }, grid: { height: '80%', left: 25, @@ -90,12 +103,12 @@ class band_activity extends plot_base { right: 60, bottom: 0, show: true, - backgroundColor: 'rgb(255, 255, 255)', + backgroundColor: 'rgb(255, 255, 255)', }, xAxis: { type: 'category', data: this.bands, - axisTick: { + axisTick: { show: true, }, axisLine: { @@ -108,12 +121,12 @@ class band_activity extends plot_base { yAxis: { type: 'category', data: this.continents, - axisTick: { + axisTick: { show: true, }, axisLine: { show: false, - }, + }, splitArea: { show: true } @@ -125,10 +138,10 @@ class band_activity extends plot_base { top: 'center', min: 0, max: 30, - inRange : { - color: ['#ffffe6','yellow','red'] - - } + inRange: { + color: ['#ffffe6', 'yellow', 'red'] + + } }, series: [ { @@ -147,58 +160,58 @@ class band_activity extends plot_base { } ] }); - }); + }); } /** - * Chart creator - * - * @constructor - * @param {String} chart_id The HTML id where place chart - * @param {string} end_point This is backend end-point for chart datas - * @param {integer} refresh_time Time to refesh chart - * @param {Json} cont_cq The continent list( EU, SA, ...) - * @param {Json} band_freq The frequency band list (160, 80, 60... UHF, SHF) - */ - constructor(chart_id, end_point, cont_cq, band_freq) { - super(chart_id,end_point); + * Chart creator + * + * @constructor + * @param {String} chart_id The HTML id where place chart + * @param {string} end_point This is backend end-point for chart datas + * @param {integer} refresh_time Time to refesh chart + * @param {Json} cont_cq The continent list( EU, SA, ...) + * @param {Json} band_freq The frequency band list (160, 80, 60... UHF, SHF) + */ + constructor(chart_id, end_point, cont_cq, band_freq) { + super(chart_id, end_point); //populate continents array - let continents=[]; + let continents = []; cont_cq.forEach(function myFunction(item, index) { - continents[index]=item['id']; + continents[index] = item['id']; }); - this.continents=continents; + this.continents = continents; //populate bands array - let bands=[]; + let bands = []; band_freq.forEach(function myFunction(item, index) { - bands[index]=item['id']; + bands[index] = item['id']; }); - this.bands=bands; + this.bands = bands; //managing region - var selectedContinent=getCookie('user_region'); - var selectedContinent_desc=getCookie('user_region_desc'); + var selectedContinent = getCookie('user_region'); + var selectedContinent_desc = getCookie('user_region_desc'); if (!selectedContinent) { - selectedContinent='EU'; - selectedContinent_desc='Europe'; - setCookie('user_region',selectedContinent,60); - setCookie('user_region_desc',selectedContinent_desc,60); + selectedContinent = 'EU'; + selectedContinent_desc = 'Europe'; + setCookie('user_region', selectedContinent, 60); + setCookie('user_region_desc', selectedContinent_desc, 60); } selectElement('continentInput', selectedContinent); - - addEventHandler(document.getElementById('continentInput'), 'change', function() { - selectedContinent=this.value; - selectedContinent_desc=this.options[this.selectedIndex].text; - setCookie('user_region',selectedContinent,60); - setCookie('user_region_desc',selectedContinent_desc,60); + + addEventHandler(document.getElementById('continentInput'), 'change', function () { + selectedContinent = this.value; + selectedContinent_desc = this.options[this.selectedIndex].text; + setCookie('user_region', selectedContinent, 60); + setCookie('user_region_desc', selectedContinent_desc, 60); plot_ba.refresh(selectedContinent); - setText('txt_continent','\xa0 Based on DX SPOTS from stations in '+ selectedContinent_desc +' during the last 15 minutes, displayed by Continent and Band'); + setText('txt_continent', '\xa0 Based on DX SPOTS from stations in ' + selectedContinent_desc + ' during the last 15 minutes, displayed by Continent and Band'); }); - setText('txt_continent','\xa0 Based on DX SPOTS from stations in '+ selectedContinent_desc +' during the last 15 minutes, displayed by Continent and Band'); + setText('txt_continent', '\xa0 Based on DX SPOTS from stations in ' + selectedContinent_desc + ' during the last 15 minutes, displayed by Continent and Band'); this.refresh(selectedContinent); } @@ -210,7 +223,7 @@ class band_activity extends plot_base { * ******************************************************************************/ class world_dx_spots_live extends plot_base { - + /** * refresh and populate chart * @@ -219,23 +232,32 @@ class world_dx_spots_live extends plot_base { super.refresh(); console.log('refresh world_dx_spots_live'); // Asynchronous Data Loading - fetch(this.end_point) - .then((response) => response.json()) - .then((data) => { + + fetch(this.end_point, { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }) + + .then((response) => response.json()) + .then((data) => { fetch('world.json') .then(response => response.text()) .then(geoJson => { - var last_refresh=get_last_refresh(data); - var dataMap=[]; + var last_refresh = get_last_refresh(data); + var dataMap = []; data['world_dx_spots_live'].forEach(function myFunction(item, index) { //lon, lat, number of qso - dataMap.push({'value':[item['lat'],item['lon'],item['count']]}); + dataMap.push({ 'value': [item['lat'], item['lon'], item['count']] }); }); this.myChart.hideLoading(); - echarts.registerMap('WR', geoJson); - - this.myChart.setOption( { + echarts.registerMap('WR', geoJson); + + this.myChart.setOption({ visualMap: { show: false, @@ -243,7 +265,7 @@ class world_dx_spots_live extends plot_base { max: 30, inRange: { symbolSize: [5, 20] - } + } }, geo: { @@ -261,36 +283,36 @@ class world_dx_spots_live extends plot_base { }, emphasis: { areaColor: '#3ba272' //3ba272 91cc75 - } + } }, label: { emphasis: { show: false } - }, + }, }, tooltip: { trigger: 'item', - formatter: function(val) { - var out='Spots: '+ val.value[2] +''; + formatter: function (val) { + var out = 'Spots: ' + val.value[2] + ''; return out; } - + }, - + toolbox: { show: true, showTitle: false, orient: 'vertical', left: 'right', - top: 'center', + top: 'center', feature: { mark: { show: true }, dataView: { show: true, readOnly: false }, restore: { show: true }, saveAsImage: { show: true } } - }, + }, legend: { show: false }, @@ -298,13 +320,13 @@ class world_dx_spots_live extends plot_base { text: 'World DX SPOTS in last hour', subtext: last_refresh, top: 'top', - right:'right', - }, - series: [ + right: 'right', + }, + series: [ { - type: 'scatter', - coordinateSystem: 'geo', - data:dataMap, + type: 'scatter', + coordinateSystem: 'geo', + data: dataMap, label: { emphasis: { position: 'right', @@ -316,20 +338,20 @@ class world_dx_spots_live extends plot_base { color: '#fc8452', borderColor: '#fa0a0a', } - }, + }, /* - symbolSize: function (val) { - return val[2] / 4; - }, - */ + symbolSize: function (val) { + return val[2] / 4; + }, + */ } - ] - + ] + }); //end options - } - ); - }); + } + ); + }); } /** * Chart creator @@ -337,9 +359,9 @@ class world_dx_spots_live extends plot_base { * @constructor * @param {String} chart_id The HTML id where place chart * @param {string} end_point This is backend end-point for chart datas - */ - constructor(chart_id, end_point) { - super(chart_id,end_point); + */ + constructor(chart_id, end_point) { + super(chart_id, end_point); this.refresh(); } @@ -350,7 +372,7 @@ class world_dx_spots_live extends plot_base { * ******************************************************************************/ class hour_band extends plot_base { - + /** * refresh and populate chart * @@ -360,39 +382,47 @@ class hour_band extends plot_base { // Asynchronous Data Loading super.refresh(); - console.log ('refresh hour_band'); - fetch(this.end_point) - .then((response) => response.json()) - .then((data) => { + console.log('refresh hour_band'); + + fetch(this.end_point, { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }) + .then((response) => response.json()) + .then((data) => { // Fill in the dat - var last_refresh=get_last_refresh(data); + var last_refresh = get_last_refresh(data); //set hour indicator names - var hour_indicators=[]; + var hour_indicators = []; for (let i = 23; i > -1; i--) { - var hour_name={}; - var s=i.toString(); - hour_name['name']=s; + var hour_name = {}; + var s = i.toString(); + hour_name['name'] = s; hour_indicators.push(hour_name); } //cycling whithin each bands and hours - var dataMap=[]; + var dataMap = []; this.bands.forEach(band_item => { - var qso=[]; - - for (let i = 23; i > -1; i--) { + var qso = []; + + for (let i = 23; i > -1; i--) { try { - var value=data['hour_band'][band_item][i]; + var value = data['hour_band'][band_item][i]; if (typeof value == 'undefined') { value = 0; - } + } qso.push(value); } catch (TypeError) { //TODO } - } - var tot={'value':qso,'name':band_item}; + } + var tot = { 'value': qso, 'name': band_item }; dataMap.push(tot); }); @@ -400,17 +430,17 @@ class hour_band extends plot_base { //options this.myChart.setOption({ legend: { - + orient: 'horizontal', left: 'left', - bottom: 'bottom' + bottom: 'bottom' }, title: { text: 'DX SPOTS per hour in last month', subtext: last_refresh, top: 'top', right: 'right', - }, + }, tooltip: { trigger: 'axis', }, @@ -419,23 +449,23 @@ class hour_band extends plot_base { showTitle: false, orient: 'vertical', left: 'right', - top: 'center', + top: 'center', feature: { mark: { show: true }, dataView: { show: true, readOnly: true }, restore: { show: true }, saveAsImage: { show: true } } - }, + }, radar: { - shape: 'circle', + shape: 'circle', //startAngle: 285, //0 on left side startAngle: 105, //0 on top indicator: hour_indicators, center: ['47%', '46%'], axisName: { color: 'rgb(80,80,80)', - }, + }, }, series: [ { @@ -443,25 +473,25 @@ class hour_band extends plot_base { width: 2 }, type: 'radar', - symbol: 'none', + symbol: 'none', data: dataMap, tooltip: { trigger: 'item', formatter: (params) => { - return 'Band: '+params.name; - }, - }, + return 'Band: ' + params.name; + }, + }, emphasis: { lineStyle: { width: 4 } - }, + }, } ] }); }); } - + /** * Chart creator @@ -470,15 +500,15 @@ class hour_band extends plot_base { * @param {String} chart_id The HTML id where place chart * @param {string} end_point This is backend end-point for chart datas * @param {Json} band_freq The frequency band list (160, 80, 60... UHF, SHF) - */ - constructor(chart_id,end_point,band_freq) { + */ + constructor(chart_id, end_point, band_freq) { // Initialize the echarts instance based on the prepared dom - super(chart_id,end_point); + super(chart_id, end_point); //populate bands array - let lcl_bands=[]; + let lcl_bands = []; band_freq.forEach(function myFunction(item, index) { - lcl_bands[index]=item['id']; + lcl_bands[index] = item['id']; }); this.bands = lcl_bands; this.refresh(); @@ -491,22 +521,30 @@ class hour_band extends plot_base { * javascript used to build dx spots per month chart * ******************************************************************************/ -class dx_spots_per_month extends plot_base { - +class dx_spots_per_month extends plot_base { + /** - * refresh and populate chart - */ + * refresh and populate chart + */ refresh() { console.log('refresh dx_spots_per_month'); // Asynchronous Data Loading //$.getJSON(end_point).done(function(data) { - fetch(this.end_point) - .then((response) => response.json()) - .then((data) => { + + fetch(this.end_point, { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }) + .then((response) => response.json()) + .then((data) => { // Fill in the data - var last_refresh=get_last_refresh(data); + var last_refresh = get_last_refresh(data); var year_now = new Date().getFullYear(); var year_0 = (year_now - 0).toString(); var year_1 = (year_now - 1).toString(); @@ -514,14 +552,14 @@ class dx_spots_per_month extends plot_base { var months_name = get_months_names(); - var dataMap_year_0=[]; - var dataMap_year_1=[]; - var dataMap_year_2=[]; + var dataMap_year_0 = []; + var dataMap_year_1 = []; + var dataMap_year_2 = []; for (let i = 1; i < 13; i++) { dataMap_year_0.push(data.spots_per_month[i].year_0); dataMap_year_1.push(data.spots_per_month[i].year_1); dataMap_year_2.push(data.spots_per_month[i].year_2); - } + } //options this.myChart.setOption({ @@ -535,11 +573,11 @@ class dx_spots_per_month extends plot_base { text: 'DX SPOTS per month', subtext: last_refresh, top: 'top', - left:'left' - }, + left: 'left' + }, legend: { data: [year_2, year_1, year_0], - bottom: 'bottom' + bottom: 'bottom' }, toolbox: { show: true, @@ -566,7 +604,7 @@ class dx_spots_per_month extends plot_base { { type: 'value', axisLabel: { - formatter: (function (value){ + formatter: (function (value) { return format_u_k_m(value); }) } @@ -589,7 +627,7 @@ class dx_spots_per_month extends plot_base { focus: 'series' }, data: dataMap_year_1 - + }, { name: year_0, @@ -597,9 +635,9 @@ class dx_spots_per_month extends plot_base { emphasis: { focus: 'series' }, - data: dataMap_year_0 + data: dataMap_year_0 }, - ] + ] }); }); } @@ -610,9 +648,9 @@ class dx_spots_per_month extends plot_base { * @constructor * @param {String} chart_id The HTML id where place chart * @param {string} end_point This is backend end-point for chart datas - */ - constructor(chart_id, end_point) { - super(chart_id,end_point); + */ + constructor(chart_id, end_point) { + super(chart_id, end_point); this.refresh(); } } @@ -622,27 +660,34 @@ class dx_spots_per_month extends plot_base { * ******************************************************************************/ class dx_spots_trend extends plot_base { - + /** - * refresh and populate chart - */ + * refresh and populate chart + */ refresh() { - console.log('refresh dx_spots_trend'); + console.log('refresh dx_spots_trend'); // Asynchronous Data Loading - fetch(this.end_point) - .then((response) => response.json()) - .then((data) => { + fetch(this.end_point, { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + } + }) + .then((response) => response.json()) + .then((data) => { // Fill in the data - var last_refresh=get_last_refresh(data); - var dataMap=[]; + var last_refresh = get_last_refresh(data); + var dataMap = []; for (const [key, value] of Object.entries(data['spots_trend'])) { - var tuple=[]; + var tuple = []; tuple.push(key); tuple.push(value); dataMap.push(tuple); - } + } //options this.myChart.setOption({ tooltip: { @@ -655,22 +700,22 @@ class dx_spots_trend extends plot_base { text: 'DX SPOTS trend', subtext: last_refresh, top: 'top', - left:'left' + left: 'left' }, toolbox: { show: true, showTitle: false, orient: 'vertical', left: 'right', - top: 'center', + top: 'center', feature: { dataView: { show: true, readOnly: false }, dataZoom: { yAxisIndex: 'none' - }, + }, restore: {}, - magicType: { show: true, type: ['line', 'bar'] }, - saveAsImage: {}, + magicType: { show: true, type: ['line', 'bar'] }, + saveAsImage: {}, } }, xAxis: { @@ -681,10 +726,10 @@ class dx_spots_trend extends plot_base { type: 'value', boundaryGap: [0, '10%'], axisLabel: { - formatter: (function (value){ + formatter: (function (value) { return format_u_k_m(value); }) - } + } }, dataZoom: [ { @@ -706,53 +751,54 @@ class dx_spots_trend extends plot_base { symbol: 'none', itemStyle: { color: '#078513' - }, + }, areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, - color: '#57fa75' + color: '#57fa75' }, { offset: 1, - color: '#118226' + color: '#118226' } ]) }, data: dataMap } - ] - + ] + }); }); } - + /** - * Chart creator - * - * @constructor - * @param {String} chart_id The HTML id where place chart - * @param {string} end_point This is backend end-point for chart datas - */ - constructor(chart_id,end_point) { + * Chart creator + * + * @constructor + * @param {String} chart_id The HTML id where place chart + * @param {string} end_point This is backend end-point for chart datas + */ + constructor(chart_id, end_point) { // Initialize the echarts instance based on the prepared dom - super(chart_id,end_point); + super(chart_id, end_point); this.refresh(); } } //create objects and timing -var plot_ba = new band_activity ('chart-band_activity','/plot_get_heatmap_data', continents_cq,band_frequencies); -setInterval(function(){plot_ba.refresh();},5*60*1000); -var plot_wdsl = new world_dx_spots_live ('chart-world_dx_spots_live','/plot_get_world_dx_spots_live'); -setInterval(function(){plot_wdsl.refresh();},5*60*1000); +var plot_ba = new band_activity('chart-band_activity', '/plot_get_heatmap_data', continents_cq, band_frequencies); +setInterval(function () { plot_ba.refresh(); }, 5 * 60 * 1000); -var plot_hb = new hour_band('chart-hour_band','/plot_get_hour_band',band_frequencies); -setInterval(function(){plot_hb.refresh();},1*60*60*1000); +var plot_wdsl = new world_dx_spots_live('chart-world_dx_spots_live', '/plot_get_world_dx_spots_live'); +setInterval(function () { plot_wdsl.refresh(); }, 5 * 60 * 1000); -var plot_dspm = new dx_spots_per_month ('chart-dx_spots_x_month','/plot_get_dx_spots_per_month'); -setInterval(function(){plot_dspm.refresh();},12*60*60*1000); +var plot_hb = new hour_band('chart-hour_band', '/plot_get_hour_band', band_frequencies); +setInterval(function () { plot_hb.refresh(); }, 1 * 60 * 60 * 1000); -var plot_dst = new dx_spots_trend ('chart-dx_spots_trend','/plot_get_dx_spots_trend'); -setInterval(function(){plot_dst.refresh();},12*60*60*1000); \ No newline at end of file +var plot_dspm = new dx_spots_per_month('chart-dx_spots_x_month', '/plot_get_dx_spots_per_month'); +setInterval(function () { plot_dspm.refresh(); }, 12 * 60 * 60 * 1000); + +var plot_dst = new dx_spots_trend('chart-dx_spots_trend', '/plot_get_dx_spots_trend'); +setInterval(function () { plot_dst.refresh(); }, 12 * 60 * 60 * 1000); \ No newline at end of file diff --git a/static/js/dev/table.js b/static/js/dev/table.js index 38aae64..26cf264 100644 --- a/static/js/dev/table.js +++ b/static/js/dev/table.js @@ -164,7 +164,7 @@ class table_builder { const td_comm = document.createElement('td'); td_comm.className = 'd-none d-lg-table-cell d-xl-table-cell'; try { - td_comm.textContent = line.comm.substring(0,100); + td_comm.textContent = line.comm.substring(0, 100); } catch (err) { td_comm.textContent = ''; } @@ -245,7 +245,7 @@ class table_builder { return new bootstrap.Popover(popoverTriggerEl); }); - this.first_time=false; + this.first_time = false; } } } //end class @@ -257,7 +257,7 @@ class table_builder { const adxo_url = 'https://www.ng3k.com/misc/adxo.html'; const qrz_url = 'https://www.qrz.com/db/'; const tb = new table_builder('bodyspot'); -var qryAll_sv = ''; +var params_sv = {}; /** * Decode Announced Dx Operation (ng3k) @@ -287,38 +287,42 @@ function mySearch(event) { * Function for construct query string for single value selection * * @param id {string} The html identifier used for filter - * @param param {string}the parameter for the query * @param len {number} The maximum number of element that could be selected; use -1 if the filter permits a single selection - * @param qrystr {string} Th initial query string to be completed with the new filter + * @param qry_json {object} The input json */ -function getFilter(id, param, len, qrystr) { +function compose_filter(id, len, qry_json) { try { let selectedFilter = [].map.call(document.getElementById(id).selectedOptions, option => option.value); - let qryFilter = ''; - if (selectedFilter.length < len || len == -1) { - qryFilter = selectedFilter.map(function (el) { + if (selectedFilter.length < len) { + qry_json[id] = []; + selectedFilter.map(function (el) { if (el) { - return param + '=' + el; + qry_json[id].push(el); } else { return ''; } - }).join('&'); - qrystr = qrystr.concat('&'.concat(qryFilter)); - if (qrystr.substring(0, 1) == '&') { - qrystr = qrystr.substring(1); - } - } + }); + } else if (len == -1) { + selectedFilter.map(function (el) { + if (el) { + qry_json[id]=el; + } else { + return ''; + } + }); + } } catch (err) { - if (err.name == 'TypeError') { - /* error managed: it is ok: probabilly ther is no filter on cq region */ + if (err.name == 'TypeError') { + console.error(err.name); + /* error managed: it is ok: probabilly ther is no filter on cq region */ } else { throw err; } - } + } - return qrystr; + return qry_json; } /** @@ -328,34 +332,36 @@ function getFilter(id, param, len, qrystr) { */ function refresh_timer() { - let qryAll = ''; + let params = {}; //get other filters - qryAll = getFilter('band', 'b', 14, qryAll); - qryAll = getFilter('de_re', 'e', 7, qryAll); - qryAll = getFilter('dx_re', 'x', 7, qryAll); - qryAll = getFilter('mode', 'm', 3, qryAll); - qryAll = getFilter('cqdeInput', 'qe', -1, qryAll); - qryAll = getFilter('cqdxInput', 'qx', -1, qryAll); + params = compose_filter('band', 14, params); + params = compose_filter('de_re', 7, params); + params = compose_filter('dx_re', 7, params); + params = compose_filter('mode', 3, params); + params = compose_filter('cqdeInput', -1, params); + params = compose_filter('cqdxInput', -1, params); - //Composing query string - let qryString; + delete params_sv['lr']; //remove line row number, for future param comparison //If the filter is changed we need to reset the data table and restart from rowid=0 - if (qryAll != qryAll_sv) { + if (JSON.stringify(params) !== JSON.stringify(params_sv)) { tb.resetData(); - qryAll_sv = qryAll; + params_sv = params; } - - qryString = ('spotlist?lr=').concat(tb.getLastRowId()); - - if (qryAll) { - qryString = qryString.concat('&'.concat(qryAll)); - } - - + params['lr']=tb.getLastRowId(); + //Open a new connection, using the GET request on the URL endpoint - fetch(qryString) + //let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content"); + fetch('spotlist', { + method: 'POST', + cache: 'no-cache', + credentials: 'same-origin', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify( params ) + }) .then((response) => response.json()) .then((data_new) => { try { diff --git a/static/js/rel/callsign_inline.min.js b/static/js/rel/callsign_inline.min.js index c77e22c..1a78c28 100644 --- a/static/js/rel/callsign_inline.min.js +++ b/static/js/rel/callsign_inline.min.js @@ -1 +1 @@ -var my_adxo_events=JSON.parse(my_adxo_events_json.replaceAll("\t","")),qryString="spotlist?c="+callsign;fetch(qryString).then(l=>l.json()).then(o=>{try{tb.build(o,callsign)}catch(l){console.log(l),console.log(l.stack),console.log(o)}}); +var my_adxo_events=JSON.parse(my_adxo_events_json.replaceAll("\t",""));let params={};params.callsign=callsign,fetch("spotlist",{method:"POST",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify(params)}).then(e=>e.json()).then(a=>{try{tb.build(a,callsign)}catch(e){console.log(e),console.log(e.stack),console.log(a)}}); diff --git a/static/js/rel/callsign_search.min.js b/static/js/rel/callsign_search.min.js index ac7e94f..cab9a5b 100644 --- a/static/js/rel/callsign_search.min.js +++ b/static/js/rel/callsign_search.min.js @@ -1 +1 @@ -function myCallsignSearch(e){e.preventDefault(),0<(callsign=document.getElementById("callsignInput").value).replace(/\s/g,"").length&&(location.href="/callsign.html?c=".concat(callsign.trim().toUpperCase()),console.log(location.href))}document.getElementById("form-callsign").addEventListener("submit",myCallsignSearch); +function myCallsignSearch(e){e.preventDefault(),0<(callsign=document.getElementById("callsignInput").value).replace(/\s/g,"").length&&(location.href="/callsign.html?c=".concat(callsign.trim().toUpperCase()))}document.getElementById("form-callsign").addEventListener("submit",myCallsignSearch); diff --git a/static/js/rel/plot.min.js b/static/js/rel/plot.min.js index b783cc5..565a948 100644 --- a/static/js/rel/plot.min.js +++ b/static/js/rel/plot.min.js @@ -1 +1 @@ -class plot_base{refresh(){}constructor(t,e){var o=document.getElementById(t);this.end_point=e,this.myChart=echarts.init(o);let s=echarts.init(document.querySelector("#"+t),null);window.addEventListener("resize",function(){s.resize()})}}class band_activity extends plot_base{refresh(t){super.refresh(),console.log("refresh band_activity"),void 0!==t&&(this.selectedContinent=t),fetch(this.end_point+"?continent="+this.selectedContinent).then(t=>t.json()).then(t=>{var e=get_last_refresh(t),t=Array.from(t["band activity"]).map(function(t){return[t[1],t[0],t[2]||"-"]});this.myChart.setOption({tooltip:{position:"top",formatter:function(t){return t.seriesName+" on "+t.name+" band: "+t.data[2]+""}},title:{text:"Band activity",subtext:e,top:"top",left:"left"},toolbox:{show:!0,showTitle:!1,orient:"vertical",right:"right",top:"bottom",feature:{mark:{show:!0},dataView:{show:!0,readOnly:!0},restore:{show:!0},saveAsImage:{show:!0}}},grid:{height:"80%",left:25,top:50,right:60,bottom:0,show:!0,backgroundColor:"rgb(255, 255, 255)"},xAxis:{type:"category",data:this.bands,axisTick:{show:!0},axisLine:{show:!1},splitArea:{show:!0}},yAxis:{type:"category",data:this.continents,axisTick:{show:!0},axisLine:{show:!1},splitArea:{show:!0}},visualMap:{calculable:!0,orient:"vertical",right:"right",top:"center",min:0,max:30,inRange:{color:["#ffffe6","yellow","red"]}},series:[{name:"Spots",type:"heatmap",data:t,label:{show:!1},emphasis:{itemStyle:{shadowBlur:10,shadowColor:"rgba(100, 0, 0, 0.5)"}}}]})})}constructor(t,e,o,s){super(t,e);let r=[],a=(o.forEach(function(t,e){r[e]=t.id}),this.continents=r,[]);s.forEach(function(t,e){a[e]=t.id}),this.bands=a;var n=getCookie("user_region"),i=getCookie("user_region_desc");n||(n="EU",i="Europe",setCookie("user_region",n,60),setCookie("user_region_desc",i,60)),selectElement("continentInput",n),addEventHandler(document.getElementById("continentInput"),"change",function(){n=this.value,i=this.options[this.selectedIndex].text,setCookie("user_region",n,60),setCookie("user_region_desc",i,60),plot_ba.refresh(n),setText("txt_continent","  Based on DX SPOTS from stations in "+i+" during the last 15 minutes, displayed by Continent and Band")}),setText("txt_continent","  Based on DX SPOTS from stations in "+i+" during the last 15 minutes, displayed by Continent and Band"),this.refresh(n)}}class world_dx_spots_live extends plot_base{refresh(){super.refresh(),console.log("refresh world_dx_spots_live"),fetch(this.end_point).then(t=>t.json()).then(s=>{fetch("world.json").then(t=>t.text()).then(t=>{var e=get_last_refresh(s),o=[];s.world_dx_spots_live.forEach(function(t,e){o.push({value:[t.lat,t.lon,t.count]})}),this.myChart.hideLoading(),echarts.registerMap("WR",t),this.myChart.setOption({visualMap:{show:!1,min:0,max:30,inRange:{symbolSize:[5,20]}},geo:{type:"map",map:"WR",roam:!0,zoom:1.2,aspectScale:1,layoutCenter:["50%","54%"],layoutSize:"100%",itemStyle:{normal:{areaColor:"#91cc75",borderColor:"#111"},emphasis:{areaColor:"#3ba272"}},label:{emphasis:{show:!1}}},tooltip:{trigger:"item",formatter:function(t){return"Spots: "+t.value[2]+""}},toolbox:{show:!0,showTitle:!1,orient:"vertical",left:"right",top:"center",feature:{mark:{show:!0},dataView:{show:!0,readOnly:!1},restore:{show:!0},saveAsImage:{show:!0}}},legend:{show:!1},title:{text:"World DX SPOTS in last hour",subtext:e,top:"top",right:"right"},series:[{type:"scatter",coordinateSystem:"geo",data:o,label:{emphasis:{position:"right",show:!1}},itemStyle:{normal:{color:"#fc8452",borderColor:"#fa0a0a"}}}]})})})}constructor(t,e){super(t,e),this.refresh()}}class hour_band extends plot_base{refresh(){super.refresh(),console.log("refresh hour_band"),fetch(this.end_point).then(t=>t.json()).then(r=>{var t=get_last_refresh(r),e=[];for(let t=23;-1{var o=[];for(let t=23;-1"Band: "+t.name},emphasis:{lineStyle:{width:4}}}]})})}constructor(t,e,o){super(t,e);let s=[];o.forEach(function(t,e){s[e]=t.id}),this.bands=s,this.refresh()}}class dx_spots_per_month extends plot_base{refresh(){console.log("refresh dx_spots_per_month"),fetch(this.end_point).then(t=>t.json()).then(e=>{var t=get_last_refresh(e),o=(new Date).getFullYear(),s=(+o).toString(),r=(o-1).toString(),o=(o-2).toString(),a=get_months_names(),n=[],i=[],h=[];for(let t=1;t<13;t++)n.push(e.spots_per_month[t].year_0),i.push(e.spots_per_month[t].year_1),h.push(e.spots_per_month[t].year_2);this.myChart.setOption({tooltip:{trigger:"axis",axisPointer:{type:"shadow"}},title:{text:"DX SPOTS per month",subtext:t,top:"top",left:"left"},legend:{data:[o,r,s],bottom:"bottom"},toolbox:{show:!0,showTitle:!1,orient:"vertical",left:"right",top:"center",feature:{mark:{show:!0},dataView:{show:!0,readOnly:!1},magicType:{show:!0,type:["line","bar","stack"]},restore:{show:!0},saveAsImage:{show:!0}}},xAxis:[{type:"category",axisTick:{show:!1},data:a}],yAxis:[{type:"value",axisLabel:{formatter:function(t){return format_u_k_m(t)}}}],series:[{name:o,type:"bar",barGap:0,emphasis:{focus:"series"},data:h},{name:r,type:"bar",emphasis:{focus:"series"},data:i},{name:s,type:"bar",emphasis:{focus:"series"},data:n}]})})}constructor(t,e){super(t,e),this.refresh()}}class dx_spots_trend extends plot_base{refresh(){console.log("refresh dx_spots_trend"),fetch(this.end_point).then(t=>t.json()).then(t=>{var e,o,s=get_last_refresh(t),r=[];for([e,o]of Object.entries(t.spots_trend)){var a=[];a.push(e),a.push(o),r.push(a)}this.myChart.setOption({tooltip:{trigger:"axis",position:function(t){return[t[0],"10%"]}},title:{text:"DX SPOTS trend",subtext:s,top:"top",left:"left"},toolbox:{show:!0,showTitle:!1,orient:"vertical",left:"right",top:"center",feature:{dataView:{show:!0,readOnly:!1},dataZoom:{yAxisIndex:"none"},restore:{},magicType:{show:!0,type:["line","bar"]},saveAsImage:{}}},xAxis:{type:"time",boundaryGap:!1},yAxis:{type:"value",boundaryGap:[0,"10%"],axisLabel:{formatter:function(t){return format_u_k_m(t)}}},dataZoom:[{type:"inside",start:65,end:100},{start:0,end:20}],series:[{name:"Spots",type:"line",smooth:!0,symbol:"none",itemStyle:{color:"#078513"},areaStyle:{color:new echarts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:"#57fa75"},{offset:1,color:"#118226"}])},data:r}]})})}constructor(t,e){super(t,e),this.refresh()}}var plot_ba=new band_activity("chart-band_activity","/plot_get_heatmap_data",continents_cq,band_frequencies),plot_wdsl=(setInterval(function(){plot_ba.refresh()},3e5),new world_dx_spots_live("chart-world_dx_spots_live","/plot_get_world_dx_spots_live")),plot_hb=(setInterval(function(){plot_wdsl.refresh()},3e5),new hour_band("chart-hour_band","/plot_get_hour_band",band_frequencies)),plot_dspm=(setInterval(function(){plot_hb.refresh()},36e5),new dx_spots_per_month("chart-dx_spots_x_month","/plot_get_dx_spots_per_month")),plot_dst=(setInterval(function(){plot_dspm.refresh()},432e5),new dx_spots_trend("chart-dx_spots_trend","/plot_get_dx_spots_trend"));setInterval(function(){plot_dst.refresh()},432e5); +class plot_base{refresh(){}constructor(e,t){var o=document.getElementById(e);this.end_point=t,this.myChart=echarts.init(o);let s=echarts.init(document.querySelector("#"+e),null);window.addEventListener("resize",function(){s.resize()})}}class band_activity extends plot_base{refresh(e){super.refresh(),console.log("refresh band_activity"),void 0!==e&&(this.selectedContinent=e);e={continent:this.selectedContinent};fetch(this.end_point,{method:"POST",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).then(e=>e.json()).then(e=>{var t=get_last_refresh(e),e=Array.from(e["band activity"]).map(function(e){return[e[1],e[0],e[2]||"-"]});this.myChart.setOption({tooltip:{position:"top",formatter:function(e){return e.seriesName+" on "+e.name+" band: "+e.data[2]+""}},title:{text:"Band activity",subtext:t,top:"top",left:"left"},toolbox:{show:!0,showTitle:!1,orient:"vertical",right:"right",top:"bottom",feature:{mark:{show:!0},dataView:{show:!0,readOnly:!0},restore:{show:!0},saveAsImage:{show:!0}}},grid:{height:"80%",left:25,top:50,right:60,bottom:0,show:!0,backgroundColor:"rgb(255, 255, 255)"},xAxis:{type:"category",data:this.bands,axisTick:{show:!0},axisLine:{show:!1},splitArea:{show:!0}},yAxis:{type:"category",data:this.continents,axisTick:{show:!0},axisLine:{show:!1},splitArea:{show:!0}},visualMap:{calculable:!0,orient:"vertical",right:"right",top:"center",min:0,max:30,inRange:{color:["#ffffe6","yellow","red"]}},series:[{name:"Spots",type:"heatmap",data:e,label:{show:!1},emphasis:{itemStyle:{shadowBlur:10,shadowColor:"rgba(100, 0, 0, 0.5)"}}}]})})}constructor(e,t,o,s){super(e,t);let r=[],a=(o.forEach(function(e,t){r[t]=e.id}),this.continents=r,[]);s.forEach(function(e,t){a[t]=e.id}),this.bands=a;var n=getCookie("user_region"),i=getCookie("user_region_desc");n||(n="EU",i="Europe",setCookie("user_region",n,60),setCookie("user_region_desc",i,60)),selectElement("continentInput",n),addEventHandler(document.getElementById("continentInput"),"change",function(){n=this.value,i=this.options[this.selectedIndex].text,setCookie("user_region",n,60),setCookie("user_region_desc",i,60),plot_ba.refresh(n),setText("txt_continent","  Based on DX SPOTS from stations in "+i+" during the last 15 minutes, displayed by Continent and Band")}),setText("txt_continent","  Based on DX SPOTS from stations in "+i+" during the last 15 minutes, displayed by Continent and Band"),this.refresh(n)}}class world_dx_spots_live extends plot_base{refresh(){super.refresh(),console.log("refresh world_dx_spots_live"),fetch(this.end_point,{method:"POST",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"}}).then(e=>e.json()).then(s=>{fetch("world.json").then(e=>e.text()).then(e=>{var t=get_last_refresh(s),o=[];s.world_dx_spots_live.forEach(function(e,t){o.push({value:[e.lat,e.lon,e.count]})}),this.myChart.hideLoading(),echarts.registerMap("WR",e),this.myChart.setOption({visualMap:{show:!1,min:0,max:30,inRange:{symbolSize:[5,20]}},geo:{type:"map",map:"WR",roam:!0,zoom:1.2,aspectScale:1,layoutCenter:["50%","54%"],layoutSize:"100%",itemStyle:{normal:{areaColor:"#91cc75",borderColor:"#111"},emphasis:{areaColor:"#3ba272"}},label:{emphasis:{show:!1}}},tooltip:{trigger:"item",formatter:function(e){return"Spots: "+e.value[2]+""}},toolbox:{show:!0,showTitle:!1,orient:"vertical",left:"right",top:"center",feature:{mark:{show:!0},dataView:{show:!0,readOnly:!1},restore:{show:!0},saveAsImage:{show:!0}}},legend:{show:!1},title:{text:"World DX SPOTS in last hour",subtext:t,top:"top",right:"right"},series:[{type:"scatter",coordinateSystem:"geo",data:o,label:{emphasis:{position:"right",show:!1}},itemStyle:{normal:{color:"#fc8452",borderColor:"#fa0a0a"}}}]})})})}constructor(e,t){super(e,t),this.refresh()}}class hour_band extends plot_base{refresh(){super.refresh(),console.log("refresh hour_band"),fetch(this.end_point,{method:"POST",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"}}).then(e=>e.json()).then(r=>{var e=get_last_refresh(r),t=[];for(let e=23;-1{var o=[];for(let e=23;-1"Band: "+e.name},emphasis:{lineStyle:{width:4}}}]})})}constructor(e,t,o){super(e,t);let s=[];o.forEach(function(e,t){s[t]=e.id}),this.bands=s,this.refresh()}}class dx_spots_per_month extends plot_base{refresh(){console.log("refresh dx_spots_per_month"),fetch(this.end_point,{method:"POST",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"}}).then(e=>e.json()).then(t=>{var e=get_last_refresh(t),o=(new Date).getFullYear(),s=(+o).toString(),r=(o-1).toString(),o=(o-2).toString(),a=get_months_names(),n=[],i=[],h=[];for(let e=1;e<13;e++)n.push(t.spots_per_month[e].year_0),i.push(t.spots_per_month[e].year_1),h.push(t.spots_per_month[e].year_2);this.myChart.setOption({tooltip:{trigger:"axis",axisPointer:{type:"shadow"}},title:{text:"DX SPOTS per month",subtext:e,top:"top",left:"left"},legend:{data:[o,r,s],bottom:"bottom"},toolbox:{show:!0,showTitle:!1,orient:"vertical",left:"right",top:"center",feature:{mark:{show:!0},dataView:{show:!0,readOnly:!1},magicType:{show:!0,type:["line","bar","stack"]},restore:{show:!0},saveAsImage:{show:!0}}},xAxis:[{type:"category",axisTick:{show:!1},data:a}],yAxis:[{type:"value",axisLabel:{formatter:function(e){return format_u_k_m(e)}}}],series:[{name:o,type:"bar",barGap:0,emphasis:{focus:"series"},data:h},{name:r,type:"bar",emphasis:{focus:"series"},data:i},{name:s,type:"bar",emphasis:{focus:"series"},data:n}]})})}constructor(e,t){super(e,t),this.refresh()}}class dx_spots_trend extends plot_base{refresh(){console.log("refresh dx_spots_trend"),fetch(this.end_point,{method:"POST",cache:"no-cache",credentials:"same-origin",headers:{"Content-Type":"application/json"}}).then(e=>e.json()).then(e=>{var t,o,s=get_last_refresh(e),r=[];for([t,o]of Object.entries(e.spots_trend)){var a=[];a.push(t),a.push(o),r.push(a)}this.myChart.setOption({tooltip:{trigger:"axis",position:function(e){return[e[0],"10%"]}},title:{text:"DX SPOTS trend",subtext:s,top:"top",left:"left"},toolbox:{show:!0,showTitle:!1,orient:"vertical",left:"right",top:"center",feature:{dataView:{show:!0,readOnly:!1},dataZoom:{yAxisIndex:"none"},restore:{},magicType:{show:!0,type:["line","bar"]},saveAsImage:{}}},xAxis:{type:"time",boundaryGap:!1},yAxis:{type:"value",boundaryGap:[0,"10%"],axisLabel:{formatter:function(e){return format_u_k_m(e)}}},dataZoom:[{type:"inside",start:65,end:100},{start:0,end:20}],series:[{name:"Spots",type:"line",smooth:!0,symbol:"none",itemStyle:{color:"#078513"},areaStyle:{color:new echarts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:"#57fa75"},{offset:1,color:"#118226"}])},data:r}]})})}constructor(e,t){super(e,t),this.refresh()}}var plot_ba=new band_activity("chart-band_activity","/plot_get_heatmap_data",continents_cq,band_frequencies),plot_wdsl=(setInterval(function(){plot_ba.refresh()},3e5),new world_dx_spots_live("chart-world_dx_spots_live","/plot_get_world_dx_spots_live")),plot_hb=(setInterval(function(){plot_wdsl.refresh()},3e5),new hour_band("chart-hour_band","/plot_get_hour_band",band_frequencies)),plot_dspm=(setInterval(function(){plot_hb.refresh()},36e5),new dx_spots_per_month("chart-dx_spots_x_month","/plot_get_dx_spots_per_month")),plot_dst=(setInterval(function(){plot_dspm.refresh()},432e5),new dx_spots_trend("chart-dx_spots_trend","/plot_get_dx_spots_trend"));setInterval(function(){plot_dst.refresh()},432e5); diff --git a/static/js/rel/table.min.js b/static/js/rel/table.min.js index e1a1e69..86ee8a4 100644 --- a/static/js/rel/table.min.js +++ b/static/js/rel/table.min.js @@ -1 +1 @@ -class table_builder{constructor(e){this.selector=e,this.current_data=[],this.first_time=!0}getLastRowId(){let e;return e=null==this.current_data||this.current_data.length<1?0:this.current_data[0].rowid}resetData(){this.current_data=[]}#buildRow(e,t,n,a=""){var r=document.createElement("tr"),t=(0NG3K Website",l=document.createElement("i"),d=(l.className="bi-search",l.role="button",l.ariaLabel=e.dx,document.createElement("a")),c=(d.href=qrz_url+e.dx,d.target="_blank",d.rel="noopener",document.createElement("span")),s=document.createElement("mark"),s=(s.textContent=e.dx,e.dx==a?c.appendChild(s):c.textContent=" "+e.dx,null!=o&&((a=document.createElement("i")).tabIndex=0,a.className="bi-megaphone-fill",a.style="color: cornflowerblue;",a.role="button",a.ariaLabel="dx_operations",a.setAttribute("data-bs-container","body"),a.setAttribute("data-bs-toggle","popover"),a.setAttribute("data-bs-trigger","focus"),a.setAttribute("data-bs-sanitizer","true"),a.setAttribute("data-bs-placement","auto"),a.setAttribute("data-bs-html","true"),a.setAttribute("data-bs-title","Announced DX Op.: "+o.summary),a.setAttribute("data-bs-content",o.description+"data from "+t),c.appendChild(a)),document.createElement("td"));d.appendChild(l),s.appendChild(d),s.append(c),r.appendChild(s);try{var i=document.createElement("span"),u=(i.className="img-flag fi fi-"+e.iso,i.setAttribute("data-bs-container","body"),i.setAttribute("data-bs-toggle","popover"),i.setAttribute("data-bs-trigger","hover"),i.setAttribute("data-bs-placement","left"),i.setAttribute("data-bs-content",e.country),document.createElement("td"));u.appendChild(i),r.appendChild(u)}catch(e){console.log(e),console.log("error creating flag");o=document.createElement("td");r.appendChild(o)}t=document.createElement("td"),t.className="d-none d-lg-table-cell d-xl-table-cell",t.textContent=e.country,r.appendChild(t),a=document.createElement("td");a.className="d-none d-lg-table-cell d-xl-table-cell";try{a.textContent=e.comm.substring(0,100)}catch(e){a.textContent=""}r.appendChild(a);let m=new Date(1e3*e.time),h="00"+m.getUTCHours(),p=(h=h.substring(h.length-2,h.length),"00"+m.getMinutes()),b=(p=p.substring(p.length-2,p.length),"00"+m.getUTCDate()),g=(b=b.substring(b.length-2,b.length),"00"+(Number(m.getUTCMonth())+1));g=g.substring(g.length-2,g.length);l=m.getUTCFullYear(),d=h+":"+p,m=b+"/"+g+"/"+l,c=document.createElement("div"),c.className="d-flex flex-column",s=document.createElement("div");return s.textContent=d,c.appendChild(s),m!=n&&((i=document.createElement("div")).textContent=m,c.appendChild(i)),r.appendChild(c),r}build(n,a){if(null!=n){var r=new Date;let e="00"+r.getUTCDate(),t=(e=e.substring(e.length-2,e.length),"00"+(Number(r.getUTCMonth())+1));t=t.substring(t.length-2,t.length);var r=r.getUTCFullYear(),l=e+"/"+t+"/"+r,d=(document.getElementById(this.selector).replaceChildren(),[]);for(let e=0;ee.value);(l.lengthe.json()).then(t=>{try{tb.build(t)}catch(e){console.log(e),console.log(e.stack),console.log(t)}})} +class table_builder{constructor(e){this.selector=e,this.current_data=[],this.first_time=!0}getLastRowId(){let e;return e=null==this.current_data||this.current_data.length<1?0:this.current_data[0].rowid}resetData(){this.current_data=[]}#buildRow(e,t,n,a=""){var r=document.createElement("tr"),t=(0NG3K Website",l=document.createElement("i"),o=(l.className="bi-search",l.role="button",l.ariaLabel=e.dx,document.createElement("a")),s=(o.href=qrz_url+e.dx,o.target="_blank",o.rel="noopener",document.createElement("span")),i=document.createElement("mark"),i=(i.textContent=e.dx,e.dx==a?s.appendChild(i):s.textContent=" "+e.dx,null!=d&&((a=document.createElement("i")).tabIndex=0,a.className="bi-megaphone-fill",a.style="color: cornflowerblue;",a.role="button",a.ariaLabel="dx_operations",a.setAttribute("data-bs-container","body"),a.setAttribute("data-bs-toggle","popover"),a.setAttribute("data-bs-trigger","focus"),a.setAttribute("data-bs-sanitizer","true"),a.setAttribute("data-bs-placement","auto"),a.setAttribute("data-bs-html","true"),a.setAttribute("data-bs-title","Announced DX Op.: "+d.summary),a.setAttribute("data-bs-content",d.description+"data from "+t),s.appendChild(a)),document.createElement("td"));o.appendChild(l),i.appendChild(o),i.append(s),r.appendChild(i);try{var c=document.createElement("span"),u=(c.className="img-flag fi fi-"+e.iso,c.setAttribute("data-bs-container","body"),c.setAttribute("data-bs-toggle","popover"),c.setAttribute("data-bs-trigger","hover"),c.setAttribute("data-bs-placement","left"),c.setAttribute("data-bs-content",e.country),document.createElement("td"));u.appendChild(c),r.appendChild(u)}catch(e){console.log(e),console.log("error creating flag");d=document.createElement("td");r.appendChild(d)}t=document.createElement("td"),t.className="d-none d-lg-table-cell d-xl-table-cell",t.textContent=e.country,r.appendChild(t),a=document.createElement("td");a.className="d-none d-lg-table-cell d-xl-table-cell";try{a.textContent=e.comm.substring(0,100)}catch(e){a.textContent=""}r.appendChild(a);let m=new Date(1e3*e.time),p="00"+m.getUTCHours(),h=(p=p.substring(p.length-2,p.length),"00"+m.getMinutes()),b=(h=h.substring(h.length-2,h.length),"00"+m.getUTCDate()),g=(b=b.substring(b.length-2,b.length),"00"+(Number(m.getUTCMonth())+1));g=g.substring(g.length-2,g.length);l=m.getUTCFullYear(),o=p+":"+h,m=b+"/"+g+"/"+l,s=document.createElement("div"),s.className="d-flex flex-column",i=document.createElement("div");return i.textContent=o,s.appendChild(i),m!=n&&((c=document.createElement("div")).textContent=m,s.appendChild(c)),r.appendChild(s),r}build(n,a){if(null!=n){var r=new Date;let e="00"+r.getUTCDate(),t=(e=e.substring(e.length-2,e.length),"00"+(Number(r.getUTCMonth())+1));t=t.substring(t.length-2,t.length);var r=r.getUTCFullYear(),l=e+"/"+t+"/"+r,o=(document.getElementById(this.selector).replaceChildren(),[]);for(let e=0;ee.value);a.lengthe.json()).then(t=>{try{tb.build(t)}catch(e){console.log(e),console.log(e.stack),console.log(t)}})} diff --git a/static/pwa/manifest.webmanifest b/static/pwa/manifest.webmanifest index 763ba3f..5bd0e89 100644 --- a/static/pwa/manifest.webmanifest +++ b/static/pwa/manifest.webmanifest @@ -1,5 +1,5 @@ { - "name": "IU1BOW Spiderweb v2.4.2", + "name": "IU1BOW Spiderweb v2.4.4", "description": "DXCluser for ham radio by IU1BOW", "short_name": "Spiderweb", "theme_color": "#f3b221", diff --git a/static/pwa/service-worker.js b/static/pwa/service-worker.js index 1dc0959..1393493 100644 --- a/static/pwa/service-worker.js +++ b/static/pwa/service-worker.js @@ -1,10 +1,10 @@ // Dichiarazione della costante per il nome della cache -const CACHE_NAME = 'pwa-spiderweb_v2.4.2' +const CACHE_NAME = 'pwa-spiderweb_v2.4.4' // Dichiarazione della costante per gli URL da mettere in cache const URLS_TO_CACHE = [ '/static/images/background.webp', - '/static/css/dev/style.css', + '/static/css/rel/style.min.css', '/static/images/icons/favicon.ico', '/static/images/icons/icon-144x144.png', '/static/images/icons/icon-152x152.png', @@ -18,9 +18,9 @@ const URLS_TO_CACHE = [ '/static/images/icons/icon-96x96.png', '/static/images/icons/icon-apple.png', '/static/images/icons/spider_ico_master.svg', - '/static/js/dev/callsign_inline.js', - '/static/js/dev/callsign_search.js', - '/static/js/dev/common.js', + '/static/js/rel/callsign_inline.min.js', + '/static/js/rel/callsign_search.min.js', + '/static/js/rel/common.min.js', '/privacy.html', '/cookies.html', '/offline.html', diff --git a/templates/_base.html b/templates/_base.html index 8cc740a..4e27df9 100644 --- a/templates/_base.html +++ b/templates/_base.html @@ -14,7 +14,7 @@ - + @@ -92,24 +92,24 @@ © Copyleft: IU1BOW - Spiderweb - v2.4.2 + v2.4.4 - + - + {% block app_scripts %} - + {% endblock app_scripts %} {% block inline_scripts %} {% endblock inline_scripts %} @@ -140,7 +140,7 @@ - + {% endif %} {% endblock cookie %} diff --git a/templates/callsign.html b/templates/callsign.html index b9a800b..f0741eb 100644 --- a/templates/callsign.html +++ b/templates/callsign.html @@ -16,5 +16,5 @@ var callsign = '{{callsign}}'; {% endblock app_data %} {% block inline_scripts %} - + {% endblock %} \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 083bd60..9090135 100644 --- a/templates/index.html +++ b/templates/index.html @@ -305,8 +305,8 @@ var band_frequencies={{bands["bands"]|tojson|safe}}; {% endblock app_data %} {% block app_scripts %} {{ super() }} - + {% endblock %} {% block inline_scripts %} - + {% endblock %} \ No newline at end of file diff --git a/templates/plots.html b/templates/plots.html index 3b06e3b..b626e06 100644 --- a/templates/plots.html +++ b/templates/plots.html @@ -89,5 +89,5 @@ var band_frequencies={{bands["bands"]|tojson|safe}}; - + {% endblock app_scripts %} \ No newline at end of file diff --git a/webapp.py b/webapp.py index 515e361..ea39598 100644 --- a/webapp.py +++ b/webapp.py @@ -30,6 +30,7 @@ app.config.update( inline_script_nonce = "" csrf = CSRFProtect(app) + logger.debug(app.config) if app.config["DEBUG"]: @@ -94,17 +95,24 @@ def query_build_callsign(callsign): return query_string -def query_build(): +def query_build(parameters): try: - # get url parameters - last_rowid = request.args.get("lr") # Last rowid fetched by front end - band = request.args.getlist("b") # band filter - dere = request.args.getlist("e") # DE continent filter - dxre = request.args.getlist("x") # Dx continent filter - mode = request.args.getlist("m") # mode filter - decq = request.args.getlist("qe") # DE cq zone filter - dxcq = request.args.getlist("qx") # DX cq zone filter + last_rowid = str(parameters["lr"]) # Last rowid fetched by front end + + get_param = lambda parameters, parm_name: parameters[parm_name] if (parm_name in parameters) else [] + band=get_param(parameters, "band") + dere=get_param(parameters, "de_re") + dxre=get_param(parameters, "dx_re") + mode=get_param(parameters, "mode") + + decq = [] + if "cqdeInput" in parameters: + decq[0] = parameters["cqdeInput"] + + dxcq = [] + if "cqdxInput" in parameters: + dxcq[0] = parameters["cqdxInput"] query_string = "" @@ -120,7 +128,6 @@ def query_build(): ) band_qry_string += "))" - # construct mode query mode_qry_string = " AND ((" for i, item_mode in enumerate(mode): @@ -138,7 +145,6 @@ def query_build(): ) mode_qry_string += "))" - # construct DE continent region query dere_qry_string = " AND spottercq IN (" for i, item_dere in enumerate(dere): @@ -179,6 +185,7 @@ def query_build(): + last_rowid ) + if len(band) > 0: query_string += band_qry_string @@ -210,15 +217,15 @@ def query_build(): # the main query to show spots # it gets url parameter in order to apply the build the right query # and apply the filter required. It returns a json with the spots -def spotquery(): +def spotquery(parameters): try: - callsign = request.args.get("c") # search specific callsign - - if callsign: - query_string = query_build_callsign(callsign) + if 'callsign' in parameters: + logging.debug('search callsign') + query_string = query_build_callsign( parameters['callsign'] ) else: - query_string = query_build() + logging.debug('search eith other filters') + query_string = query_build(parameters) qm.qry(query_string) data = qm.get_data() @@ -246,11 +253,9 @@ def spotquery(): except Exception as e: logger.error(e) - # find adxo events adxo_events = None - def get_adxo(): global adxo_events adxo_events = get_adxo_events() @@ -267,15 +272,19 @@ bubble_graph_hb = HourBand(logger, qm, band_frequencies) geo_graph_wdsl = WorldDxSpotsLive(logger, qm, pfxt) # ROUTINGS -@app.route("/spotlist", methods=["GET"]) +@app.route("/spotlist", methods=["POST"]) +@csrf.exempt def spotlist(): - response = flask.Response(json.dumps(spotquery())) + logger.debug(request.json) + response = flask.Response(json.dumps(spotquery(request.json))) return response def who_is_connected(): host_port = cfg["telnet"].split(":") response = who(host_port[0], host_port[1], cfg["mycallsign"]) + logger.debug("list of connected clusters:") + logger.debug(response) return response #Calculate nonce token used in inline script and in csp "script-src" header @@ -313,7 +322,6 @@ def sw(): def root(): return app.send_static_file("html/offline.html") - @app.route("/world.json") def world_data(): return app.send_static_file("data/world.json") @@ -336,7 +344,6 @@ def plots(): ) return response - @app.route("/cookies.html", methods=["GET"]) def cookies(): response = flask.Response( @@ -351,7 +358,6 @@ def cookies(): ) return response - @app.route("/privacy.html", methods=["GET"]) def privacy(): response = flask.Response( @@ -366,7 +372,6 @@ def privacy(): ) return response - @app.route("/sitemap.xml") def sitemap(): return app.send_static_file("sitemap.xml") @@ -404,9 +409,12 @@ def find_callsign(): return response -@app.route("/plot_get_heatmap_data", methods=["GET"]) +@app.route("/plot_get_heatmap_data", methods=["POST"]) +@csrf.exempt def get_heatmap_data(): - continent = request.args.get("continent") + #continent = request.args.get("continent") + continent = request.json['continent'] + logger.debug(request.get_json()); response = flask.Response(json.dumps(heatmap_cbp.get_data(continent))) logger.debug(response) if response is None: @@ -414,7 +422,8 @@ def get_heatmap_data(): return response -@app.route("/plot_get_dx_spots_per_month", methods=["GET"]) +@app.route("/plot_get_dx_spots_per_month", methods=["POST"]) +@csrf.exempt def get_dx_spots_per_month(): response = flask.Response(json.dumps(bar_graph_spm.get_data())) logger.debug(response) @@ -423,7 +432,8 @@ def get_dx_spots_per_month(): return response -@app.route("/plot_get_dx_spots_trend", methods=["GET"]) +@app.route("/plot_get_dx_spots_trend", methods=["POST"]) +@csrf.exempt def get_dx_spots_trend(): response = flask.Response(json.dumps(line_graph_st.get_data())) logger.debug(response) @@ -432,7 +442,8 @@ def get_dx_spots_trend(): return response -@app.route("/plot_get_hour_band", methods=["GET"]) +@app.route("/plot_get_hour_band", methods=["POST"]) +@csrf.exempt def get_dx_hour_band(): response = flask.Response(json.dumps(bubble_graph_hb.get_data())) logger.debug(response) @@ -441,7 +452,8 @@ def get_dx_hour_band(): return response -@app.route("/plot_get_world_dx_spots_live", methods=["GET"]) +@app.route("/plot_get_world_dx_spots_live", methods=["POST"]) +@csrf.exempt def get_world_dx_spots_live(): response = flask.Response(json.dumps(geo_graph_wdsl.get_data())) logger.debug(response)