node distribution functionality
This commit is contained in:
parent
e60cdfc04e
commit
096705ce65
@ -40,8 +40,11 @@
|
|||||||
"dotenv": "^8.0.0",
|
"dotenv": "^8.0.0",
|
||||||
"express": "^4.15.2",
|
"express": "^4.15.2",
|
||||||
"express-static-gzip": "^1.1.3",
|
"express-static-gzip": "^1.1.3",
|
||||||
|
"geoip-lite": "^1.4.7",
|
||||||
"helmet": "^3.18.0",
|
"helmet": "^3.18.0",
|
||||||
"jsdom": "^15.1.1",
|
"jsdom": "^15.1.1",
|
||||||
|
"leaflet": "^1.9.4",
|
||||||
|
"leaflet.markercluster": "^1.5.3",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"morgan": "^1.9.1",
|
"morgan": "^1.9.1",
|
||||||
"ng2-odometer": "^1.1.3",
|
"ng2-odometer": "^1.1.3",
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
latestBlockDetails,
|
latestBlockDetails,
|
||||||
previousBlockDetails
|
previousBlockDetails
|
||||||
} from '../utils/common';
|
} from '../utils/common';
|
||||||
|
const geoip = require('geoip-lite');
|
||||||
var moment = require('moment');
|
var moment = require('moment');
|
||||||
moment.updateLocale('en', {
|
moment.updateLocale('en', {
|
||||||
relativeTime: {
|
relativeTime: {
|
||||||
@ -270,6 +271,11 @@ export class BlockchainBlockController {
|
|||||||
redisMiddleware(process.env.REDIS_EXPIRY),
|
redisMiddleware(process.env.REDIS_EXPIRY),
|
||||||
this.getepicmineapi,
|
this.getepicmineapi,
|
||||||
);
|
);
|
||||||
|
this.router.get(
|
||||||
|
`${this.path}/v1/peers/all`,
|
||||||
|
redisMiddleware(process.env.REDIS_EXPIRY),
|
||||||
|
this.getpeersallapi,
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @swagger
|
* @swagger
|
||||||
@ -758,6 +764,39 @@ export class BlockchainBlockController {
|
|||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
// get /v1/peers/all
|
||||||
|
private getpeersallapi = async( request: Request,res: Response) => {
|
||||||
|
var axios = require('axios');
|
||||||
|
try {
|
||||||
|
var config = {
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://5.75.242.4:3413/v1/peers/all',
|
||||||
|
headers: { }
|
||||||
|
};
|
||||||
|
await axios(config).then( (response) => {
|
||||||
|
const data = response.data;
|
||||||
|
|
||||||
|
// Perform IP geolocation for each item in the 'data' array
|
||||||
|
data.forEach(peer => {
|
||||||
|
const ip = peer.addr.split(':')[0];
|
||||||
|
const geo = geoip.lookup(ip);
|
||||||
|
|
||||||
|
// Add the 'geo' data to the 'peer' object
|
||||||
|
peer.geo = geo;
|
||||||
|
});
|
||||||
|
res.status(200).json({
|
||||||
|
status: 200,
|
||||||
|
response: data
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log('axios-error');
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private BlockchainBlockCreate = async (
|
private BlockchainBlockCreate = async (
|
||||||
request: Request,
|
request: Request,
|
||||||
|
@ -56,7 +56,6 @@
|
|||||||
<!-- <option disabled value="Mainnet">MainNet</option> -->
|
<!-- <option disabled value="Mainnet">MainNet</option> -->
|
||||||
</select>
|
</select>
|
||||||
<i class="arrow_drpdwn net_dropdwn"></i>
|
<i class="arrow_drpdwn net_dropdwn"></i>
|
||||||
|
|
||||||
<!-- <ul class="list-unstyled d-inline-block mb-0">
|
<!-- <ul class="list-unstyled d-inline-block mb-0">
|
||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a
|
<a
|
||||||
|
20
src/app/view/location/location.component.css
Normal file
20
src/app/view/location/location.component.css
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
.map-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
display: flex; /* Use flexbox to center the map within its container */
|
||||||
|
justify-content: center; /* Center horizontally */
|
||||||
|
align-items: center; /* Center vertically */
|
||||||
|
}
|
||||||
|
|
||||||
|
.map-frame {
|
||||||
|
border: 2px solid black;
|
||||||
|
height: 70%; /* Adjust the height of the map frame */
|
||||||
|
width: 70%; /* Adjust the width of the map frame */
|
||||||
|
}
|
||||||
|
|
||||||
|
#map {
|
||||||
|
height: 100%;
|
||||||
|
}
|
8
src/app/view/location/location.component.html
Normal file
8
src/app/view/location/location.component.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<div class="view_content" >
|
||||||
|
|
||||||
|
<div class="map-container">
|
||||||
|
<div class="map-frame">
|
||||||
|
<div id="map"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
25
src/app/view/location/location.component.spec.ts
Normal file
25
src/app/view/location/location.component.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LocationComponent } from './location.component';
|
||||||
|
|
||||||
|
describe('LocationComponent', () => {
|
||||||
|
let component: LocationComponent;
|
||||||
|
let fixture: ComponentFixture<LocationComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ LocationComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LocationComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
70
src/app/view/location/location.component.ts
Normal file
70
src/app/view/location/location.component.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { Component, AfterViewInit } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import * as L from 'leaflet';
|
||||||
|
import 'leaflet.markercluster'; // Import the marker cluster library
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-location',
|
||||||
|
templateUrl: './location.component.html',
|
||||||
|
styleUrls: ['./location.component.css']
|
||||||
|
})
|
||||||
|
export class LocationComponent implements AfterViewInit {
|
||||||
|
private map;
|
||||||
|
private locations = [];
|
||||||
|
private markerClusterGroup: L.MarkerClusterGroup; // Create a marker cluster group
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this.initMap();
|
||||||
|
this.fetchLocationData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initMap(): void {
|
||||||
|
this.map = L.map('map', {
|
||||||
|
center: [30, -20],
|
||||||
|
zoom: 3,
|
||||||
|
maxBounds: L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180)) , // Disable horizontal scrolling
|
||||||
|
bounceAtZoomLimits:true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
maxZoom: 18,
|
||||||
|
minZoom: 2,
|
||||||
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||||
|
});
|
||||||
|
|
||||||
|
tiles.addTo(this.map);
|
||||||
|
this.markerClusterGroup = L.markerClusterGroup(); // Initialize the marker cluster group
|
||||||
|
this.markerClusterGroup.addTo(this.map); // Add it to the map
|
||||||
|
}
|
||||||
|
|
||||||
|
private addMarkers(): void {
|
||||||
|
const arrayOfLoc = this.locations
|
||||||
|
.map(e => {
|
||||||
|
if (e && e.geo && e.geo.ll && e.geo.city) {
|
||||||
|
return { lat: e.geo.ll[0], lng: e.geo.ll[1], name: e.geo.city };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.filter(e => e !== null);
|
||||||
|
|
||||||
|
for (const location of arrayOfLoc) {
|
||||||
|
const customIcon = L.icon({
|
||||||
|
iconUrl: "/assets/img/icons8-location-80.png",
|
||||||
|
iconSize: [32, 32], // Adjust the icon size as needed
|
||||||
|
iconAnchor: [16, 32], // Adjust the icon anchor as needed
|
||||||
|
});
|
||||||
|
const marker = L.marker([location.lat, location.lng],{ icon: customIcon });
|
||||||
|
marker.bindPopup(location.name);
|
||||||
|
this.markerClusterGroup.addLayer(marker); // Add marker to the cluster group
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fetchLocationData(): void {
|
||||||
|
this.http.get('https://explorer3.epic.tech/epic_explorer/v1/blockchain_block/v1/peers/all').subscribe((data: any) => {
|
||||||
|
this.locations = data.response;
|
||||||
|
this.addMarkers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ import { Routes, RouterModule } from '@angular/router';
|
|||||||
import { HomeLayoutComponent } from '../shared/components/layouts/home-layout/home-layout.component';
|
import { HomeLayoutComponent } from '../shared/components/layouts/home-layout/home-layout.component';
|
||||||
import { SiteLayoutComponent } from '../shared/components/layouts/site-layout/site-layout.component';
|
import { SiteLayoutComponent } from '../shared/components/layouts/site-layout/site-layout.component';
|
||||||
import { ApiViewComponent } from '../view/api-view/api-view.component';
|
import { ApiViewComponent } from '../view/api-view/api-view.component';
|
||||||
|
import { LocationComponent } from '../view/location/location.component';
|
||||||
const viewRoutes: Routes = [
|
const viewRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
@ -38,6 +39,10 @@ const siteRoutes: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'api-index',
|
path: 'api-index',
|
||||||
component: ApiViewComponent
|
component: ApiViewComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'nodes-distribution',
|
||||||
|
component: LocationComponent
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -10,10 +10,10 @@ import { TransServiceService } from '../shared/services/trans-service.service';
|
|||||||
import { ChartService} from '../shared/services/chart.service';
|
import { ChartService} from '../shared/services/chart.service';
|
||||||
import { CustomLoader } from '../app.module';
|
import { CustomLoader } from '../app.module';
|
||||||
import { ApiViewComponent } from './api-view/api-view.component';
|
import { ApiViewComponent } from './api-view/api-view.component';
|
||||||
|
import { LocationComponent } from './location/location.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [ApiViewComponent],
|
declarations: [ApiViewComponent, LocationComponent],
|
||||||
imports: [CommonModule, ViewRoutingModule, SharedModule,
|
imports: [CommonModule, ViewRoutingModule, SharedModule,
|
||||||
TranslateModule.forChild({
|
TranslateModule.forChild({
|
||||||
loader: {provide: TranslateLoader, useClass: CustomLoader, deps : [HttpClient]},
|
loader: {provide: TranslateLoader, useClass: CustomLoader, deps : [HttpClient]},
|
||||||
|
BIN
src/assets/img/icons8-location-80.png
Normal file
BIN
src/assets/img/icons8-location-80.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.3 KiB |
Loading…
Reference in New Issue
Block a user