tethys.backend/resources/js/Pages/Map.vue

313 lines
9.6 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import { Head } from '@inertiajs/vue3';
import { onMounted, onUnmounted, ref, Ref } from 'vue';
// import { MainService } from '@/Stores/main';;
import {
mdiChartTimelineVariant
} from '@mdi/js';
import LayoutGuest from '@/Layouts/LayoutGuest.vue';
import SectionMain from '@/Components/SectionMain.vue';
// import CardBox from '@/Components/CardBox.vue';
import BaseButton from '@/Components/BaseButton.vue';
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
// import SectionBannerStarOnGitHub from '@/Components/SectionBannerStarOnGitea.vue';
import { Map } from 'leaflet/src/map/index';
import { Rectangle } from 'leaflet';
import { canvas } from 'leaflet/src/layer/vector/Canvas';
import { svg } from 'leaflet/src/layer/vector/SVG';
import { MapOptions } from '@/Components/Map/MapOptions';
import axios from 'axios';
import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
import { Attribution } from 'leaflet/src/control/Control.Attribution';
import { stardust } from '@eidellev/adonis-stardust/client';
import DrawControlComponent from '@/Components/Map/draw.component.vue';
import { MapService } from '@/Stores/map.service';
import { LayerGroup } from 'leaflet/src/layer/LayerGroup'
import { OpensearchDocument } from '@/Dataset';
Map.include({
// @namespace Map; @method getRenderer(layer: Path): Renderer
// Returns the instance of `Renderer` that should be used to render the given
// `Path`. It will ensure that the `renderer` options of the map and paths
// are respected, and that the renderers do exist on the map.
getRenderer: function (layer) {
// @namespace Path; @option renderer: Renderer
// Use this specific instance of `Renderer` for this path. Takes
// precedence over the map's [default renderer](#map-renderer).
var renderer = layer.options.renderer || this._getPaneRenderer(layer.options.pane) || this.options.renderer || this._renderer;
if (!renderer) {
renderer = this._renderer = this._createRenderer();
}
if (!this.hasLayer(renderer)) {
this.addLayer(renderer);
}
return renderer;
},
_getPaneRenderer: function (name) {
if (name === 'overlayPane' || name === undefined) {
return false;
}
var renderer = this._paneRenderers[name];
if (renderer === undefined) {
renderer = this._createRenderer({ pane: name });
this._paneRenderers[name] = renderer;
}
return renderer;
},
_createRenderer: function (options) {
// @namespace Map; @option preferCanvas: Boolean = false
// Whether `Path`s should be rendered on a `Canvas` renderer.
// By default, all `Path`s are rendered in a `SVG` renderer.
return (this.options.preferCanvas && canvas(options)) || svg(options);
},
});
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
const DEFAULT_BASE_LAYER_ATTRIBUTION = '&copy; <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
const OPEN_SEARCH_HOST = 'http://192.168.21.18';
let map: Map;
const fitBounds: LatLngBoundsExpression = [
[46.4318173285, 9.47996951665],
[49.0390742051, 16.9796667823],
];
const mapId = 'map';
const draw: Ref<DrawControlComponent | null> = ref(null);
const southWest = ref(null);
const northEast = ref(null);
const mapService = MapService();
const coverage = {
x_min: undefined,
y_min: undefined,
x_max: undefined,
y_max: undefined,
elevation_min: undefined,
elevation_max: undefined,
elevation_absolut: undefined,
depth_min: undefined,
depth_max: undefined,
depth_absolut: undefined,
time_min: undefined,
time_max: undefined,
time_absolut: undefined,
};
const filterLayerGroup = new LayerGroup();
// Replace with your actual data
const datasets: Ref<OpensearchDocument[]> = ref([]);
onMounted(() => {
initMap();
});
onUnmounted(() => {
map.off('zoomend zoomlevelschange');
});
const mapOptions: MapOptions = {
center: [48.208174, 16.373819],
zoom: 3,
zoomControl: false,
attributionControl: false,
};
const initMap = async () => {
// init leaflet map
map = new Map('map', mapOptions);
mapService.setMap(mapId, map);
map.scrollWheelZoom.disable();
map.fitBounds(fitBounds);
draw.value?.toggleDraw();
map.addLayer(filterLayerGroup);
const attributionControl = new Attribution().addTo(map);
attributionControl.setPrefix(false);
let osmGgray = tileLayerWMS('https://ows.terrestris.de/osm-gray/service', {
format: 'image/png',
attribution: DEFAULT_BASE_LAYER_ATTRIBUTION,
layers: 'OSM-WMS',
});
let layerOptions = {
label: DEFAULT_BASE_LAYER_NAME,
visible: true,
layer: osmGgray,
};
layerOptions.layer.addTo(map);
map.on('Draw.Event.CREATED', handleDrawEventCreated);
// // const query = {
// // query: {
// // term: {
// // id: "103"
// // }
// // }
// // };
// // to do : call extra method:
// const query = {
// // q: 'id:103'
// // q: 'author:"Iglseder, Christoph" OR title:"Datensatz"',
// // q: 'author:"Iglseder"',
// q: '*',
// _source: 'author,bbox_xmin,bbox_xmax,bbox_ymin,bbox_ymax,abstract,title',
// size: 1000
// // qf:"title^3 author^2 subject^1",
// }
// try {
// let response = await axios({
// method: 'GET',
// url: OPEN_SEARCH_HOST + '/tethys-records/_search',
// headers: { 'Content-Type': 'application/json' },
// params: query
// });
// // Loop through the hits in the response
// response.data.hits.hits.forEach(hit => {
// // Get the geo_location attribute
// // var geo_location = hit._source.geo_location;
// let xMin = hit._source.bbox_xmin;
// let xMax = hit._source.bbox_xmax;
// let yMin = hit._source.bbox_ymin;
// let yMax = hit._source.bbox_ymax;
// var bbox: LatLngBoundsExpression = [[yMin, xMin], [yMax, xMax]];
// // Parse the WKT string to get the bounding box coordinates
// // var bbox = wktToBbox(geo_location);
// // // Add the bounding box to the map as a rectangle
// new Rectangle(bbox, { color: "#ff7800", weight: 1 }).addTo(map);
// // console.log(hit._source);
// });
// } catch (error) {
// console.error(error);
// }
};
const handleDrawEventCreated = async (event) => {
filterLayerGroup.clearLayers();
datasets.value = [];
let layer = event.layer;
let bounds = layer.getBounds();
// coverage.x_min = bounds.getSouthWest().lng;
// coverage.y_min = bounds.getSouthWest().lat;
// coverage.x_max = bounds.getNorthEast().lng;
// coverage.y_max = bounds.getNorthEast().lat;
try {
let response = await axios({
method: 'POST',
url: OPEN_SEARCH_HOST + '/tethys-records/_search',
headers: { 'Content-Type': 'application/json' },
data: {
"size": 1000,
"query": {
"bool": {
"must": {
"match_all": {}
},
"filter": {
"geo_bounding_box": {
"geo_location": { // replace 'location' with your geo-point field name
"top_left": {
"lat": bounds.getNorthEast().lat,
"lon": bounds.getSouthWest().lng
},
"bottom_right": {
"lat": bounds.getSouthWest().lat,
"lon": bounds.getNorthEast().lng
}
}
}
}
}
// _source: 'author,bbox_xmin,bbox_xmax,bbox_ymin,bbox_ymax,abstract,title',
// "size": 1000
}
}
});
// Loop through the hits in the response
response.data.hits.hits.forEach(hit => {
// Get the geo_location attribute
// var geo_location = hit._source.geo_location;
let xMin = hit._source.bbox_xmin;
let xMax = hit._source.bbox_xmax;
let yMin = hit._source.bbox_ymin;
let yMax = hit._source.bbox_ymax;
var bbox: LatLngBoundsExpression = [[yMin, xMin], [yMax, xMax]];
// Parse the WKT string to get the bounding box coordinates
// var bbox = wktToBbox(geo_location);
// // Add the bounding box to the map as a rectangle
let rect = new Rectangle(bbox, { color: "#ff7800", weight: 1 });
filterLayerGroup.addLayer(rect);
datasets.value.push(hit._source);
});
} catch (error) {
console.error(error);
}
};
</script>
<template>
<LayoutGuest>
<Head title="Map" />
<!-- <section class="p-6" v-bind:class="containerMaxW"> -->
<SectionMain>
<SectionTitleLineWithButton v-bind:icon="mdiChartTimelineVariant" title="Tethys Map" main>
<!-- <BaseButton href="https://gitea.geologie.ac.at/geolba/tethys" target="_blank" :icon="mdiGithub"
label="Star on Gitea" color="contrast" rounded-full small /> -->
<BaseButton :route-name="stardust.route('app.login.show')" label="Login" color="white" rounded-full small />
</SectionTitleLineWithButton>
<!-- <SectionBannerStarOnGitHub /> -->
<!-- <CardBox> -->
<div id="map" class="map-container mapDesktop mt-6 mb-6 rounded-2xl py-12 px-6 text-center">
<DrawControlComponent ref="draw" :preserve="false" :mapId="mapId" :southWest="southWest"
:northEast="northEast">
</DrawControlComponent>
</div>
<div d="search-result-list-wrapper" class="flex flex-wrap col-span-24">
<div v-for="dataset in datasets" :key="dataset.id" class="w-full sm:w-1/2 md:w-1/3 lg:w-1/4 p-4">
<div class="bg-white rounded shadow p-6">
<h2 class="text-xl font-bold mb-2">{{ dataset.title_output }}</h2>
<p class="text-gray-700 mb-2">{{ dataset.abstract_output }}</p>
<div class="text-sm text-gray-600">
<div v-for="author in dataset.author" :key="author" class="mb-1">{{ author }}</div>
</div>
<div class="mt-4">
<span
class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">{{
dataset.year }}</span>
<span
class="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2">{{
dataset.language }}</span>
</div>
</div>
</div>
</div>
</SectionMain>
<!-- </section> -->
</LayoutGuest></template>