changed api method from get to post

This commit is contained in:
coulisse 2023-02-19 22:47:28 +01:00
parent f000bba226
commit ab50f3841e
20 changed files with 388 additions and 311 deletions

View File

@ -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

View File

@ -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:** <corrado.gerbaldo@gmail.com>
- **Licensing:** Gpl V3.0 see [LICENSE](LICENSE) file.

View File

@ -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

View File

@ -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

View File

@ -16,7 +16,7 @@
<link rel="icon" href="/static/images/icons/spider_ico_master.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/static/images/icons/icon-apple.png">
<link rel="manifest" href="/static/pwa/manifest.webmanifest">
<link rel="stylesheet" href="/static/css/dev/style.css">
<link rel="stylesheet" href="/static/css/rel/style.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
@ -96,23 +96,23 @@
<span class="copyleft">&copy;</span> Copyleft:
<span id="copyDate"></span>
<a href="https://github.com/coulisse/spiderweb/" target="blank" rel="noopener">IU1BOW - Spiderweb</a>
<span id="version">v2.4.2</span>
<span id="version">v2.4.4</span>
<!--
<a href="https://github.com/coulisse/spiderweb/" target="blank" rel="noopener"><img src="/static/images/icons/github-mark.svg" alt="github.com" width="16px" height="16px"></a>
-->
</div>
</footer>
<script async src="static/js/dev/load-sw.js"></script>
<script async src="static/js/rel/load-sw.min.js"></script>
<script nonce="">
</script>
<script defer src="static/js/dev/common.js"></script>
<script defer src="static/js/rel/common.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"></script>
<script async src="static/js/dev/callsign_search.js"></script>
<script async src="static/js/rel/callsign_search.min.js"></script>

View File

@ -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 {

View File

@ -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";
}

View File

@ -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: '+'<strong>'+p.data[2]+'</strong>';
var format = p.seriesName + ' on ' + p.name + ' band: ' + '<strong>' + p.data[2] + '</strong>';
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: <STRONG>'+ val.value[2] +'</STRONG>';
formatter: function (val) {
var out = 'Spots: <STRONG>' + val.value[2] + '</STRONG>';
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);
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);

View File

@ -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 {

View File

@ -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)}});

View File

@ -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);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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",

View File

@ -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',

View File

@ -14,7 +14,7 @@
<link rel="icon" href="/static/images/icons/spider_ico_master.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/static/images/icons/icon-apple.png">
<link rel="manifest" href="/static/pwa/manifest.webmanifest">
<link rel="stylesheet" href="/static/css/dev/style.css">
<link rel="stylesheet" href="/static/css/rel/style.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css"
integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
@ -92,24 +92,24 @@
<span class="copyleft">&copy;</span> Copyleft:
<span id="copyDate"></span>
<a href="https://github.com/coulisse/spiderweb/" target="blank" rel="noopener">IU1BOW - Spiderweb</a>
<span id="version">v2.4.2</span>
<span id="version">v2.4.4</span>
<!--
<a href="https://github.com/coulisse/spiderweb/" target="blank" rel="noopener"><img src="/static/images/icons/github-mark.svg" alt="github.com" width="16px" height="16px"></a>
-->
</div>
</footer>
<script async src="static/js/dev/load-sw.js"></script>
<script async src="static/js/rel/load-sw.min.js"></script>
<script nonce="{{ inline_script_nonce }}">
{% block app_data %}
var my_callsign = '{{mycallsign}}';
{% endblock app_data %}
</script>
<script defer src="static/js/dev/common.js"></script>
<script defer src="static/js/rel/common.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"></script>
{% block app_scripts %}
<script async src="static/js/dev/callsign_search.js"></script>
<script async src="static/js/rel/callsign_search.min.js"></script>
{% endblock app_scripts %}
{% block inline_scripts %}
{% endblock inline_scripts %}
@ -140,7 +140,7 @@
</div>
</div>
<script defer src="static/js/dev/cookie_consent.js"></script>
<script defer src="static/js/rel/cookie_consent.min.js"></script>
{% endif %}
{% endblock cookie %}
</body>

View File

@ -16,5 +16,5 @@
var callsign = '{{callsign}}';
{% endblock app_data %}
{% block inline_scripts %}
<script defer src="static/js/dev/callsign_inline.js"></script>
<script defer src="static/js/rel/callsign_inline.min.js"></script>
{% endblock %}

View File

@ -305,8 +305,8 @@ var band_frequencies={{bands["bands"]|tojson|safe}};
{% endblock app_data %}
{% block app_scripts %}
{{ super() }}
<script defer src="static/js/dev/table.js"></script>
<script defer src="static/js/rel/table.min.js"></script>
{% endblock %}
{% block inline_scripts %}
<script defer src="static/js/dev/index_inline.js"></script>
<script defer src="static/js/rel/index_inline.min.js"></script>
{% endblock %}

View File

@ -89,5 +89,5 @@ var band_frequencies={{bands["bands"]|tojson|safe}};
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.1/echarts.min.js"
integrity="sha512-OTbGFYPLe3jhy4bUwbB8nls0TFgz10kn0TLkmyA+l3FyivDs31zsXCjOis7YGDtE2Jsy0+fzW+3/OVoPVujPmQ=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script defer src="static/js/dev/plot.js"></script>
<script defer src="static/js/rel/plot.min.js"></script>
{% endblock app_scripts %}

View File

@ -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)