Skip to content

Commit

Permalink
dc clusters
Browse files Browse the repository at this point in the history
  • Loading branch information
maciejkocylapc committed Dec 3, 2024
1 parent 0f6913a commit e39b578
Show file tree
Hide file tree
Showing 8 changed files with 226 additions and 56 deletions.
30 changes: 1 addition & 29 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
@import "carousels";
@import "map";
@import "modals";
@import "data_center_map";

html {
overflow-x: hidden;
Expand All @@ -50,35 +51,6 @@ body {
}
}

#map {
height: 600px; /* The height is 400 pixels */
width: 100%; /* The width is the width of the web page */
}

#floating-panel {
position: absolute;
top: 10px;
left: 25%;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
text-align: center;
font-family: "Roboto", "sans-serif";
line-height: 30px;
padding-left: 10px;
}

#floating-panel {
background-color: #fff;
border: 1px solid #999;
left: 25%;
padding: 5px;
position: absolute;
top: 10px;
z-index: 5;
}

.background-color {
position: fixed;
z-index: -2;
Expand Down
44 changes: 44 additions & 0 deletions app/assets/stylesheets/data_center_map.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#map {
height: 600px; /* The height is 400 pixels */
width: 100%; /* The width is the width of the web page */
border-radius: 25px;
}

.data-center {
align-items: center;
background-color: #17132a;
border-radius: 50%;
color: #dedede;
display: flex;
font-size: 14px;
gap: 5px;
height: 23px;
justify-content: center;
padding: 4px;
position: relative;
position: relative;
transition: all 0.3s ease-out;
width: 23px;

.data-center-details {
display: none;
flex-direction: column;
flex: 1;
}

&.highlight {
// background-color: #FFFFFF;
border-radius: 8px;
box-shadow: 10px 10px 5px rgba(0, 0, 0, 0.2);
height: auto;
padding: 8px 15px;
width: 230px;

.data-center-details {
padding-left: 10px;
display: block;
flex-direction: column;
flex: 1;
}
}
}
11 changes: 10 additions & 1 deletion app/controllers/api/v1/data_centers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@ def index_with_nodes
end

def index_for_map
data_centers = DataCenter.joins(:data_center_stats)
data_centers = DataCenter.select(:traits_organization, :data_center_key, :location_latitude, :location_longitude, :active_validators_count, :active_validators_stake, :traits_autonomous_system_number)
.joins(:data_center_stats)
.where("data_center_stats.network = ?", map_params[:network])
.where.not(data_center_key: "0--Unknown")
# if map_params[:asn_search].present?
# data_centers = data_centers.where("data_centers.traits_autonomous_system_number = ?", map_params[:asn_search])
# end
render json: {
data_centers: data_centers
}, status: :ok
Expand Down Expand Up @@ -98,6 +103,10 @@ def data_center_stats
def dc_params
params.permit(:network, :show_gossip_nodes)
end

def map_params
params.permit(:network, :asn_search)
end
end
end
end
2 changes: 2 additions & 0 deletions app/javascript/packs/data_centers/map_component.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import Vue from 'vue/dist/vue.esm'
import TurbolinksAdapter from 'vue-turbolinks';
import MapComponent from './map_component.vue';
import store from "../stores/main_store.js";

Vue.use(TurbolinksAdapter);

document.addEventListener('turbolinks:load', () => {
new Vue({
el: '#data-center-map-component',
store,
render(createElement) {
return createElement(MapComponent)
}
Expand Down
173 changes: 147 additions & 26 deletions app/javascript/packs/data_centers/map_component.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<template>
<div class="container">
<!-- <div id="floating-panel">
<button id="toggle-heatmap">Toggle Heatmap</button>
<button id="change-gradient">Change gradient</button>
<button id="change-radius">Change radius</button>
<button id="change-opacity">Change opacity</button>
</div> -->
<div id="map"></div>
<div id="floating-panel">
<button id="toggle-heatmap" class="btn btn-xs btn-secondary" v-on:click="toggleHeatmap()">Toggle Heatmap</button>
<button id="toggle-markers" class="btn btn-xs btn-secondary" v-on:click="toggleMarkers()">Toggle Markers</button>
<input id="search-asn" v-model="asn_search" placeholder="search by asn"></input>
</div>
<div id="map" class="mt-2"></div>
</div>
</template>

<script>
import axios from 'axios';
import { mapGetters } from 'vuex';
import '../mixins/numbers_mixins'
import { MarkerClusterer } from "@googlemaps/markerclusterer";
axios.defaults.headers.get["Authorization"] = window.api_authorization;
Expand All @@ -27,7 +28,11 @@
return {
data_centers: [],
heat_points: [],
map: null
map: null,
heatmap: null,
asn_search: null,
markerClusterer: null,
markers_visible: true
}
},
Expand All @@ -36,9 +41,38 @@
this.add_markers();
},
computed: mapGetters([
'network'
]),
computed: {
...mapGetters([
'network'
]),
marker_list: function() {
if(this.markers_visible) {
return this.data_centers.map(data_center => data_center.marker);
} else {
return [];
}
}
},
watch: {
asn_search: function(new_asn, old_asn) {
if(new_asn.length > 4) {
this.data_centers.forEach(data_center => {
if (data_center.traits_autonomous_system_number == new_asn) {
data_center.marker.map = this.map;
} else {
data_center.marker.map = null;
}
this.markerClusterer.clearMarkers();
});
} else {
this.data_centers.forEach(data_center => {
data_center.marker.map = this.map;
});
this.set_up_clusterer(this.marker_list, this.map);
}
}
},
methods: {
initMap: async function() {
Expand All @@ -54,36 +88,123 @@
},
add_markers: async function() {
const { AdvancedMarkerElement } = await google.maps.importLibrary("marker");
const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker");
const infoWindow = new google.maps.InfoWindow();
axios.get('/api/v1/data-centers-for-map')
axios.get('/api/v1/data-centers-for-map?network=' + this.network)
.then(response => {
this.data_centers = response.data['data_centers'];
this.data_centers.forEach(data_center => {
let position = { lat: parseFloat(data_center.location_latitude), lng: parseFloat(data_center.location_longitude) };
this.heat_points.push(new google.maps.LatLng(position['lat'], position['lng']));
let map = this.map;
const marker = new AdvancedMarkerElement({
data_center.marker = new AdvancedMarkerElement({
position,
map,
title: data_center.data_center_key,
// content: pin.element,
title: data_center.traits_organization,
content: this.buildContent(data_center),
gmpClickable: true,
});
marker.addListener("click", ({ domEvent, latLng }) => {
const { target } = domEvent;
infoWindow.close();
infoWindow.setContent(marker.title);
infoWindow.open(marker.map, marker);
data_center.marker.addListener("click", () => {
this.toggleHighlight(data_center.marker, data_center);
});
});
const heatmap = new google.maps.visualization.HeatmapLayer({
data: this.heat_points,
map: this.map,
this.heatmap = new google.maps.visualization.HeatmapLayer({
data: this.heat_points,
map: this.map,
});
this.set_up_clusterer(this.marker_list, this.map);
});
},
set_up_clusterer: function(marker_list, map) {
this.markerClusterer && this.markerClusterer.clearMarkers();
this.markerClusterer = new MarkerClusterer( {
map: map,
markers: marker_list,
renderer: {
render: ({ markers, _position: position }) => {
const count = markers.length;
const svg = window.btoa(`
<svg fill="#17132a" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 240">
<circle cx="120" cy="120" opacity=".6" r="70" />
<circle cx="120" cy="120" opacity=".3" r="90" />
<circle cx="120" cy="120" opacity=".2" r="110" />
<circle cx="120" cy="120" opacity=".1" r="130" />
</svg>`);
return new google.maps.Marker({
position,
icon: {
url: `data:image/svg+xml;base64,${svg}`,
scaledSize: new google.maps.Size(45, 45),
},
label: {
text: String(count),
color: "rgba(255,255,255,0.9)",
fontSize: "12px",
},
zIndex: count,
});
}
}
});
},
toggleHighlight: function(marker, data_center) {
if (marker.content.classList.contains("highlight")) {
marker.content.classList.remove("highlight");
marker.zIndex = null;
} else {
marker.content.classList.add("highlight");
marker.zIndex = 1;
}
},
buildContent: function(data_center) {
const content = document.createElement("div");
content.classList.add("data-center");
content.innerHTML = `
<div class="icon">
<i class="fa-solid fa-database" aria-hidden="true"></i>
</div>
<div class="data-center-details">
<p class="h4">${data_center.traits_organization}</p>
<div class="mb-1">
<span>${data_center.data_center_key}</span>
<span class="text-muted">(${data_center.traits_autonomous_system_number})</span>
</div>
<div class="mb-1">
<span class="me-1">active stake: ${this.lamports_to_sol(data_center.active_validators_stake)} SOL</span>
</div>
<div class="mb-1">
<span class="me-1">active validators: ${data_center.active_validators_count}</span>
</div>
</div>
`;
return content;
},
toggleHeatmap: function() {
this.heatmap.setMap(this.heatmap.getMap() ? null : this.map);
},
toggleMarkers: function() {
if(this.markers_visible) {
this.asn_search = null;
this.markers_visible = false;
this.data_centers.forEach(data_center => {
data_center.marker.map = null;
});
} else {
this.markers_visible = true;
this.data_centers.forEach(data_center => {
data_center.marker.map = this.map;
});
}
this.set_up_clusterer(this.marker_list, this.map);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions app/javascript/packs/stake_accounts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ document.addEventListener('DOMContentLoaded', () => {
render(createElement) {
return createElement(IndexTemplate);
},

component: {
'StakeAccountRow': StakeAccountRow,
'StakePoolStats': StakePoolStats,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-env": "^7.24.7",
"@fortawesome/fontawesome-free": "^6.2.1",
"@googlemaps/markerclusterer": "^2.5.3",
"@rails/actioncable": "^6.1.7",
"@rails/activestorage": "^6.1.7",
"@rails/ujs": "^6.1.7",
Expand Down
Loading

0 comments on commit e39b578

Please sign in to comment.