Commit a1ee423c authored by Porter Libby's avatar Porter Libby
Browse files
parents 09fc5e7c 9ff1701d
......@@ -15,6 +15,50 @@ The `public/js` folder contains all the client-side JS:
- **public / js / map.js** - handles creation of maps and points for the `map` view. Uses ARC GIS JS API.
- **public / js / util.js** - handles odd things, such as generation of `HTML` for the template, and disabling/enabling views.
## Creating a new PSQL Query
The process of adding new server-side queries and allowing the client-side to access those functions, without providing access to the data, can be a little tricky. I have outlined the process I use here in the hopes that it will be helpful.
1. In `queries.js` create a new function to get information using a programmed query string. This should look something like the example below:
```js
...
const getSomething = (request, response) => {
var query = 'SELECT something from SOMETABLE;'
serverOut(query); // print the query text
pool.query(query, (error, results) => {
if (error) {
throw error // error from query string
}
response.status(200).json(results.rows) // return the results
})
}
module.exports = {
...
getSomething, // this must match the route in index.js
...
}
```
2. In `index.js`, create a route so that the client-side will be able to access the routes in `queries.js`. This should look something like this:
```js
app.get('/something', q.getSomething); // should match the name in module.exports
```
3. We can now access the route from client-side. For example, in the file `public/js/data.js`. This should look something like this:
```js
function getSomthing(){
$.ajax({
type: 'GET',
url: '/something', // should match the name in index.js
success: function(response) {
console.table(response); // show the full result
// a renderer could be made to use this data here
},
error: function(xhr, status, err) {
console.log(xhr.responseText); // if query fails
}
});
}
```
## HTML Template
For style and `CSS` information, refer to the [ customization guide](CUSTOM.md).
HTML template exists in `views/index.ejs`.
\ No newline at end of file
......@@ -68,7 +68,7 @@ h1 span{
}
}
.elem-1{
background-color: var(--theme4);
background-color: #aaa;
}
.elem-0{
background-color: var(--theme4);
......@@ -275,9 +275,23 @@ label
.data-catagory-simple .detailed_info{
display: none;
}
.data-catagory-simple .detailed_info_2{
display: none;
}
.data-catagory-detail .detailed_info{
display: inline;
}
.data-catagory-detail .detailed_info_2{
display: none;
}
.data-catagory-detail-2 .detailed_info{
display: none;
}
.data-catagory-detail-2 .detailed_info_2{
display: inline;
}
.lds-ellipsis {
display: inline-block;
......
......@@ -12,6 +12,7 @@
var query_type = null; // 0 = reading, 1 = streaming
var query_selection = [null,null,null,null,null,null]; // trip, site, sector, spot/host, platform, date
var query_data = null;
var details_mode = 0;
var placeholderHTML = "<div style='float: left; width: 100%; height: 100%; text-align:center; padding-top:20px;color: var(--themep)'>Organizing numbers...</div><div class='lds-ellipsis'><div></div><div></div><div></div><div></div></div>";
......@@ -26,14 +27,14 @@ This is the entry point so that both of these options in the descision tree can
*/
function setReading(){
query_type = 0;
resetElements(['trips','sites','sectors','spots','streamingplatform','streamingdates','streaming','readingplatform','readingdates','reading']);
resetElements(['trips','sites','sectors','spots','streaminghost','streamingplatform','streamingdates','streaming','readingplatform','readingdates','reading']);
document.getElementById("button_permalink").disabled = true;
document.getElementById("button_csv").disabled = true;
getTrips(); // get top level of data and render to the next block on the form
}
function setStreaming(){
query_type = 1;
resetElements(['trips','sites','sectors','spots','streamingplatform','streamingdates','streaming','readingplatform','readingdates','reading']);
resetElements(['trips','sites','sectors','spots','streaminghost','streamingplatform','streamingdates','streaming','readingplatform','readingdates','reading']);
document.getElementById("button_permalink").disabled = true;
document.getElementById("button_csv").disabled = true;
getTrips(); // get top level of data and render to the next block on the form
......@@ -64,13 +65,17 @@ function getTrips(){
success: function(response) {
var tripnames = [];
var tripids = [];
var r_count = [];
var s_count = [];
for(x = 0; x < response.length; x++){
tripids.push(response[x].tripid);
tripnames.push(response[x].tripname);
r_count.push(response[x].r_count);
s_count.push(response[x].s_count);
}
console.info('TRIPS');
console.table(response);
renderTrips(tripnames, tripids);
renderTrips(tripnames, tripids, r_count, s_count);
},
error: function(xhr, status, err) {
console.log(xhr.responseText);
......@@ -98,13 +103,17 @@ function getSites(trip_id){
success: function(response) {
var sitenames = [];
var siteids = [];
var r_count = [];
var s_count = [];
for(x = 0; x < response.length; x++){
sitenames.push(response[x].sitename);
siteids.push(response[x].siteid);
r_count.push(response[x].r_count);
s_count.push(response[x].s_count);
}
console.info('SITES');
console.table(response);
renderSites(sitenames, siteids);
renderSites(sitenames, siteids, r_count, s_count);
},
error: function(xhr, status, err) {
console.log(xhr.responseText);
......@@ -132,13 +141,17 @@ function getSectors(site_id){
success: function(response) {
var sectornames = [];
var sectorids = [];
var r_count = [];
var s_count = [];
for(x = 0; x < response.length; x++){
sectornames.push(response[x].sectorname);
sectorids.push(response[x].sectorid);
r_count.push(response[x].r_count);
s_count.push(response[x].s_count);
}
console.info('SECTORS');
console.table(response);
renderSectors(sectornames, sectorids);
renderSectors(sectornames, sectorids, r_count, s_count);
},
error: function(xhr, status, err) {
console.log(xhr.responseText);
......@@ -166,12 +179,16 @@ function getSpots(sector_id){
data: {sectorid: sector_id, siteid: query_selection[1], tripid: query_selection[0]},
success: function(response) {
var spotids = [];
var r_count = [];
var s_count = [];
for(x = 0; x < response.length; x++){
spotids.push(response[x].spotid);
r_count.push(response[x].r_count);
s_count.push(response[x].s_count);
}
console.info('SPOTS');
console.table(response);
renderSpots(spotids);
renderSpots(spotids, r_count, s_count);
},
error: function(xhr, status, err) {
console.log(xhr.responseText);
......@@ -313,12 +330,14 @@ function getStreamingsHosts(sector_id){
data: {sectorid: sector_id, siteid: query_selection[1], tripid: query_selection[0]},
success: function(response) {
var hosts = [];
var s_count = [];
for(x = 0; x < response.length; x++){
hosts.push(response[x]);
s_count.push(response[x].s_count)
}
console.info('DATA - HOSTS');
console.table(response);
renderStreamingsHosts(hosts);
renderStreamingsHosts(hosts, s_count);
},
error: function(xhr, status, err) {
console.log(xhr.responseText);
......@@ -445,7 +464,7 @@ to create a radiobutton.
When a get function returns its data, it sends it to a render function if it needs to be selected from.
*/
function renderTrips(tripnames, tripids){
function renderTrips(tripnames, tripids, r_count, s_count){
var container = document.getElementById('trips');
container.innerHTML = '';
if (container.childElementCount == 0){ // dont override selections with navigation
......@@ -454,13 +473,13 @@ function renderTrips(tripnames, tripids){
trips_ls.id = 'trips-ls';
for(x = 0; x < tripnames.length; x++){
var elem = createRadioElementTrips((x % 2),'trips', false, tripnames[x],tripids[x]); // util function
var elem = createRadioElementTrips((x % 2),'trips', [r_count[x], s_count[x]], tripnames[x],tripids[x]); // util function
trips_ls.innerHTML += elem;
}
container.append(trips_ls);
}
}
function renderSites(sitenames, siteids){
function renderSites(sitenames, siteids, r_count, s_count){
var container = document.getElementById('sites');
container.innerHTML = "";
container.innerHTML += "<div onclick='togglediv(" + '"#sites-ls","sites-button"' + ")' class='data-header'><h1>Sites <span id='sites-button'>-</span></h1></div>";
......@@ -468,12 +487,12 @@ function renderSites(sitenames, siteids){
sites_ls.id = 'sites-ls';
for(x = 0; x < sitenames.length; x++){
var elem = createRadioElementSites((x % 2),'sites', false, sitenames[x],siteids[x]); // util function
var elem = createRadioElementSites((x % 2),'sites', [r_count[x], s_count[x]], sitenames[x],siteids[x]); // util function
sites_ls.innerHTML += elem;
}
container.append(sites_ls);
}
function renderSectors(sectornames, sectorids){
function renderSectors(sectornames, sectorids, r_count, s_count){
var container = document.getElementById('sectors');
container.innerHTML = "";
......@@ -483,7 +502,7 @@ function renderSectors(sectornames, sectorids){
sectors_ls.id = 'sectors-ls';
for(x = 0; x < sectornames.length; x++){
var elem = createRadioElementSectors((x % 2),'sectors', false, sectornames[x], sectorids[x]); // util function
var elem = createRadioElementSectors((x % 2),'sectors', [r_count[x], s_count[x]], sectornames[x], sectorids[x]); // util function
sectors_ls.innerHTML += elem;
}
container.append(sectors_ls);
......@@ -493,7 +512,7 @@ function renderSectors(sectornames, sectorids){
}
function renderSpots(spotids){
function renderSpots(spotids, r_count, s_count){
var container = document.getElementById('spots');
container.innerHTML = "";
if (spotids.length != 0){
......@@ -502,7 +521,7 @@ function renderSpots(spotids){
spots_ls.id = 'spots-ls';
for(x = 0; x < spotids.length; x++){
var elem = createRadioElementSpots((x % 2),'spots', false, spotids[x], spotids[x]); // util function
var elem = createRadioElementSpots((x % 2),'spots', [r_count[x], s_count[x]], spotids[x], spotids[x]); // util function
spots_ls.innerHTML += elem;
}
container.append(spots_ls);
......@@ -510,7 +529,7 @@ function renderSpots(spotids){
document.getElementById('data-prompt').innerHTML = "No Spots found for this sector"
}
}
function renderStreamingsHosts(hosts){
function renderStreamingsHosts(hosts,s_count){
if (streamings.length != 0){
var container = document.getElementById('streaminghost');
container.innerHTML = "";
......@@ -522,7 +541,7 @@ function renderStreamingsHosts(hosts){
if (hosts[x].hostname){
hostname = hosts[x].hostname.toString()
}
var elem = createRadioElementStreamingsHosts((x % 2),'hosts', false, hosts[x].hostid, hostname ); // util function
var elem = createRadioElementStreamingsHosts((x % 2),'hosts', s_count[x], hosts[x].hostid, hostname ); // util function
streamingshosts_ls.innerHTML += elem;
}
container.append(streamingshosts_ls);
......
......@@ -45,8 +45,15 @@ function switchToData(){
// TEAMPLATES FOR DOM PIECES
// generalized formula
function createRadioElement(name, id, label, f){
var radioHtml = '<div class="elem-div elem-0">'
function createRadioElement(name, id, label, f, count=999){
var radioHtml = '<div class="elem-div elem-'
if (count == 0){
radioHtml += "1"
}else{
radioHtml += "0"
}
radioHtml += '">';
if (typeof id === 'string' || id instanceof String){
radioHtml += '<input class="data-radio form-radio" onchange="'+ f +'(';
radioHtml += "'" + id + "'";
......@@ -56,6 +63,7 @@ function createRadioElement(name, id, label, f){
}
radioHtml += '<label for="' + label + '">';
radioHtml += '<strong>'+ label + "</strong>";
radioHtml += '<span class="detailed_info_2"> (' + count +' values)</span>';
radioHtml += '<span class="detailed_info"> (ID: ' + id +')</span>';
radioHtml += '</label></div>';
......@@ -63,27 +71,34 @@ function createRadioElement(name, id, label, f){
}
// take information from data.js and write it into html
function createRadioElementTrips( mode, name, checked, label, id ) {
function createRadioElementTrips( mode, name, count, label, id ) {
var f = "getSites";
return createRadioElement(name, id, label, f);
return createRadioElement(name, id, label, f, count[query_type]);
}
function createRadioElementSites( mode, name, checked, label, id ) {
function createRadioElementSites( mode, name, count, label, id ) {
var f = "getSectors";
return createRadioElement(name, id, label, f);
return createRadioElement(name, id, label, f, count[query_type]);
}
// this one is different since it changes for reading and streaming
function createRadioElementSectors( mode, name, checked, label, id ) {
function createRadioElementSectors( mode, name, count, label, id ) {
var f = "getSpots"; // if reading
if (query_type == 1){ // if streaming
f = "getStreamingsHosts";
}
return createRadioElement(name, id, label, f);
return createRadioElement(name, id, label, f, count[query_type]);
}
function createRadioElementSpots( mode, name, checked, label,id ) {
function createRadioElementSpots( mode, name, count, label,id ) {
var f = "getReadings";
var radioHtml = '<div class="elem-div elem-';
//return createRadioElement(name, id, label, f);
var radioHtml = '<div class="elem-div elem-0">'
if (count == 0){
radioHtml += '1">';
}else{
radioHtml += '0">';
}
if (typeof id === 'string' || id instanceof String){
radioHtml += '<input class="data-radio form-check" onchange="'+ f +'(';
radioHtml += "'" + id + "'";
......@@ -94,13 +109,14 @@ function createRadioElementSpots( mode, name, checked, label,id ) {
radioHtml += '<label for="' + label + '">';
radioHtml += '<strong>'+ label + "</strong>";
radioHtml += '<span class="detailed_info"> (ID: ' + id +')</span>';
radioHtml += '<span class="detailed_info_2"> (' + count[query_type] +' values)</span>';
radioHtml += '</label></div>';
return radioHtml;
}
function createRadioElementStreamingsHosts( mode, name, checked, id, label ) {
function createRadioElementStreamingsHosts( mode, name, count, id, label ) {
var f = "getStreamingsPlatforms";
return createRadioElement(name, id, label, f);
return createRadioElement(name, id, label, f, count);
}
function createRadioElementStreamingsPlatforms( mode, name, checked, id, label ) {
var f = "getStreamingsDates";
......@@ -259,19 +275,30 @@ function removeQuery(){
base = current.split('?')[0];
location.replace(base);
}
function toggleDetails(){
function toggleDetails(){ // details_mode located in data.js
console.log('bruh')
console.log(details_mode)
var all = document.getElementsByClassName('data-catagory');
console.log(all)
for (var i = 0; i < all.length; i++) {
if (all[i].classList.contains('data-catagory-simple')){
if (details_mode == 0){
all[i].classList.remove('data-catagory-simple');
all[i].classList.add('data-catagory-detail');
$("#button_details").css("opacity", "1.0");
}else{
all[i].classList.add('data-catagory-simple');
}else if (details_mode == 1){
all[i].classList.remove('data-catagory-detail');
all[i].classList.add('data-catagory-detail-2');
$("#button_details").css("opacity", "1.0");
}else {
all[i].classList.remove('data-catagory-detail-2');
all[i].classList.add('data-catagory-simple');
$("#button_details").css("opacity", "0.5");
}
}
}
details_mode = (details_mode + 1) % 3;
}
function createCSV(){
const rows = [["tripid","platformid","sensorid","hostid","recordtime","value_1","quality","latitude","longitude","elevation","accuracy","satellites","value_2","value_3","siteid","sectorid","value_4","value_5","value_6"]];
......
......@@ -23,7 +23,10 @@ const pool = new Pool({
})
const getTrips = (request, response) => {
var query = "SELECT tripName, tripID from fieldday_trip;";
var query = "SELECT tripName, tripID, "
+ "(SELECT COUNT(*) FROM fieldday_streaming WHERE tripid=fieldday_trip.tripid) AS s_count, " // get s_count and r_count as the number of nodes in the subtree of each
+ "(SELECT COUNT(*) FROM fieldday_reading WHERE tripid=fieldday_trip.tripid) AS r_count"
+ " from fieldday_trip;";
serverOut(query);
pool.query(query, (error, results) => {
......@@ -34,7 +37,10 @@ const getTrips = (request, response) => {
})
}
const getSites = (request, response) => {
var query = 'SELECT siteName, siteID from fieldday_site where tripid='+ (request.query.id) + ';';
var query = 'SELECT siteName, siteID, '
+ "(SELECT COUNT(*) FROM fieldday_streaming WHERE tripid="+ (request.query.id) +" AND siteid=fieldday_site.siteid) AS s_count, " // get s_count and r_count as the number of nodes in the subtree of each
+ "(SELECT COUNT(*) FROM fieldday_reading WHERE tripid="+ (request.query.id) +" AND siteid=fieldday_site.siteid) AS r_count"
+' from fieldday_site where tripid='+ (request.query.id) + ';';
serverOut(query);
pool.query(query, (error, results) => {
......@@ -45,7 +51,10 @@ const getSites = (request, response) => {
})
}
const getSectors = (request, response) => {
var query = 'SELECT sectorname, sectorid from fieldday_sector where tripid='+ (request.query.tripid)
var query = 'SELECT sectorname, sectorid, '
+ "(SELECT COUNT(*) FROM fieldday_streaming WHERE tripid="+ (request.query.tripid) + ' and siteid=' + (request.query.siteid) + " AND sectorid=fieldday_sector.sectorid) AS s_count, " // get s_count and r_count as the number of nodes in the subtree of each
+ "(SELECT COUNT(*) FROM fieldday_reading WHERE tripid="+ (request.query.tripid) + ' and siteid=' + (request.query.siteid) + " AND sectorid=fieldday_sector.sectorid) AS r_count"
+' from fieldday_sector where tripid='+ (request.query.tripid)
+ ' and siteid=' + (request.query.siteid) + ';'
serverOut(query);
......@@ -57,7 +66,9 @@ const getSectors = (request, response) => {
})
}
const getSpots = (request, response) => {
var query = 'SELECT spotid from fieldday_spot where tripid='+ (request.query.tripid)
var query = 'SELECT spotid, '
+ "(SELECT COUNT(*) FROM fieldday_reading WHERE tripid="+ (request.query.tripid) + ' and siteid=' + (request.query.siteid) + ' and sectorid=' + (request.query.sectorid) + " AND spotid=fieldday_spot.spotid) AS r_count"
+' from fieldday_spot where tripid='+ (request.query.tripid)
+' and siteid='+ (request.query.siteid)
+' and sectorid='+ request.query.sectorid +';';
serverOut(query);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment