Fullstack Portal Created by the HCMR for the Marine Strategy Framework Directive Program in order to cover demands and aspects considering extendability and maintainability
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

508 lines
13 KiB

var requestsGridlayer
var wfd;
var legends = {};
var selectedEntityGroup = null;
var selectedEntityId = null;
var selectedMru = null;
async function get_layer_list() {
let response = await fetch(BASE_URL + '/src/geoserver/get_layers.php');
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
let json = await response.json();
return json
} else {
alert("HTTP-Error: " + response.status);
}
}
async function fetchGeoJson(layerCode) {
console.debug('fetching geojson...');
const url = BASE_URL + "/interface/geojson/" + layerCode;
try {
const response = await fetch(url);
const data = await response.json();
console.debug('geojson data: ', data);
return data;
} catch (error) {
console.error(error);
}
}
function highlightFeature(e) {
let overLayer = e.target;
e.target.tempStyle = {
weight: overLayer.options.weight,
color: overLayer.options.color,
dashArray: overLayer.options.dashArray,
fillOpacity: overLayer.options.fillOpacity
};
console.debug("highlighted: ", e.target);
try {
overLayer.setStyle({
weight: 5,
color: '#666',
dashArray: '',
fillOpacity: 0.7
});
} catch (err) {
console.log('could not change style');
}
}
function resetHighlight(e) {
try {
e.target.setStyle(e.target.tempStyle);
delete e.target.tempStyle;
} catch {
console.debug('eee');
}
}
function onEachFeature(feature, layer) {
layer.on({
mouseover: highlightFeature,
mouseout: resetHighlight,
click: zoomToFeature
});
}
function styleLine(feature, layer) {
return {
fillColor: getColor(), //feature.properties.name
weight: 2,
radius: 8,
opacity: 1,
color: '#000',
dashArray: '3',
fillOpacity: 0.8
};
}
function stylePoint(feature, latlng) {
console.debug(feature);
return L.circleMarker(latlng, styleRules);
};
function getColor(d=null) {
if (d != null)
return intToRGB(hashCode(d));
else
return "#ff7800";
}
function intToRGB(i){
var c = (i & 0x00FFFFFF)
.toString(16)
.toUpperCase();
return "00000".substring(0, 6 - c.length) + c;
}
function hashCode(str) { // java String#hashCode
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
return hash;
}
// zoom to feature (for data sources)
function zoomToFeature(e) {
let featureId = e.target.feature.properties.id;
console.debug('feature zoomed: ', e.target);
try {
selectedEntityGroup = e.target.feature.id.split('.')[0];
selectedEntityId = e.target.feature.properties.id;
} catch (error) {
selectedEntityId = e.target.feature.properties.id;
}
lonlat = {lon: e.latlng.lng, lat: e.latlng.lat};
console.debug('zoomed feature: ', e.target.feature);
moreInfoPopup(e.target.feature.properties);
try {
mapL.fitBounds(e.target.getBounds());
} catch (err) {
console.log('cannot zoom ', err);
}
}
function boundsToExtent(northEast, southWest, my_crs) {
let my_proj = my_crs.projection;
let rt = my_proj.project(northEast);
let lb = my_proj.project(southWest);
return {
left: lb.x,
bottom: lb.y,
right: rt.x,
top: rt.y
}
}
function getBathymetry() {
// load contours in JSON
const url = "https://ows.emodnet-bathymetry.eu/wfs?service=WFS&version=1.1.0&request=GetFeature&typeName=emodnet:contours&outputFormat=application/json";
const rainbow_url = "https://ows.emodnet-bathymetry.eu/wms";
let remoteLayer;
// add rainbow colored bathymetry map
const rnb = L.tileLayer.wms(rainbow_url, { transparent: true, layers: 'emodnet:mean_rainbowcolour', format: 'image/png'});
const cnt = L.tileLayer.wms(rainbow_url, { transparent: true, layers: 'emodnet:contours', format: 'image/png'});
// legends['DPTH'] = L.control.Legend({
// position: "bottomright",
// title: 'Bathymetry',
// symbolWidth: 150,
// symbolHeight: 208,
// collapsed: false,
// legends: [{
// type: "image",
// label: ' ',
// url: "https://tiles.emodnet-bathymetry.eu/legends/legend_rainbow.png"
// }]
// }).addTo(mapL);
remoteLayer = L.layerGroup([rnb, cnt]);
return remoteLayer;
}
async function getDepthOnPoint(latlng) {
await fetch(`https://rest.emodnet-bathymetry.eu/depth_sample?geom=POINT(${latlng.lng}%20${latlng.lat})`, {
"credentials": "omit",
"headers": {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-site",
"Sec-GPC": "1"
},
"method": "GET",
"mode": "cors"
}).then(res => {
return res.json();
}).then(depthInfo => {
const depth = depthInfo.avg.toString();
L.popup()
.setLatLng(latlng)
.setContent(`<table class="table"><tr><th>Topography (m)</th></tr><tr><td>${depth}</td></tr></table>`)
.openOn(mapL);
});
}
function getHabitat(layerCode) {
// load contours in JSON
const url = "https://ows.emodnet-seabedhabitats.eu/geoserver/emodnet_view/wms";
const lgndUrl = "https://ows.emodnet-seabedhabitats.eu/geoserver/emodnet_view/ows?service=WMS&request=GetLegendGraphic&format=image%2Fpng&width=20&height=20&layer=eusm2021_bio_200&style=eusm2019_msfd_200"
// add rainbow colored bathymetry map
let habitats = new L.layerGroup();
const lrs = ['eusm2021_msfd_800', 'eusm2021_msfd_400', 'eusm2021_msfd_200'];
let l;
lrs.forEach(layer => {
l = L.tileLayer.betterWms(url, { transparent: true, layers: layer, format: 'image/png'});
habitats.addLayer(l)
});
// legends[layerCode] = L.control.Legend({
// position: "bottomright",
// symbolWidth: 400,
// symbolHeight: 600,
// collapsed: false,
// title: 'Habitat Type',
// legends: [{
// type: "image",
// label: ' ',
// url: lgndUrl
// }]
// }).addTo(mapL);
//
return habitats;
}
function moreInfoPopup(props) {
let title;
if (props.hasOwnProperty('code')) {
title = `${props.code} &mdash; ${props.name}`;
} else {
title = `Grid &mdash; ${props.cellcode}`;
}
if (typeof props.tspr !== 'undefined') {
title = `POSEIDON &mdash; ${props.pid}`;
props.entity_group = 'POSEIDON';
}
if (typeof props.ctStationCode !== 'undefined')
title = `WFD &mdash; ${props.ctStationCode}`;
Alpine.store('entity', props);
getPagePartial('more-info').then(content => {
new L.control.window(mapL, {
title: title,
content: `${content}`,
visible: true,
position: 'left'
});
});
}
function mruPopup(props) {
if (props.hasOwnProperty('nssg')) {
L.popup()
.setLatLng([props.y_coord, props.x_coord])
.setContent(`<table class="table"><tr><th>NSSG Label</th></tr><tr><td>${props.nssg_label}</td></tr></table>`)
.openOn(mapL);
return;
}
let title;
Alpine.store('mru', props);
title = `MRU: ${props.mr_ms_aa}`;
getPagePartial('mru-info').then(content => {
content.props = props;
new L.control.window(mapL, {
title: title,
content: `${content}`,
visible: true,
position: 'left'
});
});
}
// Fetches html from elements folder
async function getPagePartial(partialName, target=null) {
// const url = BASE_URL + `/src/Views/${partialName}.php`;
const url = BASE_URL + `/interface/partial/${partialName}`;
const res = await fetch(url)
.then((response) => {return response.text();})
.then((content) => {
return content
})
.catch((err) => {return err;});
try {
// fill target element with html
document.querySelector(target).innerHTML = res;
} catch(err) {
return res;
}
}
function getProduct(layer) {
let url = layer.endpoint;
let legendUrl = layer.legend;
let l;
l = L.tileLayer.betterWms(url, { transparent: true, layers: layer.code, format: 'image/png'});
// legends[layer.code] = L.control.Legend({
// position: "bottomright",
// symbolWidth: 100,
// symbolHeight: 200,
// collapsed: false,
// title: 'Probability of habitat presence',
// legends: [{
// type: "image",
// label: ' ',
// url: legendUrl
// }]
// }).addTo(mapL);
mapL.on('click', e => {
let location = e.latlng;
});
return l;
}
function initializeLayerTree() {
pTree = new PickleTree({
c_target: 'layertree', //'maptab_treeview',
c_config: {
// options here
switchMode: true,
hasLink: true,
drag: false,
contextPos: 'before',
foldedStatus: true
},
switchCallback: layerTreeSwitch,
c_data: myData
});
}
function getWFD(layer) {
var wmsGroup = L.layerGroup();
const layerCode = layer.code;
const layerTitle = layer.name;
const legendName = layerCode.split('_').slice(1,3).join('_');
const lgndUrl = BASE_URL + "/img/legends/" + legendName + ".png";
let l;
l = L.tileLayer.wms(BASE_URL + '/geoserver/wms', { transparent: true, layers: layerCode + layer.minSuffix, format: 'image/png'});
wmsGroup.addLayer(l);
layerControls[layerCode] = L.control.slider(value => {
wmsGroup.removeLayer(l);
l = L.tileLayer.wms(BASE_URL + '/geoserver/wms', { transparent: true, layers: layerCode + value, format: 'image/png'});
wmsGroup.addLayer(l);
},{
min: layer.minSuffix,
max: layer.maxSuffix,
step: 1,
value: layer.minSuffix,
logo: 'Year Selector ' + layerTitle,
}).addTo(mapL);
// legends[layerCode] = L.control.Legend({
// position: "bottomright",
// title: layerTitle,
// symbolWidth: 90,
// symbolHeight: 130,
// collapsed: false,
// legends: [{
// type: "image",
// label: '',
// url: lgndUrl
// }]
// }).addTo(mapL);
//
return wmsGroup;
}
async function searchForRequests() {
let response = await fetch(BASE_URL + '/actions/requests');
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
let json = await response.json();
return json;
} else {
alert("HTTP-Error: " + response.status);
}
}
function flattenJson(data, depth = 1) {
var result = {};
function recurse(cur, prop) {
if (Object(cur) !== cur || depth === 0) {
result[prop] = cur;
} else if (Array.isArray(cur)) {
for(var i=0, l=cur.length; i<l; i++)
recurse(cur[i], prop + "[" + i + "]");
if (l == 0)
result[prop] = [];
} else {
var isEmpty = true;
for (var p in cur) {
isEmpty = false;
recurse(cur[p], prop ? prop + "." + p : p, depth - 1);
}
if (isEmpty && prop)
result[prop] = {};
}
}
recurse(data, "", depth);
return result;
}
async function downloadShapefile(layerName, srs) {
let response = await fetch(BASE_URL + '/geoserver/shapefile/' + layerName + '/' + srs, {
"credentials": "include",
"headers": {
"Accept": "application/zip",
"Accept-Language": "en-US,en;q=0.5",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Pragma": "no-cache",
"Cache-Control": "no-cache"
},
"method": "GET",
"mode": "cors"
});
if (response.ok) { // if HTTP-status is 200-299
// get the response body (the method explained below)
let zip = await response.blob();
var a = document.createElement("a");
let data = await zip;
a.href = window.URL.createObjectURL(data);
a.download = layerName + "_shapefiles";
a.click();
} else {
alert("HTTP-Error: " + response.status);
}
}
async function getFisheriesProduct() {
// Create timeline slider control
const group = L.layerGroup();
// load contours in JSON
const bgLayer = L.tileLayer.betterWms(BASE_URL + '/geoserver/wms', { layers: 'nssg_areas', transparent: true, format: "image/png"});
const url = BASE_URL + "/interface/charts/afppy";
try {
const response = await fetch(url);
const data = await response.json();
let pies;
// Add the custom control to the map
pies = createPie(data, 1990).addTo(group);
layerControls['AFPPY'] = L.control.slider(value => {
pies.remove();
pies = createPie(data, value);
group.addLayer(pies);
},{
min: 1990,
max: 2019,
step: 1,
value: 1990,
logo: 'Year Selector',
}).addTo(mapL);
} catch (error) {
console.error(error);
}
bgLayer.addTo(group);
return group;
}
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}