mirror of
https://github.com/jlengrand/geospatial-messenger.git
synced 2026-03-10 08:21:17 +00:00
Add messages layer + bring back SseBroadcaster
This commit is contained in:
@@ -6,13 +6,19 @@ import org.postgis.PGbox2d
|
||||
import org.postgis.Point
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/message")
|
||||
class MessageController @Autowired constructor(val repository: MessageRepository) {
|
||||
|
||||
val broadcaster = SseBroadcaster()
|
||||
|
||||
@PostMapping
|
||||
fun create(@RequestBody message: Message) = repository.create(message)
|
||||
fun create(@RequestBody message: Message) {
|
||||
repository.create(message)
|
||||
broadcaster.send(message)
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
fun findMessages() = repository.findAll()
|
||||
@@ -22,4 +28,7 @@ class MessageController @Autowired constructor(val repository: MessageRepository
|
||||
@PathVariable xMax:Double, @PathVariable yMax:Double)
|
||||
= repository.findByBoundingBox(PGbox2d(Point(xMin, yMin), Point(xMax, yMax)))
|
||||
|
||||
}
|
||||
@GetMapping("/subscribe")
|
||||
fun subscribe(): SseEmitter = broadcaster.subscribe()
|
||||
|
||||
}
|
||||
25
src/main/kotlin/io/spring/messenger/web/SseBroadcaster.kt
Normal file
25
src/main/kotlin/io/spring/messenger/web/SseBroadcaster.kt
Normal file
@@ -0,0 +1,25 @@
|
||||
package io.spring.messenger.web
|
||||
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter
|
||||
import java.util.*
|
||||
import java.util.Collections.synchronizedSet
|
||||
|
||||
class SseBroadcaster {
|
||||
|
||||
private var sseEmitters = synchronizedSet(HashSet<SseEmitter>());
|
||||
|
||||
fun subscribe(): SseEmitter {
|
||||
val sseEmitter: SseEmitter = SseEmitter()
|
||||
sseEmitter.onCompletion({ this.sseEmitters.remove(sseEmitter) });
|
||||
this.sseEmitters.add(sseEmitter);
|
||||
return sseEmitter
|
||||
}
|
||||
|
||||
fun send(o:Any) {
|
||||
synchronized (sseEmitters) {
|
||||
sseEmitters.iterator().forEach { it.send(o, MediaType.APPLICATION_JSON) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="map" class="map"></div>
|
||||
<div id="popup" class="ol-popup">
|
||||
</div>
|
||||
<div>
|
||||
<span>Current user: </span><select id="select-user"></select>
|
||||
</div>
|
||||
|
||||
@@ -28,7 +28,7 @@ var geolocation = new ol.Geolocation({
|
||||
projection: view.getProjection()
|
||||
});
|
||||
geolocation.on("error", function (error) {
|
||||
alert(error.message);
|
||||
alert("Geolocation error: " + error.message);
|
||||
});
|
||||
var positionFeature = new ol.Feature();
|
||||
positionFeature.setStyle(new ol.style.Style({
|
||||
@@ -55,18 +55,19 @@ geolocation.setTracking(true);
|
||||
|
||||
// ################################# Popup #################################
|
||||
|
||||
var container = document.getElementById('popup');
|
||||
|
||||
var popup = new ol.Overlay(({
|
||||
element: container,
|
||||
autoPan: true,
|
||||
autoPanAnimation: {
|
||||
duration: 250
|
||||
}
|
||||
}));
|
||||
map.addOverlay(popup)
|
||||
|
||||
map.on('singleclick', function (evt) {
|
||||
var coordinate = evt.coordinate;
|
||||
var container = document.createElement("div");
|
||||
container.className = "ol-popup";
|
||||
var popup = new ol.Overlay(({
|
||||
element: container,
|
||||
autoPan: true,
|
||||
autoPanAnimation: {
|
||||
duration: 250
|
||||
}
|
||||
}));
|
||||
map.addOverlay(popup)
|
||||
popup.setPosition(coordinate);
|
||||
$(container).editable(function(value, settings) {
|
||||
$.ajax({
|
||||
@@ -75,6 +76,7 @@ map.on('singleclick', function (evt) {
|
||||
data: JSON.stringify({content: value, author: $('#select-user').val(), location: {type: "Point", coordinates:[coordinate[0],coordinate[1]]}}),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json"});
|
||||
popup.setPosition(undefined);
|
||||
return value;
|
||||
}, {
|
||||
type : "textarea",
|
||||
@@ -82,3 +84,35 @@ map.on('singleclick', function (evt) {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ################################# Messages layer #################################
|
||||
|
||||
var vectorSource = new ol.source.Vector({
|
||||
loader: function(extent, resolution, projection) {
|
||||
var url = '/message/bbox/' + extent[0] + "," + extent[1] + "," + extent[2] + "," + extent[3];
|
||||
$.ajax({url: url, dataType: 'json', success: function(response) {
|
||||
if (response.error) {
|
||||
alert(response.error.message + '\n' +
|
||||
response.error.details.join('\n'));
|
||||
} else {
|
||||
$.each(response, function( index, value ) {
|
||||
var feature = new ol.Feature({
|
||||
geometry: new ol.geom.Point(value.location.coordinates),
|
||||
data: value
|
||||
});
|
||||
vectorSource.addFeature(feature);
|
||||
});
|
||||
}
|
||||
}});
|
||||
},
|
||||
strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ({
|
||||
tileSize: 512
|
||||
}))
|
||||
});
|
||||
|
||||
var vector = new ol.layer.Vector({
|
||||
source: vectorSource,
|
||||
style: new ol.style.Style({image: new ol.style.Icon({src: "pig.png", scale: 0.15})}),
|
||||
});
|
||||
|
||||
map.addLayer(vector);
|
||||
|
||||
Reference in New Issue
Block a user