web-mojo 2.2.9 → 2.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.cjs.js.map +1 -1
- package/dist/admin.es.js +825 -6
- package/dist/admin.es.js.map +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +2 -2
- package/dist/chunks/{MetricsMiniChartWidget-Cg5Hyx28.js → MetricsMiniChartWidget-DL5stA6A.js} +31 -9
- package/dist/chunks/MetricsMiniChartWidget-DL5stA6A.js.map +1 -0
- package/dist/chunks/{MetricsMiniChartWidget-DNIU3bL-.js → MetricsMiniChartWidget-vXr5pxpm.js} +2 -2
- package/dist/chunks/{MetricsMiniChartWidget-DNIU3bL-.js.map → MetricsMiniChartWidget-vXr5pxpm.js.map} +1 -1
- package/dist/chunks/{version-CHVtoVR0.js → version-DOHckOGK.js} +4 -4
- package/dist/chunks/version-DOHckOGK.js.map +1 -0
- package/dist/chunks/version-DUvrBxZl.js +2 -0
- package/dist/chunks/version-DUvrBxZl.js.map +1 -0
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/MetricsMiniChartWidget-Cg5Hyx28.js.map +0 -1
- package/dist/chunks/version-BlWcQoar.js +0 -2
- package/dist/chunks/version-BlWcQoar.js.map +0 -1
- package/dist/chunks/version-CHVtoVR0.js.map +0 -1
package/dist/admin.es.js
CHANGED
|
@@ -3,14 +3,14 @@ import { V as View, M as MOJOUtils, r as rest } from "./chunks/Rest-ChN4Ntac.js"
|
|
|
3
3
|
import "./chunks/WebSocketClient-bLYhu2Wv.js";
|
|
4
4
|
import { D as Dialog$1 } from "./chunks/Dialog-Cu_Dx46k.js";
|
|
5
5
|
import { W } from "./chunks/Dialog-Cu_Dx46k.js";
|
|
6
|
-
import { M as MetricsChart, c as MetricsMiniChartWidget, P as PieChart } from "./chunks/MetricsMiniChartWidget-
|
|
6
|
+
import { M as MetricsChart, c as MetricsMiniChartWidget, P as PieChart } from "./chunks/MetricsMiniChartWidget-DL5stA6A.js";
|
|
7
7
|
import { aj as MemberList, T as TableView, B as IncidentEventList, ap as PushDeviceList, ai as LogList, c as TabView, b as TablePage, M as Member, ak as MemberForms, ay as GeoLocatedIP, az as GeoLocatedIPList, aB as TicketList, J as IncidentList, a0 as IncidentStats, V as IncidentHistoryList, U as IncidentHistory, H as Incident, C as ChatView, K as IncidentForms, I as IncidentEvent, G as IncidentEventForms, aD as TicketNoteList, aC as TicketNote, aA as Ticket, aE as TicketForms, aF as TicketCategories, W as RuleSet, a2 as MatchByOptions, a1 as BundleByOptions, _ as RuleList, X as RuleSetList, k as EmailDomainForms, j as EmailDomainList, E as EmailDomain, n as MailboxForms, m as MailboxList, l as Mailbox, s as EmailTemplate, u as EmailTemplateForms, t as EmailTemplateList, o as SentMessage, q as SentMessageList, av as PushDeliveryList, aw as PushConfigForms, at as PushConfigList, ax as PushTemplateForms, ar as PushTemplateList, a6 as Job, ac as JobEventList, aa as JobLogList, a8 as JobForms, a7 as JobList, af as JobRunnerList, ad as JobsEngineStats, ag as JobRunnerForms, ae as JobRunner, ah as Log, al as MetricsPermission, an as MetricsForms, am as MetricsPermissionList, x as FileManagerForms, w as FileManagerList, y as File, A as FileForms, z as FileList, i as S3BucketForms, h as S3BucketList } from "./chunks/ChatView-DfhhZKoN.js";
|
|
8
8
|
import DataView from "./chunks/DataView-i7kpJjVQ.js";
|
|
9
9
|
import { F as FormView, a as applyFileDropMixin } from "./chunks/FormView-B_90L1RY.js";
|
|
10
10
|
import { MapView } from "./map.es.js";
|
|
11
11
|
import { M as Model, C as Collection } from "./chunks/Collection-G5_fJcpB.js";
|
|
12
12
|
import { L as LightboxGallery, P as PDFViewer } from "./chunks/PDFViewer--jlqnuVw.js";
|
|
13
|
-
import { B, a, V, b, c, d } from "./chunks/version-
|
|
13
|
+
import { B, a, V, b, c, d } from "./chunks/version-DOHckOGK.js";
|
|
14
14
|
class AdminHeaderView extends View {
|
|
15
15
|
constructor(options = {}) {
|
|
16
16
|
super({
|
|
@@ -2249,6 +2249,795 @@ class GeoLocatedIPTablePage extends TablePage {
|
|
|
2249
2249
|
}
|
|
2250
2250
|
}
|
|
2251
2251
|
}
|
|
2252
|
+
class MapLibreView extends View {
|
|
2253
|
+
constructor(options = {}) {
|
|
2254
|
+
super({
|
|
2255
|
+
className: "maplibre-view",
|
|
2256
|
+
...options
|
|
2257
|
+
});
|
|
2258
|
+
this.markers = options.markers || [];
|
|
2259
|
+
this.center = options.center || null;
|
|
2260
|
+
this.zoom = options.zoom || 13;
|
|
2261
|
+
this.height = options.height || 400;
|
|
2262
|
+
this.pitch = options.pitch || 0;
|
|
2263
|
+
this.bearing = options.bearing || 0;
|
|
2264
|
+
this.mapStyle = options.style || "streets";
|
|
2265
|
+
this.showNavigationControl = options.showNavigationControl !== false;
|
|
2266
|
+
this.autoFitBounds = options.autoFitBounds !== false;
|
|
2267
|
+
this.map = null;
|
|
2268
|
+
this.mapMarkers = [];
|
|
2269
|
+
this.pendingMarkers = [...this.markers];
|
|
2270
|
+
this.lineSources = options.lineSources || [];
|
|
2271
|
+
this.pendingLineData = /* @__PURE__ */ new Map();
|
|
2272
|
+
this.template = `
|
|
2273
|
+
<div class="maplibre-container">
|
|
2274
|
+
<div id="maplibre-{{id}}" style="height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;"></div>
|
|
2275
|
+
</div>
|
|
2276
|
+
`;
|
|
2277
|
+
}
|
|
2278
|
+
async onAfterRender() {
|
|
2279
|
+
await this.loadMapLibre();
|
|
2280
|
+
await this.initializeMap();
|
|
2281
|
+
}
|
|
2282
|
+
async loadMapLibre() {
|
|
2283
|
+
if (window.maplibregl) return;
|
|
2284
|
+
const link = document.createElement("link");
|
|
2285
|
+
link.rel = "stylesheet";
|
|
2286
|
+
link.href = "https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css";
|
|
2287
|
+
document.head.appendChild(link);
|
|
2288
|
+
return new Promise((resolve, reject) => {
|
|
2289
|
+
const script = document.createElement("script");
|
|
2290
|
+
script.src = "https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js";
|
|
2291
|
+
script.onload = resolve;
|
|
2292
|
+
script.onerror = reject;
|
|
2293
|
+
document.head.appendChild(script);
|
|
2294
|
+
});
|
|
2295
|
+
}
|
|
2296
|
+
getMapStyle() {
|
|
2297
|
+
const styles = {
|
|
2298
|
+
streets: "https://demotiles.maplibre.org/style.json",
|
|
2299
|
+
dark: {
|
|
2300
|
+
version: 8,
|
|
2301
|
+
sources: {
|
|
2302
|
+
osm: {
|
|
2303
|
+
type: "raster",
|
|
2304
|
+
tiles: ["https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"],
|
|
2305
|
+
tileSize: 256,
|
|
2306
|
+
attribution: "© OpenStreetMap contributors"
|
|
2307
|
+
}
|
|
2308
|
+
},
|
|
2309
|
+
layers: [{
|
|
2310
|
+
id: "osm",
|
|
2311
|
+
type: "raster",
|
|
2312
|
+
source: "osm"
|
|
2313
|
+
}],
|
|
2314
|
+
glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf"
|
|
2315
|
+
},
|
|
2316
|
+
light: {
|
|
2317
|
+
version: 8,
|
|
2318
|
+
sources: {
|
|
2319
|
+
osm: {
|
|
2320
|
+
type: "raster",
|
|
2321
|
+
tiles: ["https://a.tile.openstreetmap.org/{z}/{x}/{y}.png"],
|
|
2322
|
+
tileSize: 256,
|
|
2323
|
+
attribution: "© OpenStreetMap contributors"
|
|
2324
|
+
}
|
|
2325
|
+
},
|
|
2326
|
+
layers: [{
|
|
2327
|
+
id: "osm",
|
|
2328
|
+
type: "raster",
|
|
2329
|
+
source: "osm"
|
|
2330
|
+
}],
|
|
2331
|
+
glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf"
|
|
2332
|
+
},
|
|
2333
|
+
satellite: {
|
|
2334
|
+
version: 8,
|
|
2335
|
+
sources: {
|
|
2336
|
+
satellite: {
|
|
2337
|
+
type: "raster",
|
|
2338
|
+
tiles: ["https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"],
|
|
2339
|
+
tileSize: 256,
|
|
2340
|
+
attribution: "© Esri"
|
|
2341
|
+
}
|
|
2342
|
+
},
|
|
2343
|
+
layers: [{
|
|
2344
|
+
id: "satellite",
|
|
2345
|
+
type: "raster",
|
|
2346
|
+
source: "satellite"
|
|
2347
|
+
}],
|
|
2348
|
+
glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf"
|
|
2349
|
+
},
|
|
2350
|
+
terrain: {
|
|
2351
|
+
version: 8,
|
|
2352
|
+
sources: {
|
|
2353
|
+
terrain: {
|
|
2354
|
+
type: "raster",
|
|
2355
|
+
tiles: ["https://a.tile.opentopomap.org/{z}/{x}/{y}.png"],
|
|
2356
|
+
tileSize: 256,
|
|
2357
|
+
attribution: "© OpenTopoMap contributors"
|
|
2358
|
+
}
|
|
2359
|
+
},
|
|
2360
|
+
layers: [{
|
|
2361
|
+
id: "terrain",
|
|
2362
|
+
type: "raster",
|
|
2363
|
+
source: "terrain"
|
|
2364
|
+
}],
|
|
2365
|
+
glyphs: "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf"
|
|
2366
|
+
}
|
|
2367
|
+
};
|
|
2368
|
+
return styles[this.mapStyle] || styles.streets;
|
|
2369
|
+
}
|
|
2370
|
+
async initializeMap() {
|
|
2371
|
+
const mapElement = this.element.querySelector(`#maplibre-${this.id}`);
|
|
2372
|
+
if (!mapElement || !window.maplibregl) return;
|
|
2373
|
+
let mapCenter = this.center;
|
|
2374
|
+
if (!mapCenter && this.markers.length > 0) {
|
|
2375
|
+
mapCenter = [this.markers[0].lng, this.markers[0].lat];
|
|
2376
|
+
}
|
|
2377
|
+
if (!mapCenter) {
|
|
2378
|
+
mapCenter = [0, 0];
|
|
2379
|
+
}
|
|
2380
|
+
this.map = new window.maplibregl.Map({
|
|
2381
|
+
container: mapElement,
|
|
2382
|
+
style: this.getMapStyle(),
|
|
2383
|
+
center: mapCenter,
|
|
2384
|
+
zoom: this.zoom,
|
|
2385
|
+
pitch: this.pitch,
|
|
2386
|
+
bearing: this.bearing
|
|
2387
|
+
});
|
|
2388
|
+
if (this.showNavigationControl) {
|
|
2389
|
+
this.map.addControl(new window.maplibregl.NavigationControl(), "top-right");
|
|
2390
|
+
}
|
|
2391
|
+
this.map.on("load", () => {
|
|
2392
|
+
const initialMarkers = this.pendingMarkers.length ? this.pendingMarkers : this.markers;
|
|
2393
|
+
this.updateMarkers(initialMarkers);
|
|
2394
|
+
this.lineSources.forEach((source) => this.addLineSource(source));
|
|
2395
|
+
this.pendingLineData.forEach((source) => this.addLineSource(source));
|
|
2396
|
+
this.pendingLineData.clear();
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
addMarkers(markers) {
|
|
2400
|
+
if (!this.map || !Array.isArray(markers)) {
|
|
2401
|
+
this.pendingMarkers = Array.isArray(markers) ? markers : [];
|
|
2402
|
+
return;
|
|
2403
|
+
}
|
|
2404
|
+
markers.forEach((markerData) => {
|
|
2405
|
+
const { lng, lat, popup, color, icon, size } = markerData;
|
|
2406
|
+
if (!lng || !lat) return;
|
|
2407
|
+
const el = document.createElement("div");
|
|
2408
|
+
el.className = "maplibre-marker";
|
|
2409
|
+
const markerSize = Number(size) || 30;
|
|
2410
|
+
el.style.width = `${markerSize}px`;
|
|
2411
|
+
el.style.height = `${markerSize}px`;
|
|
2412
|
+
el.style.borderRadius = "50%";
|
|
2413
|
+
el.style.backgroundColor = color || "#3b82f6";
|
|
2414
|
+
el.style.border = "3px solid white";
|
|
2415
|
+
el.style.boxShadow = "0 2px 4px rgba(0,0,0,0.3)";
|
|
2416
|
+
el.style.cursor = "pointer";
|
|
2417
|
+
el.style.display = "flex";
|
|
2418
|
+
el.style.alignItems = "center";
|
|
2419
|
+
el.style.justifyContent = "center";
|
|
2420
|
+
if (icon) {
|
|
2421
|
+
el.innerHTML = `<i class="${icon}" style="color: white;"></i>`;
|
|
2422
|
+
}
|
|
2423
|
+
const marker = new window.maplibregl.Marker({ element: el }).setLngLat([lng, lat]).addTo(this.map);
|
|
2424
|
+
if (popup) {
|
|
2425
|
+
const mapPopup = new window.maplibregl.Popup({ offset: 25 }).setHTML(popup);
|
|
2426
|
+
marker.setPopup(mapPopup);
|
|
2427
|
+
}
|
|
2428
|
+
this.mapMarkers.push(marker);
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2431
|
+
fitBounds() {
|
|
2432
|
+
if (!this.map || this.markers.length === 0) return;
|
|
2433
|
+
const bounds = new window.maplibregl.LngLatBounds();
|
|
2434
|
+
this.markers.forEach((marker) => {
|
|
2435
|
+
bounds.extend([marker.lng, marker.lat]);
|
|
2436
|
+
});
|
|
2437
|
+
this.map.fitBounds(bounds, {
|
|
2438
|
+
padding: 50,
|
|
2439
|
+
maxZoom: 15
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
updateMarkers(newMarkers) {
|
|
2443
|
+
const markers = Array.isArray(newMarkers) ? newMarkers : [];
|
|
2444
|
+
this.markers = markers;
|
|
2445
|
+
this.pendingMarkers = markers;
|
|
2446
|
+
if (!this.map) return;
|
|
2447
|
+
this.clearMarkers();
|
|
2448
|
+
this.addMarkers(markers);
|
|
2449
|
+
if (this.autoFitBounds && markers.length > 1) {
|
|
2450
|
+
this.fitBounds();
|
|
2451
|
+
} else if (markers.length === 1 && this.map) {
|
|
2452
|
+
this.map.flyTo({
|
|
2453
|
+
center: [markers[0].lng, markers[0].lat],
|
|
2454
|
+
zoom: this.zoom
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
clearMarkers() {
|
|
2459
|
+
this.mapMarkers.forEach((marker) => {
|
|
2460
|
+
marker.remove();
|
|
2461
|
+
});
|
|
2462
|
+
this.mapMarkers = [];
|
|
2463
|
+
}
|
|
2464
|
+
addLineSource({ id, data, paint, layout }) {
|
|
2465
|
+
if (!id || !data) return;
|
|
2466
|
+
const sourceId = `${id}-source`;
|
|
2467
|
+
if (!this.map) {
|
|
2468
|
+
this.pendingLineData.set(id, { id, data, paint, layout });
|
|
2469
|
+
return;
|
|
2470
|
+
}
|
|
2471
|
+
if (this.map.getLayer(id)) {
|
|
2472
|
+
this.map.removeLayer(id);
|
|
2473
|
+
}
|
|
2474
|
+
if (this.map.getSource(sourceId)) {
|
|
2475
|
+
this.map.removeSource(sourceId);
|
|
2476
|
+
}
|
|
2477
|
+
this.map.addSource(sourceId, {
|
|
2478
|
+
type: "geojson",
|
|
2479
|
+
data
|
|
2480
|
+
});
|
|
2481
|
+
this.map.addLayer({
|
|
2482
|
+
id,
|
|
2483
|
+
type: "line",
|
|
2484
|
+
source: sourceId,
|
|
2485
|
+
paint: {
|
|
2486
|
+
"line-color": "#3b82f6",
|
|
2487
|
+
"line-width": 2,
|
|
2488
|
+
"line-opacity": 0.6,
|
|
2489
|
+
...paint
|
|
2490
|
+
},
|
|
2491
|
+
layout: {
|
|
2492
|
+
"line-cap": "round",
|
|
2493
|
+
"line-join": "round",
|
|
2494
|
+
...layout
|
|
2495
|
+
}
|
|
2496
|
+
});
|
|
2497
|
+
}
|
|
2498
|
+
updateLineSource(id, { data, paint, layout } = {}) {
|
|
2499
|
+
if (!id || !data) return;
|
|
2500
|
+
const sourceId = `${id}-source`;
|
|
2501
|
+
if (!this.map) {
|
|
2502
|
+
this.pendingLineData.set(id, { id, data, paint, layout });
|
|
2503
|
+
return;
|
|
2504
|
+
}
|
|
2505
|
+
if (this.map.getSource(sourceId)) {
|
|
2506
|
+
this.map.getSource(sourceId).setData(data);
|
|
2507
|
+
if (paint || layout) {
|
|
2508
|
+
if (paint) {
|
|
2509
|
+
Object.entries(paint).forEach(([key, value]) => {
|
|
2510
|
+
this.map.setPaintProperty(id, key, value);
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
if (layout) {
|
|
2514
|
+
Object.entries(layout).forEach(([key, value]) => {
|
|
2515
|
+
this.map.setLayoutProperty(id, key, value);
|
|
2516
|
+
});
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
} else {
|
|
2520
|
+
this.addLineSource({ id, data, paint, layout });
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
setView(lng, lat, zoom = null) {
|
|
2524
|
+
if (!this.map) return;
|
|
2525
|
+
this.map.flyTo({
|
|
2526
|
+
center: [lng, lat],
|
|
2527
|
+
zoom: zoom || this.zoom
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
setZoom(zoom) {
|
|
2531
|
+
if (!this.map) return;
|
|
2532
|
+
this.map.setZoom(zoom);
|
|
2533
|
+
}
|
|
2534
|
+
setPitch(pitch) {
|
|
2535
|
+
if (!this.map) return;
|
|
2536
|
+
this.map.setPitch(pitch);
|
|
2537
|
+
}
|
|
2538
|
+
setBearing(bearing) {
|
|
2539
|
+
if (!this.map) return;
|
|
2540
|
+
this.map.setBearing(bearing);
|
|
2541
|
+
}
|
|
2542
|
+
async onBeforeDestroy() {
|
|
2543
|
+
if (this.map) {
|
|
2544
|
+
this.map.remove();
|
|
2545
|
+
this.map = null;
|
|
2546
|
+
}
|
|
2547
|
+
await super.onBeforeDestroy();
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
const COUNTRY_CENTROIDS = {
|
|
2551
|
+
"AD": { name: "Andorra", lat: 42.54859834854764, lng: 1.5802243611232873 },
|
|
2552
|
+
"AE": { name: "United Arab Emirates", lat: 24.18250292309135, lng: 54.27920525789581 },
|
|
2553
|
+
"AF": { name: "Afghanistan", lat: 34.13402601376932, lng: 66.59216131095278 },
|
|
2554
|
+
"AG": { name: "Antigua and Barbuda", lat: 17.07146759372967, lng: -61.78530823226373 },
|
|
2555
|
+
"AI": { name: "Anguilla", lat: 18.222874004219086, lng: -63.06008343771806 },
|
|
2556
|
+
"AL": { name: "Albania", lat: 41.14165894891656, lng: 20.061082767269493 },
|
|
2557
|
+
"AM": { name: "Armenia", lat: 40.17841274230679, lng: 45.05490831965259 },
|
|
2558
|
+
"AO": { name: "Angola", lat: -12.167424062667942, lng: 17.651768783079 },
|
|
2559
|
+
"AQ": { name: "Antarctica", lat: -77.16987521415838, lng: -177.56451613408842 },
|
|
2560
|
+
"AR": { name: "Argentina", lat: -35.697270518120085, lng: -64.53238503843076 },
|
|
2561
|
+
"AS": { name: "American Samoa", lat: -14.305711987770538, lng: -170.7007316174498 },
|
|
2562
|
+
"AT": { name: "Austria", lat: 47.631858269895794, lng: 13.797778364631036 },
|
|
2563
|
+
"AU": { name: "Australia", lat: -25.697337673983082, lng: 134.02277170916162 },
|
|
2564
|
+
"AW": { name: "Aruba", lat: 12.515625722992898, lng: -69.97564014284046 },
|
|
2565
|
+
"AZ": { name: "Azerbaijan", lat: 40.3920509942049, lng: 48.634592670644324 },
|
|
2566
|
+
"BA": { name: "Bosnia and Herzegovina", lat: 44.14415356126429, lng: 17.83467240787538 },
|
|
2567
|
+
"BB": { name: "Barbados", lat: 13.183219369337529, lng: -59.557383949150285 },
|
|
2568
|
+
"BD": { name: "Bangladesh", lat: 23.673728665121, lng: 90.43212562608613 },
|
|
2569
|
+
"BE": { name: "Belgium", lat: 50.6182138854095, lng: 4.675010154696485 },
|
|
2570
|
+
"BF": { name: "Burkina Faso", lat: 12.108709036312737, lng: -1.6932816211842325 },
|
|
2571
|
+
"BG": { name: "Bulgaria", lat: 42.82043677302438, lng: 25.251739122561908 },
|
|
2572
|
+
"BH": { name: "Bahrain", lat: 26.04798501537066, lng: 50.540695402276775 },
|
|
2573
|
+
"BI": { name: "Burundi", lat: -3.261251993278643, lng: 29.88518227845293 },
|
|
2574
|
+
"BJ": { name: "Benin", lat: 9.503013199615893, lng: 2.305714528830206 },
|
|
2575
|
+
"BL": { name: "Saint Barthelemy", lat: 17.90561691241738, lng: -62.83051610005156 },
|
|
2576
|
+
"BM": { name: "Bermuda", lat: 32.315067430740726, lng: -64.7458500599169 },
|
|
2577
|
+
"BN": { name: "Brunei Darussalam", lat: 4.543205889917609, lng: 114.6430958360464 },
|
|
2578
|
+
"BO": { name: "Bolivia", lat: -16.7312488393574, lng: -64.45209597511206 },
|
|
2579
|
+
"BQ": { name: "Bonaire", lat: 12.180844982440338, lng: -68.29350445958761 },
|
|
2580
|
+
"BQ": { name: "Saba", lat: 17.632512616389718, lng: -63.23739481909494 },
|
|
2581
|
+
"BQ": { name: "Saint Eustatius", lat: 17.4919042294197, lng: -62.978230589445026 },
|
|
2582
|
+
"BR": { name: "Brazil", lat: -11.524630416426652, lng: -54.355206608256424 },
|
|
2583
|
+
"BS": { name: "Bahamas", lat: 24.72162633646784, lng: -78.07275370060313 },
|
|
2584
|
+
"BT": { name: "Bhutan", lat: 27.42163933959824, lng: 90.46716647173861 },
|
|
2585
|
+
"BV": { name: "Bouvet Island", lat: -54.42316679395248, lng: 3.411969465057627 },
|
|
2586
|
+
"BW": { name: "Botswana", lat: -22.236609002062902, lng: 23.85779956995608 },
|
|
2587
|
+
"BY": { name: "Belarus", lat: 53.46791374543163, lng: 27.964252054715104 },
|
|
2588
|
+
"BZ": { name: "Belize", lat: 17.24252476647155, lng: -88.68273510023441 },
|
|
2589
|
+
"CA": { name: "Canada", lat: 57.550480044655636, lng: -98.41680517868062 },
|
|
2590
|
+
"CC": { name: "Cocos Islands", lat: -12.171249450199545, lng: 96.83688767323002 },
|
|
2591
|
+
"CD": { name: "Congo DRC", lat: -3.338629596207896, lng: 23.419827574282188 },
|
|
2592
|
+
"CF": { name: "Central African Republic", lat: 6.331390033944319, lng: 20.520743419397256 },
|
|
2593
|
+
"CG": { name: "Congo", lat: -0.7294391595233845, lng: 14.879732849491393 },
|
|
2594
|
+
"CH": { name: "Switzerland", lat: 46.73678128684938, lng: 8.286928794895285 },
|
|
2595
|
+
"CI": { name: "Côte d'Ivoire", lat: 7.536779279421307, lng: -5.571710194917734 },
|
|
2596
|
+
"CK": { name: "Cook Islands", lat: -21.222613253399842, lng: -159.78768870952257 },
|
|
2597
|
+
"CL": { name: "Chile", lat: -37.82938283049967, lng: -70.76863431739216 },
|
|
2598
|
+
"CM": { name: "Cameroon", lat: 6.294168487480992, lng: 12.948474142398263 },
|
|
2599
|
+
"CN": { name: "China", lat: 38.07325481105728, lng: 104.69113855849604 },
|
|
2600
|
+
"CO": { name: "Colombia", lat: 4.187753877352739, lng: -72.6445066243485 },
|
|
2601
|
+
"CR": { name: "Costa Rica", lat: 9.863467407406214, lng: -84.14673625701816 },
|
|
2602
|
+
"CU": { name: "Cuba", lat: 21.476176522869448, lng: -79.69817857618705 },
|
|
2603
|
+
"CV": { name: "Cabo Verde", lat: 15.076411518651643, lng: -23.63401005900474 },
|
|
2604
|
+
"CW": { name: "Curacao", lat: 12.199996647939832, lng: -68.96939768599042 },
|
|
2605
|
+
"CX": { name: "Christmas Island", lat: -10.446440802183416, lng: 105.70209512200549 },
|
|
2606
|
+
"CY": { name: "Cyprus", lat: 35.11700416345239, lng: 33.375346009199205 },
|
|
2607
|
+
"CZ": { name: "Czech Republic", lat: 49.74917370930982, lng: 15.383273292023533 },
|
|
2608
|
+
"DE": { name: "Germany", lat: 51.08304539800482, lng: 10.426171427430804 },
|
|
2609
|
+
"DJ": { name: "Djibouti", lat: 11.750235727618804, lng: 42.613496898789506 },
|
|
2610
|
+
"DK": { name: "Denmark", lat: 56.00118817971057, lng: 9.378670542409406 },
|
|
2611
|
+
"DM": { name: "Dominica", lat: 15.429269860940513, lng: -61.360471946942994 },
|
|
2612
|
+
"DO": { name: "Dominican Republic", lat: 18.77954818522993, lng: -70.43495198520012 },
|
|
2613
|
+
"DZ": { name: "Algeria", lat: 28.350969744889056, lng: 2.6558464719769135 },
|
|
2614
|
+
"EC": { name: "Ecuador", lat: -1.5642721388853116, lng: -78.4630326109714 },
|
|
2615
|
+
"EE": { name: "Estonia", lat: 58.648108311231034, lng: 25.916870250633806 },
|
|
2616
|
+
"EG": { name: "Egypt", lat: 26.60517034450628, lng: 30.240135435012338 },
|
|
2617
|
+
"ER": { name: "Eritrea", lat: 15.005533147667684, lng: 39.2672401449901 },
|
|
2618
|
+
"ES": { name: "Spain", lat: 40.365008336683836, lng: -3.6516251409956983 },
|
|
2619
|
+
"ES": { name: "Canarias", lat: 28.297665106525546, lng: -16.53799441021647 },
|
|
2620
|
+
"ET": { name: "Ethiopia", lat: 8.729389557048396, lng: 39.914902886544276 },
|
|
2621
|
+
"FI": { name: "Finland", lat: 65.01578959749911, lng: 25.65738433454702 },
|
|
2622
|
+
"FJ": { name: "Fiji", lat: -17.822470952336204, lng: 177.98144613732626 },
|
|
2623
|
+
"FK": { name: "Falkland Islands", lat: -51.75901312766726, lng: -58.746646363799854 },
|
|
2624
|
+
"FM": { name: "Micronesia", lat: 6.8789448129255435, lng: 158.2291899444527 },
|
|
2625
|
+
"FO": { name: "Faroe Islands", lat: 62.130896281495346, lng: -6.9811060913122835 },
|
|
2626
|
+
"FR": { name: "France", lat: 46.6423682169416, lng: 2.1940236627886227 },
|
|
2627
|
+
"GA": { name: "Gabon", lat: -0.628448459921234, lng: 11.839410898545754 },
|
|
2628
|
+
"GB": { name: "United Kingdom", lat: 53.97844735080214, lng: -2.852943909329258 },
|
|
2629
|
+
"GD": { name: "Grenada", lat: 12.112926656338907, lng: -61.67937937204098 },
|
|
2630
|
+
"GE": { name: "Georgia", lat: 42.17986277737226, lng: 43.378866534112234 },
|
|
2631
|
+
"GF": { name: "French Guiana", lat: 3.857429742497078, lng: -53.32232307156624 },
|
|
2632
|
+
"GG": { name: "Guernsey", lat: 49.45870771378872, lng: -2.576392582891568 },
|
|
2633
|
+
"GH": { name: "Ghana", lat: 7.94530467243628, lng: -1.219233362526581 },
|
|
2634
|
+
"GI": { name: "Gibraltar", lat: 36.14022671336082, lng: -5.345549484594358 },
|
|
2635
|
+
"GL": { name: "Greenland", lat: 74.16847218965994, lng: -42.07567788066985 },
|
|
2636
|
+
"GM": { name: "Gambia", lat: 13.428617959189328, lng: -15.383380385869662 },
|
|
2637
|
+
"GN": { name: "Guinea", lat: 10.255986541378112, lng: -10.986948848040218 },
|
|
2638
|
+
"GP": { name: "Guadeloupe", lat: 16.24420002705553, lng: -61.54382262282755 },
|
|
2639
|
+
"GQ": { name: "Equatorial Guinea", lat: 1.5954643936590733, lng: 10.425456672353823 },
|
|
2640
|
+
"GR": { name: "Greece", lat: 39.42012261727978, lng: 23.110368936161876 },
|
|
2641
|
+
"GS": { name: "South Georgia and South Sandwich Islands", lat: -54.37666443862139, lng: -36.77509575898928 },
|
|
2642
|
+
"GT": { name: "Guatemala", lat: 15.820878515352684, lng: -90.31219349119617 },
|
|
2643
|
+
"GU": { name: "Guam", lat: 13.445430479945276, lng: 144.78024458298802 },
|
|
2644
|
+
"GW": { name: "Guinea-Bissau", lat: 11.980075324820504, lng: -14.980186756910847 },
|
|
2645
|
+
"GY": { name: "Guyana", lat: 4.68211981385056, lng: -58.91352612754667 },
|
|
2646
|
+
"HM": { name: "Heard Island and McDonald Islands", lat: -53.084170035513736, lng: 73.49298560844045 },
|
|
2647
|
+
"HN": { name: "Honduras", lat: 14.740370695750006, lng: -86.49251679006962 },
|
|
2648
|
+
"HR": { name: "Croatia", lat: 44.91192100856702, lng: 16.625761129583374 },
|
|
2649
|
+
"HT": { name: "Haiti", lat: 18.883520486983567, lng: -72.89291379842 },
|
|
2650
|
+
"HU": { name: "Hungary", lat: 47.22527332486294, lng: 19.39620048366142 },
|
|
2651
|
+
"ID": { name: "Indonesia", lat: 0.15591979959037652, lng: 113.96538246847302 },
|
|
2652
|
+
"IE": { name: "Ireland", lat: 53.30489539816495, lng: -8.241128545554096 },
|
|
2653
|
+
"IL": { name: "Israel", lat: 31.513542220043195, lng: 35.027923472437024 },
|
|
2654
|
+
"IM": { name: "Isle of Man", lat: 54.22855301008011, lng: -4.532995055468449 },
|
|
2655
|
+
"IN": { name: "India", lat: 23.586300567746722, lng: 81.17300408530181 },
|
|
2656
|
+
"IO": { name: "British Indian Ocean Territory", lat: -7.323548444385743, lng: 72.43501618476016 },
|
|
2657
|
+
"IQ": { name: "Iraq", lat: 33.105075667527906, lng: 43.832529181056884 },
|
|
2658
|
+
"IR": { name: "Iran", lat: 32.906023742890056, lng: 54.237077001065444 },
|
|
2659
|
+
"IS": { name: "Iceland", lat: 65.12360920205514, lng: -19.05682967106099 },
|
|
2660
|
+
"IT": { name: "Italy", lat: 42.98201127614267, lng: 12.763657166123137 },
|
|
2661
|
+
"JE": { name: "Jersey", lat: 49.215396925724306, lng: -2.1291601162653575 },
|
|
2662
|
+
"JM": { name: "Jamaica", lat: 18.12207889341651, lng: -77.30358894542778 },
|
|
2663
|
+
"JO": { name: "Jordan", lat: 31.387064884449156, lng: 36.95728884547246 },
|
|
2664
|
+
"JP": { name: "Japan", lat: 36.76738832597829, lng: 137.46934234351835 },
|
|
2665
|
+
"KE": { name: "Kenya", lat: 0.6899182318376179, lng: 37.95309411262371 },
|
|
2666
|
+
"KG": { name: "Kyrgyzstan", lat: 41.35698905438358, lng: 74.17532903468319 },
|
|
2667
|
+
"KH": { name: "Cambodia", lat: 12.699186865507775, lng: 105.03973078680701 },
|
|
2668
|
+
"KI": { name: "Kiribati", lat: 1.8676673749241066, lng: -157.39024189323504 },
|
|
2669
|
+
"KM": { name: "Comoros", lat: -11.658861474508491, lng: 43.34826587429403 },
|
|
2670
|
+
"KN": { name: "Saint Kitts and Nevis", lat: 17.314736299587768, lng: -62.74560385895787 },
|
|
2671
|
+
"KP": { name: "North Korea", lat: 40.19198091470839, lng: 127.3379805653744 },
|
|
2672
|
+
"KR": { name: "South Korea", lat: 36.402386712544114, lng: 127.76224551357649 },
|
|
2673
|
+
"KW": { name: "Kuwait", lat: 29.281360965443092, lng: 47.56311109320184 },
|
|
2674
|
+
"KY": { name: "Cayman Islands", lat: 19.311231805620288, lng: -81.25203208977878 },
|
|
2675
|
+
"KZ": { name: "Kazakhstan", lat: 47.641465195176835, lng: 66.3759193479301 },
|
|
2676
|
+
"LA": { name: "Laos", lat: 18.117282736873282, lng: 103.76375899026448 },
|
|
2677
|
+
"LB": { name: "Lebanon", lat: 33.91160170722086, lng: 35.89651946324749 },
|
|
2678
|
+
"LC": { name: "Saint Lucia", lat: 13.895749185129906, lng: -60.9689510935251 },
|
|
2679
|
+
"LI": { name: "Liechtenstein", lat: 47.14627562133036, lng: 9.547674672376376 },
|
|
2680
|
+
"LK": { name: "Sri Lanka", lat: 7.696630939329944, lng: 80.66931169770622 },
|
|
2681
|
+
"LR": { name: "Liberia", lat: 6.52012979398834, lng: -9.258988935497618 },
|
|
2682
|
+
"LS": { name: "Lesotho", lat: -29.60168116924817, lng: 28.24475317864227 },
|
|
2683
|
+
"LT": { name: "Lithuania", lat: 55.29437393417175, lng: 23.946021605013534 },
|
|
2684
|
+
"LU": { name: "Luxembourg", lat: 49.77523454542369, lng: 6.103230338458876 },
|
|
2685
|
+
"LV": { name: "Latvia", lat: 56.813853047554154, lng: 24.693671325654403 },
|
|
2686
|
+
"LY": { name: "Libya", lat: 27.202915771690794, lng: 17.91133392454237 },
|
|
2687
|
+
"MA": { name: "Morocco", lat: 28.687598134979325, lng: -8.817212587250811 },
|
|
2688
|
+
"MC": { name: "Monaco", lat: 43.74798224995656, lng: 7.412820873271196 },
|
|
2689
|
+
"MD": { name: "Moldova", lat: 47.0725674580696, lng: 28.391111865941348 },
|
|
2690
|
+
"ME": { name: "Montenegro", lat: 42.73694835210454, lng: 19.29505087156758 },
|
|
2691
|
+
"MF": { name: "Saint Martin", lat: 18.078012113224464, lng: -63.06678525361946 },
|
|
2692
|
+
"MG": { name: "Madagascar", lat: -19.04163612493041, lng: 46.68493466832544 },
|
|
2693
|
+
"MH": { name: "Marshall Islands", lat: 7.307929900994344, lng: 168.72016025351076 },
|
|
2694
|
+
"MK": { name: "North Macedonia", lat: 41.59402890143112, lng: 21.70998923872772 },
|
|
2695
|
+
"ML": { name: "Mali", lat: 17.168146208584837, lng: -4.346399841781153 },
|
|
2696
|
+
"MM": { name: "Myanmar", lat: 19.901227931399873, lng: 97.08892285397344 },
|
|
2697
|
+
"MN": { name: "Mongolia", lat: 47.08644454604851, lng: 103.3987360327455 },
|
|
2698
|
+
"MP": { name: "Northern Mariana Islands", lat: 15.178063516432115, lng: 145.74119737203134 },
|
|
2699
|
+
"MQ": { name: "Martinique", lat: 14.642697353597645, lng: -61.01432380875083 },
|
|
2700
|
+
"MR": { name: "Mauritania", lat: 20.466731212820022, lng: -10.495079045035716 },
|
|
2701
|
+
"MS": { name: "Montserrat", lat: 16.735363391460357, lng: -62.18693281256255 },
|
|
2702
|
+
"MT": { name: "Malta", lat: 35.890522650899314, lng: 14.441922442508494 },
|
|
2703
|
+
"MU": { name: "Mauritius", lat: -20.28142317475198, lng: 57.56415671066546 },
|
|
2704
|
+
"MV": { name: "Maldives", lat: -0.6065577168009924, lng: 73.10076245140479 },
|
|
2705
|
+
"MW": { name: "Malawi", lat: -13.128986464184024, lng: 34.23441182298881 },
|
|
2706
|
+
"MX": { name: "Mexico", lat: 23.87436068093592, lng: -101.55399731630118 },
|
|
2707
|
+
"MY": { name: "Malaysia", lat: 3.6716608556387857, lng: 114.63330303992869 },
|
|
2708
|
+
"MZ": { name: "Mozambique", lat: -17.525230309488748, lng: 35.208577031290176 },
|
|
2709
|
+
"NA": { name: "Namibia", lat: -21.90858163281473, lng: 18.16451345845268 },
|
|
2710
|
+
"NC": { name: "New Caledonia", lat: -21.33003372660827, lng: 165.50767040438612 },
|
|
2711
|
+
"NE": { name: "Niger", lat: 17.08105392407292, lng: 8.86863247002646 },
|
|
2712
|
+
"NF": { name: "Norfolk Island", lat: -29.037654445046282, lng: 167.95259597483337 },
|
|
2713
|
+
"NG": { name: "Nigeria", lat: 9.61029352034213, lng: 8.147714845256194 },
|
|
2714
|
+
"NI": { name: "Nicaragua", lat: 12.893566631930554, lng: -85.016088327669 },
|
|
2715
|
+
"NL": { name: "Netherlands", lat: 52.134054128923886, lng: 5.554136426128487 },
|
|
2716
|
+
"NO": { name: "Norway", lat: 64.97775882947745, lng: 16.670259272390894 },
|
|
2717
|
+
"NP": { name: "Nepal", lat: 28.300920699755657, lng: 84.1338898313567 },
|
|
2718
|
+
"NR": { name: "Nauru", lat: -0.5221021440668993, lng: 166.92937633139178 },
|
|
2719
|
+
"NU": { name: "Niue", lat: -19.05230921680393, lng: -169.86878106699083 },
|
|
2720
|
+
"NZ": { name: "New Zealand", lat: -43.82765432544426, lng: 170.69035541428696 },
|
|
2721
|
+
"OM": { name: "Oman", lat: 20.7242833183209, lng: 55.841088119829 },
|
|
2722
|
+
"PA": { name: "Panama", lat: 8.439536749576892, lng: -80.14428761482796 },
|
|
2723
|
+
"PE": { name: "Peru", lat: -8.522717984240291, lng: -74.11416196781884 },
|
|
2724
|
+
"PF": { name: "French Polynesia", lat: -17.674684080120677, lng: -149.40041671099763 },
|
|
2725
|
+
"PG": { name: "Papua New Guinea", lat: -7.156912819152135, lng: 144.8348942994695 },
|
|
2726
|
+
"PH": { name: "Philippines", lat: 15.586542251094242, lng: 121.82208941416745 },
|
|
2727
|
+
"PK": { name: "Pakistan", lat: 30.116188371410882, lng: 69.08835090769651 },
|
|
2728
|
+
"PL": { name: "Poland", lat: 52.06848055692473, lng: 19.43573279234468 },
|
|
2729
|
+
"PM": { name: "Saint Pierre and Miquelon", lat: 46.95153913615198, lng: -56.32465353437558 },
|
|
2730
|
+
"PN": { name: "Pitcairn", lat: -24.366121747565458, lng: -128.3149848627581 },
|
|
2731
|
+
"PR": { name: "Puerto Rico", lat: 18.216224086610914, lng: -66.49425339593509 },
|
|
2732
|
+
"PS": { name: "Palestinian Territory", lat: 31.930818736453883, lng: 35.24251184154588 },
|
|
2733
|
+
"PT": { name: "Portugal", lat: 39.67529214702138, lng: -7.933662183874006 },
|
|
2734
|
+
"PW": { name: "Palau", lat: 7.534775852547396, lng: 134.57965086721052 },
|
|
2735
|
+
"PY": { name: "Paraguay", lat: -23.42190559259428, lng: -58.38906357428651 },
|
|
2736
|
+
"QA": { name: "Qatar", lat: 25.318528486425386, lng: 51.19794918743203 },
|
|
2737
|
+
"RE": { name: "Réunion", lat: -21.119825460665105, lng: 55.54393506194689 },
|
|
2738
|
+
"RO": { name: "Romania", lat: 45.82454894397586, lng: 25.094158201563292 },
|
|
2739
|
+
"RS": { name: "Serbia", lat: 44.02679870131969, lng: 20.85677444395745 },
|
|
2740
|
+
"RU": { name: "Russian Federation", lat: 59.039434214106194, lng: 98.6704990698032 },
|
|
2741
|
+
"RW": { name: "Rwanda", lat: -2.014687460047154, lng: 29.919439681764082 },
|
|
2742
|
+
"SA": { name: "Saudi Arabia", lat: 24.136038144757897, lng: 44.600958178225596 },
|
|
2743
|
+
"SB": { name: "Solomon Islands", lat: -9.613104734596515, lng: 160.16475795033884 },
|
|
2744
|
+
"SC": { name: "Seychelles", lat: -4.660002318822744, lng: 55.47250789595527 },
|
|
2745
|
+
"SD": { name: "Sudan", lat: 15.67060230984256, lng: 29.951458283594064 },
|
|
2746
|
+
"SE": { name: "Sweden", lat: 62.73420986108448, lng: 17.062431988004956 },
|
|
2747
|
+
"SG": { name: "Singapore", lat: 1.3528251890006349, lng: 103.81025757634053 },
|
|
2748
|
+
"SH": { name: "Saint Helena", lat: -15.962963318340398, lng: -5.717391620813109 },
|
|
2749
|
+
"SI": { name: "Slovenia", lat: 46.13759229564504, lng: 14.890636899973781 },
|
|
2750
|
+
"SJ": { name: "Svalbard", lat: 78.57318936469626, lng: 16.036378851505283 },
|
|
2751
|
+
"SK": { name: "Slovakia", lat: 48.69808390520484, lng: 19.581015362490966 },
|
|
2752
|
+
"SL": { name: "Sierra Leone", lat: 8.561330384750587, lng: -11.78656695731115 },
|
|
2753
|
+
"SM": { name: "San Marino", lat: 43.942820729097896, lng: 12.461278349581722 },
|
|
2754
|
+
"SN": { name: "Senegal", lat: 14.228861491763402, lng: -14.610875368352305 },
|
|
2755
|
+
"SO": { name: "Somalia", lat: 6.524534573103924, lng: 45.40037867243972 },
|
|
2756
|
+
"SR": { name: "Suriname", lat: 4.098723595920171, lng: -55.855514311561286 },
|
|
2757
|
+
"SS": { name: "South Sudan", lat: 7.657782041763295, lng: 30.3851856901788 },
|
|
2758
|
+
"ST": { name: "Sao Tome and Principe", lat: 0.22744704294793774, lng: 6.606158796857607 },
|
|
2759
|
+
"SV": { name: "El Salvador", lat: 13.758041517055418, lng: -88.85911489238985 },
|
|
2760
|
+
"SX": { name: "Sint Maarten", lat: 18.03942608463078, lng: -63.06883135915303 },
|
|
2761
|
+
"SY": { name: "Syria", lat: 35.09751106058316, lng: 38.5117323139514 },
|
|
2762
|
+
"SZ": { name: "Eswatini", lat: -26.562540935608702, lng: 31.510685746082007 },
|
|
2763
|
+
"TC": { name: "Turks and Caicos Islands", lat: 21.799865427483745, lng: -71.74058946811508 },
|
|
2764
|
+
"TD": { name: "Chad", lat: 15.283493546654503, lng: 18.427113900363025 },
|
|
2765
|
+
"TF": { name: "Juan De Nova Island", lat: -17.06449193630804, lng: 42.74374761089645 },
|
|
2766
|
+
"TF": { name: "French Southern Territories", lat: -49.26329687105643, lng: 69.54686984724839 },
|
|
2767
|
+
"TF": { name: "Glorioso Islands", lat: -11.566224871643417, lng: 47.290948081543384 },
|
|
2768
|
+
"TG": { name: "Togo", lat: 8.660743037717811, lng: 0.8990857571109684 },
|
|
2769
|
+
"TH": { name: "Thailand", lat: 13.66222784745538, lng: 101.08675116214552 },
|
|
2770
|
+
"TJ": { name: "Tajikistan", lat: 38.56933138382972, lng: 70.94215281065698 },
|
|
2771
|
+
"TK": { name: "Tokelau", lat: -9.195174767256544, lng: -171.85265950722743 },
|
|
2772
|
+
"TL": { name: "Timor-Leste", lat: -8.809894630601962, lng: 125.95024049562659 },
|
|
2773
|
+
"TM": { name: "Turkmenistan", lat: 39.06069118001429, lng: 58.4577357627054 },
|
|
2774
|
+
"TN": { name: "Tunisia", lat: 34.08636179565723, lng: 9.65587551697984 },
|
|
2775
|
+
"TO": { name: "Tonga", lat: -21.15927212823853, lng: -175.20415878511247 },
|
|
2776
|
+
"TR": { name: "Turkey", lat: 38.93207363123396, lng: 35.56886764076691 },
|
|
2777
|
+
"TT": { name: "Trinidad and Tobago", lat: 10.415515638298093, lng: -61.37236579976247 },
|
|
2778
|
+
"TV": { name: "Tuvalu", lat: -8.514701506447222, lng: 179.217833977593 },
|
|
2779
|
+
"TZ": { name: "Tanzania", lat: -6.355794440041147, lng: 34.81832206060381 },
|
|
2780
|
+
"UA": { name: "Ukraine", lat: 48.657532515563794, lng: 31.27377208442636 },
|
|
2781
|
+
"UG": { name: "Uganda", lat: 1.2821729218416205, lng: 32.34371768463123 },
|
|
2782
|
+
"UM": { name: "United States Minor Outlying Islands", lat: 19.302045812215958, lng: 166.63800339749642 },
|
|
2783
|
+
"US": { name: "United States", lat: 38.8208089190304, lng: -96.33161660829639 },
|
|
2784
|
+
"UY": { name: "Uruguay", lat: -32.78195043831093, lng: -56.01919523458085 },
|
|
2785
|
+
"UZ": { name: "Uzbekistan", lat: 41.4879065244633, lng: 63.8548297593985 },
|
|
2786
|
+
"VA": { name: "Vatican City", lat: 41.90402351316735, lng: 12.451312917026133 },
|
|
2787
|
+
"VC": { name: "Saint Vincent and the Grenadines", lat: 13.254808122970651, lng: -61.193766354393034 },
|
|
2788
|
+
"VE": { name: "Venezuela", lat: 7.148324760507107, lng: -66.36492135985132 },
|
|
2789
|
+
"VG": { name: "British Virgin Islands", lat: 18.42195819619707, lng: -64.62406519257699 },
|
|
2790
|
+
"VI": { name: "US Virgin Islands", lat: 17.738009708772523, lng: -64.76155341409797 },
|
|
2791
|
+
"VN": { name: "Vietnam", lat: 16.517347170839393, lng: 105.91338832758704 },
|
|
2792
|
+
"VU": { name: "Vanuatu", lat: -15.189132121699332, lng: 166.84912735669738 },
|
|
2793
|
+
"WF": { name: "Wallis and Futuna", lat: -14.283442307826677, lng: -178.12735555777184 },
|
|
2794
|
+
"WS": { name: "Samoa", lat: -13.634252953274622, lng: -172.44107655740137 },
|
|
2795
|
+
"YE": { name: "Yemen", lat: 16.001392616307445, lng: 47.46815793206386 },
|
|
2796
|
+
"YT": { name: "Mayotte", lat: -12.824468416301052, lng: 45.128142327031064 },
|
|
2797
|
+
"ZA": { name: "South Africa", lat: -28.55361930679731, lng: 24.75252746489084 },
|
|
2798
|
+
"ZM": { name: "Zambia", lat: -13.162832953186246, lng: 27.75521363430896 },
|
|
2799
|
+
"ZW": { name: "Zimbabwe", lat: -18.92700121981475, lng: 29.717829640720844 }
|
|
2800
|
+
};
|
|
2801
|
+
class MetricsCountryMapView extends View {
|
|
2802
|
+
constructor(options = {}) {
|
|
2803
|
+
const mapHeight = options.height || 320;
|
|
2804
|
+
super({
|
|
2805
|
+
className: "metrics-country-map-view",
|
|
2806
|
+
...options
|
|
2807
|
+
});
|
|
2808
|
+
this.endpoint = options.endpoint || "/api/metrics/fetch";
|
|
2809
|
+
this.account = options.account || "global";
|
|
2810
|
+
this.category = options.category || null;
|
|
2811
|
+
this.slugs = options.slugs || null;
|
|
2812
|
+
this.granularity = options.granularity || "days";
|
|
2813
|
+
this.maxCountries = options.maxCountries || 12;
|
|
2814
|
+
this.metricLabel = options.metricLabel || "Events";
|
|
2815
|
+
this.height = mapHeight;
|
|
2816
|
+
this.mapStyle = options.mapStyle || "dark";
|
|
2817
|
+
this.mapOptions = options.mapOptions || {};
|
|
2818
|
+
this.showRoutes = options.showRoutes !== false;
|
|
2819
|
+
this.routeOrigin = options.routeOrigin || { lng: -77.346, lat: 38.958, name: "Reston, VA" };
|
|
2820
|
+
this._refreshing = false;
|
|
2821
|
+
}
|
|
2822
|
+
async getTemplate() {
|
|
2823
|
+
return `
|
|
2824
|
+
<div class="metrics-country-map">
|
|
2825
|
+
<div class="map-container mb-3" data-container="${this.id}-map" style="height:${this.height}px"></div>
|
|
2826
|
+
<div class="map-legend small" data-region="legend"></div>
|
|
2827
|
+
</div>
|
|
2828
|
+
`;
|
|
2829
|
+
}
|
|
2830
|
+
async onInit() {
|
|
2831
|
+
this.statusEl = document.createElement("div");
|
|
2832
|
+
this.statusEl.className = "text-muted small px-3 pb-2";
|
|
2833
|
+
this.element.appendChild(this.statusEl);
|
|
2834
|
+
this.mapView = new MapLibreView({
|
|
2835
|
+
containerId: `${this.id}-map`,
|
|
2836
|
+
height: this.height,
|
|
2837
|
+
style: this.mapStyle,
|
|
2838
|
+
zoom: this.mapOptions.zoom ?? 1.3,
|
|
2839
|
+
center: this.mapOptions.center || [10, 20],
|
|
2840
|
+
pitch: this.mapOptions.pitch ?? 20,
|
|
2841
|
+
bearing: this.mapOptions.bearing ?? 0,
|
|
2842
|
+
showNavigationControl: this.mapOptions.showNavigationControl ?? true,
|
|
2843
|
+
autoFitBounds: this.mapOptions.autoFitBounds ?? false
|
|
2844
|
+
});
|
|
2845
|
+
this.addChild(this.mapView);
|
|
2846
|
+
await this.refresh();
|
|
2847
|
+
}
|
|
2848
|
+
async refresh() {
|
|
2849
|
+
if (this._refreshing) return;
|
|
2850
|
+
this._refreshing = true;
|
|
2851
|
+
this.setStatus("Loading hotspots…");
|
|
2852
|
+
try {
|
|
2853
|
+
const metrics = await this.fetchMetrics();
|
|
2854
|
+
await this.applyMetrics(metrics);
|
|
2855
|
+
this.setStatus("");
|
|
2856
|
+
} catch (error) {
|
|
2857
|
+
console.error("MetricsCountryMapView refresh error", error);
|
|
2858
|
+
this.setStatus("Unable to load country metrics.");
|
|
2859
|
+
} finally {
|
|
2860
|
+
this._refreshing = false;
|
|
2861
|
+
}
|
|
2862
|
+
}
|
|
2863
|
+
async fetchMetrics() {
|
|
2864
|
+
const rest2 = this.getApp()?.rest;
|
|
2865
|
+
if (!rest2) {
|
|
2866
|
+
throw new Error("REST client unavailable");
|
|
2867
|
+
}
|
|
2868
|
+
const params = {
|
|
2869
|
+
account: this.account,
|
|
2870
|
+
granularity: this.granularity,
|
|
2871
|
+
with_labels: true
|
|
2872
|
+
};
|
|
2873
|
+
if (this.category) params.category = this.category;
|
|
2874
|
+
if (this.slugs) {
|
|
2875
|
+
const slugsArray = Array.isArray(this.slugs) ? this.slugs : [this.slugs];
|
|
2876
|
+
params["slugs[]"] = slugsArray;
|
|
2877
|
+
}
|
|
2878
|
+
const response = await rest2.GET(this.endpoint, params);
|
|
2879
|
+
if (!response.success || !response.data?.status) {
|
|
2880
|
+
throw new Error(response.data?.error || "Metrics API error");
|
|
2881
|
+
}
|
|
2882
|
+
return response.data.data;
|
|
2883
|
+
}
|
|
2884
|
+
async applyMetrics(data) {
|
|
2885
|
+
const metrics = data?.data || {};
|
|
2886
|
+
const labels = data?.labels || [];
|
|
2887
|
+
const entries = [];
|
|
2888
|
+
Object.entries(metrics).forEach(([iso, series]) => {
|
|
2889
|
+
const total = series.reduce((sum, value) => sum + (Number(value) || 0), 0);
|
|
2890
|
+
if (!total) return;
|
|
2891
|
+
const centroid = COUNTRY_CENTROIDS[iso.toUpperCase()];
|
|
2892
|
+
if (!centroid) return;
|
|
2893
|
+
entries.push({
|
|
2894
|
+
code: iso.toUpperCase(),
|
|
2895
|
+
total,
|
|
2896
|
+
values: series,
|
|
2897
|
+
centroid
|
|
2898
|
+
});
|
|
2899
|
+
});
|
|
2900
|
+
if (!entries.length) {
|
|
2901
|
+
this.mapView.updateMarkers([]);
|
|
2902
|
+
this.renderLegend([]);
|
|
2903
|
+
this.setStatus("No country data available for the selected range.");
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
entries.sort((a2, b2) => b2.total - a2.total);
|
|
2907
|
+
const topEntries = entries.slice(0, this.maxCountries);
|
|
2908
|
+
const maxValue = topEntries[0]?.total || 1;
|
|
2909
|
+
const markers = topEntries.map((entry) => {
|
|
2910
|
+
const intensity = entry.total / maxValue;
|
|
2911
|
+
const markerSize = Math.round(18 + intensity * 24);
|
|
2912
|
+
return {
|
|
2913
|
+
lng: entry.centroid.lng,
|
|
2914
|
+
lat: entry.centroid.lat,
|
|
2915
|
+
size: markerSize,
|
|
2916
|
+
color: this.getMarkerColor(intensity),
|
|
2917
|
+
popup: `
|
|
2918
|
+
<div class="text-center">
|
|
2919
|
+
<strong>${entry.centroid.name}</strong><br/>
|
|
2920
|
+
<span class="text-muted">${entry.total.toLocaleString()} ${this.metricLabel}</span>
|
|
2921
|
+
</div>
|
|
2922
|
+
`
|
|
2923
|
+
};
|
|
2924
|
+
});
|
|
2925
|
+
if (this.showRoutes && this.routeOrigin?.lng && this.routeOrigin?.lat) {
|
|
2926
|
+
markers.push({
|
|
2927
|
+
lng: this.routeOrigin.lng,
|
|
2928
|
+
lat: this.routeOrigin.lat,
|
|
2929
|
+
size: 26,
|
|
2930
|
+
color: "#0d6efd",
|
|
2931
|
+
icon: "bi bi-broadcast-pin",
|
|
2932
|
+
popup: `
|
|
2933
|
+
<div class="text-center">
|
|
2934
|
+
<strong>${this.routeOrigin.name || "Operations Hub"}</strong><br/>
|
|
2935
|
+
<span class="text-muted">Origin</span>
|
|
2936
|
+
</div>
|
|
2937
|
+
`
|
|
2938
|
+
});
|
|
2939
|
+
}
|
|
2940
|
+
this.mapView.updateMarkers(markers);
|
|
2941
|
+
this.renderLegend(topEntries, labels);
|
|
2942
|
+
if (this.showRoutes) {
|
|
2943
|
+
this.renderRoutes(topEntries, maxValue);
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
getMarkerColor(intensity) {
|
|
2947
|
+
const start = [32, 201, 151];
|
|
2948
|
+
const end = [255, 193, 7];
|
|
2949
|
+
const mix = start.map(
|
|
2950
|
+
(value, idx) => Math.round(value + (end[idx] - value) * intensity)
|
|
2951
|
+
);
|
|
2952
|
+
return `rgba(${mix[0]}, ${mix[1]}, ${mix[2]}, 0.9)`;
|
|
2953
|
+
}
|
|
2954
|
+
renderLegend(entries) {
|
|
2955
|
+
const legendEl = this.element.querySelector('[data-region="legend"]');
|
|
2956
|
+
if (!legendEl) return;
|
|
2957
|
+
if (!entries.length) {
|
|
2958
|
+
legendEl.innerHTML = "";
|
|
2959
|
+
return;
|
|
2960
|
+
}
|
|
2961
|
+
const maxValue = entries[0]?.total || 1;
|
|
2962
|
+
const rows = entries.map((entry) => {
|
|
2963
|
+
const percent = (entry.total / maxValue * 100).toFixed(0);
|
|
2964
|
+
return `
|
|
2965
|
+
<div class="d-flex justify-content-between align-items-center py-1 border-top">
|
|
2966
|
+
<div>
|
|
2967
|
+
<span class="fw-semibold">${entry.centroid.name}</span>
|
|
2968
|
+
<span class="text-muted ms-1">(${entry.code})</span>
|
|
2969
|
+
</div>
|
|
2970
|
+
<div class="text-end">
|
|
2971
|
+
<div class="fw-semibold">${entry.total.toLocaleString()}</div>
|
|
2972
|
+
<small class="text-muted">${percent}% of top</small>
|
|
2973
|
+
</div>
|
|
2974
|
+
</div>
|
|
2975
|
+
`;
|
|
2976
|
+
}).join("");
|
|
2977
|
+
legendEl.innerHTML = rows;
|
|
2978
|
+
}
|
|
2979
|
+
renderRoutes(entries, maxValue) {
|
|
2980
|
+
const origin = this.routeOrigin || null;
|
|
2981
|
+
if (!origin || !origin.lng || !origin.lat || !this.mapView) return;
|
|
2982
|
+
const features = entries.map((entry) => ({
|
|
2983
|
+
type: "Feature",
|
|
2984
|
+
geometry: {
|
|
2985
|
+
type: "LineString",
|
|
2986
|
+
coordinates: [
|
|
2987
|
+
[origin.lng, origin.lat],
|
|
2988
|
+
[entry.centroid.lng, entry.centroid.lat]
|
|
2989
|
+
]
|
|
2990
|
+
},
|
|
2991
|
+
properties: {
|
|
2992
|
+
total: entry.total,
|
|
2993
|
+
intensity: entry.total / maxValue
|
|
2994
|
+
}
|
|
2995
|
+
}));
|
|
2996
|
+
const geojson = {
|
|
2997
|
+
type: "FeatureCollection",
|
|
2998
|
+
features
|
|
2999
|
+
};
|
|
3000
|
+
const paint = {
|
|
3001
|
+
"line-color": [
|
|
3002
|
+
"interpolate",
|
|
3003
|
+
["linear"],
|
|
3004
|
+
["get", "intensity"],
|
|
3005
|
+
0,
|
|
3006
|
+
"rgba(32, 201, 151, 0.2)",
|
|
3007
|
+
1,
|
|
3008
|
+
"rgba(255, 193, 7, 0.85)"
|
|
3009
|
+
],
|
|
3010
|
+
"line-width": [
|
|
3011
|
+
"interpolate",
|
|
3012
|
+
["linear"],
|
|
3013
|
+
["get", "intensity"],
|
|
3014
|
+
0,
|
|
3015
|
+
1,
|
|
3016
|
+
1,
|
|
3017
|
+
5
|
|
3018
|
+
],
|
|
3019
|
+
"line-opacity": [
|
|
3020
|
+
"interpolate",
|
|
3021
|
+
["linear"],
|
|
3022
|
+
["get", "intensity"],
|
|
3023
|
+
0,
|
|
3024
|
+
0.2,
|
|
3025
|
+
1,
|
|
3026
|
+
0.9
|
|
3027
|
+
]
|
|
3028
|
+
};
|
|
3029
|
+
this.mapView.lineSources = this.mapView.lineSources.filter((src) => src.id !== `${this.id}-routes`);
|
|
3030
|
+
this.mapView.updateLineSource(`${this.id}-routes`, {
|
|
3031
|
+
data: geojson,
|
|
3032
|
+
paint
|
|
3033
|
+
});
|
|
3034
|
+
}
|
|
3035
|
+
setStatus(message) {
|
|
3036
|
+
if (!this.statusEl) return;
|
|
3037
|
+
this.statusEl.textContent = message || "";
|
|
3038
|
+
this.statusEl.style.display = message ? "block" : "none";
|
|
3039
|
+
}
|
|
3040
|
+
}
|
|
2252
3041
|
class IncidentDashboardHeader extends View {
|
|
2253
3042
|
constructor(options = {}) {
|
|
2254
3043
|
super({
|
|
@@ -2367,6 +3156,23 @@ class IncidentDashboardPage extends Page {
|
|
|
2367
3156
|
<div class="col-xl-6 col-lg-12" data-container="incidents-widget"></div>
|
|
2368
3157
|
</div>
|
|
2369
3158
|
|
|
3159
|
+
|
|
3160
|
+
<div class="row g-4 mt-1">
|
|
3161
|
+
<div class="col-12">
|
|
3162
|
+
<div class="card shadow-sm h-100">
|
|
3163
|
+
<div class="card-header border-0 bg-transparent d-flex align-items-center justify-content-between">
|
|
3164
|
+
<div>
|
|
3165
|
+
<h6 class="mb-0 text-uppercase small text-muted">Global Event Hotspots</h6>
|
|
3166
|
+
<span class="text-muted small">Clusters sized by total events</span>
|
|
3167
|
+
</div>
|
|
3168
|
+
<span class="badge bg-info-subtle text-info">Interactive</span>
|
|
3169
|
+
</div>
|
|
3170
|
+
<div class="card-body p-0" data-container="events-country-map"></div>
|
|
3171
|
+
</div>
|
|
3172
|
+
</div>
|
|
3173
|
+
</div>
|
|
3174
|
+
|
|
3175
|
+
|
|
2370
3176
|
<div class="row g-4 mt-1">
|
|
2371
3177
|
<div class="col-lg-6">
|
|
2372
3178
|
<div class="card shadow-sm h-100">
|
|
@@ -2489,11 +3295,12 @@ class IncidentDashboardPage extends Page {
|
|
|
2489
3295
|
endpoint: "/api/metrics/fetch",
|
|
2490
3296
|
account: "incident",
|
|
2491
3297
|
category: "incident_events_by_country",
|
|
2492
|
-
granularity: "
|
|
2493
|
-
chartType: "
|
|
3298
|
+
granularity: "days",
|
|
3299
|
+
chartType: "line",
|
|
2494
3300
|
showDateRange: false,
|
|
2495
3301
|
showMetricsFilter: false,
|
|
2496
3302
|
height: 220,
|
|
3303
|
+
maxDatasets: 10,
|
|
2497
3304
|
colors: [
|
|
2498
3305
|
"rgba(32, 201, 151, 0.85)"
|
|
2499
3306
|
],
|
|
@@ -2510,11 +3317,12 @@ class IncidentDashboardPage extends Page {
|
|
|
2510
3317
|
endpoint: "/api/metrics/fetch",
|
|
2511
3318
|
account: "incident",
|
|
2512
3319
|
category: "incident_by_country",
|
|
2513
|
-
granularity: "
|
|
2514
|
-
chartType: "
|
|
3320
|
+
granularity: "days",
|
|
3321
|
+
chartType: "line",
|
|
2515
3322
|
showDateRange: false,
|
|
2516
3323
|
showMetricsFilter: false,
|
|
2517
3324
|
height: 220,
|
|
3325
|
+
maxDatasets: 10,
|
|
2518
3326
|
colors: [
|
|
2519
3327
|
"rgba(255, 193, 7, 0.85)"
|
|
2520
3328
|
],
|
|
@@ -2526,6 +3334,16 @@ class IncidentDashboardPage extends Page {
|
|
|
2526
3334
|
containerId: "incidents-by-country-chart"
|
|
2527
3335
|
});
|
|
2528
3336
|
this.addChild(this.incidentsByCountryChart);
|
|
3337
|
+
this.eventsCountryMap = new MetricsCountryMapView({
|
|
3338
|
+
containerId: "events-country-map",
|
|
3339
|
+
category: "incident_events_by_country",
|
|
3340
|
+
account: "incident",
|
|
3341
|
+
maxCountries: 15,
|
|
3342
|
+
metricLabel: "Events",
|
|
3343
|
+
height: 360,
|
|
3344
|
+
mapStyle: "dark"
|
|
3345
|
+
});
|
|
3346
|
+
this.addChild(this.eventsCountryMap);
|
|
2529
3347
|
const myTicketsCollection = new TicketList({
|
|
2530
3348
|
params: {
|
|
2531
3349
|
status: "new"
|
|
@@ -2570,6 +3388,7 @@ class IncidentDashboardPage extends Page {
|
|
|
2570
3388
|
this.incidentsWidget?.refresh(),
|
|
2571
3389
|
this.eventsByCountryChart?.refresh(),
|
|
2572
3390
|
this.incidentsByCountryChart?.refresh(),
|
|
3391
|
+
this.eventsCountryMap?.refresh(),
|
|
2573
3392
|
this.myTicketsTable?.collection?.fetch(),
|
|
2574
3393
|
this.highPriorityIncidentsTable?.collection?.fetch()
|
|
2575
3394
|
].filter(Boolean);
|