diff --git a/app/channels/points_channel.rb b/app/channels/points_channel.rb new file mode 100644 index 00000000..8ce13209 --- /dev/null +++ b/app/channels/points_channel.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class PointsChannel < ApplicationCable::Channel + def subscribed + stream_for current_user + end +end diff --git a/app/javascript/channels/index.js b/app/javascript/channels/index.js index 79ce4754..ed929ca4 100644 --- a/app/javascript/channels/index.js +++ b/app/javascript/channels/index.js @@ -1,2 +1,3 @@ // Import all the channels to be used by Action Cable import "notifications_channel" +import "points_channel" diff --git a/app/javascript/channels/points_channel.js b/app/javascript/channels/points_channel.js new file mode 100644 index 00000000..17b0b5d1 --- /dev/null +++ b/app/javascript/channels/points_channel.js @@ -0,0 +1,15 @@ +import consumer from "./consumer" + +consumer.subscriptions.create("PointsChannel", { + connected() { + // Called when the subscription is ready for use on the server + }, + + disconnected() { + // Called when the subscription has been terminated by the server + }, + + received(data) { + // Called when there's incoming data on the websocket for this channel + } +}); diff --git a/app/javascript/controllers/maps_controller.js b/app/javascript/controllers/maps_controller.js index 8a3f31b1..6ca50260 100644 --- a/app/javascript/controllers/maps_controller.js +++ b/app/javascript/controllers/maps_controller.js @@ -1,6 +1,7 @@ import { Controller } from "@hotwired/stimulus"; import L from "leaflet"; import "leaflet.heat"; +import consumer from "../channels/consumer"; // Add this import import { createMarkersArray } from "../maps/markers"; @@ -138,12 +139,92 @@ export default class extends Controller { this.map.removeControl(this.drawControl); } }); + + this.setupSubscription(); // Add this line } disconnect() { this.map.remove(); } + setupSubscription() { + consumer.subscriptions.create("PointsChannel", { + received: (data) => { + this.appendPoint(data); + } + }); + } + + appendPoint(data) { + // Parse the received point data + console.log(data) + const newPoint = data; + + // Add the new point to the markers array + this.markers.push(newPoint); + + // Create a new marker for the point + const markerOptions = { + ...this.userSettings, // Pass any relevant settings + id: newPoint[6], // Assuming index 6 contains the point ID + timestamp: newPoint[4] // Assuming index 2 contains the timestamp + }; + + const newMarker = this.createMarker(newPoint, markerOptions); + this.markersArray.push(newMarker); + + // Update the markers layer + this.markersLayer.clearLayers(); + this.markersLayer.addLayer(L.layerGroup(this.markersArray)); + + // Update heatmap + this.heatmapMarkers.push([newPoint[0], newPoint[1], 0.2]); + this.heatmapLayer.setLatLngs(this.heatmapMarkers); + + // Update polylines + this.polylinesLayer.clearLayers(); + this.polylinesLayer = createPolylinesLayer( + this.markers, + this.map, + this.timezone, + this.routeOpacity, + this.userSettings + ); + + // Pan map to new location + this.map.setView([newPoint[0], newPoint[1]], 14); + + // Update fog of war if enabled + if (this.map.hasLayer(this.fogOverlay)) { + this.updateFog(this.markers, this.clearFogRadius); + } + + // Update the last marker + this.map.eachLayer((layer) => { + if (layer instanceof L.Marker && !layer._popup) { + this.map.removeLayer(layer); + } + }); + this.addLastMarker(this.map, this.markers); + } + + createMarker(point, options) { + const marker = L.marker([point[0], point[1]]); + + // Add popup content based on point data + const popupContent = ` +
Time: ${new Date(point[2]).toLocaleString()}
+ ${point[3] ? `Address: ${point[3]}
` : ''} + ${point[7] ? `Country: ${point[7]}
` : ''} + Delete +