Skip to content

Commit

Permalink
Dislay online hosts count in the portal header
Browse files Browse the repository at this point in the history
  • Loading branch information
mike76-dev committed Mar 20, 2024
1 parent f844afa commit 0480cfb
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ ldflags= \
-X "github.com/mike76-dev/hostscore/internal/build.NodeBinaryName=hsd" \
-X "github.com/mike76-dev/hostscore/internal/build.NodeVersion=0.1.1" \
-X "github.com/mike76-dev/hostscore/internal/build.ClientBinaryName=hsc" \
-X "github.com/mike76-dev/hostscore/internal/build.ClientVersion=0.1.0" \
-X "github.com/mike76-dev/hostscore/internal/build.ClientVersion=0.2.0" \
-X "github.com/mike76-dev/hostscore/internal/build.GitRevision=${GIT_DIRTY}${GIT_REVISION}" \
-X "github.com/mike76-dev/hostscore/internal/build.BuildTime=${BUILD_TIME}"

Expand Down
39 changes: 39 additions & 0 deletions cmd/hsc/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ type hostsResponse struct {
Total int `json:"total"`
}

type onlineHostsResponse struct {
APIResponse
OnlineHosts int `json:"onlineHosts"`
}

type scansResponse struct {
APIResponse
PublicKey types.PublicKey `json:"publicKey"`
Expand Down Expand Up @@ -184,6 +189,9 @@ func (api *portalAPI) buildHTTPRoutes() {
router.GET("/hosts", func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
api.hostsHandler(w, req, ps)
})
router.GET("/hosts/online", func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
api.onlineHostsHandler(w, req, ps)
})
router.GET("/scans", func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
api.scansHandler(w, req, ps)
})
Expand Down Expand Up @@ -522,6 +530,37 @@ func (api *portalAPI) statusHandler(w http.ResponseWriter, _ *http.Request, _ ht
})
}

func (api *portalAPI) onlineHostsHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) {
network := strings.ToLower(req.FormValue("network"))
if network == "" {
writeJSON(w, APIResponse{
Status: "error",
Message: "network not provided",
})
return
}
var count int
api.mu.RLock()
if network == "mainnet" {
for _, host := range api.hosts {
if api.isOnline(*host) {
count++
}
}
} else if network == "zen" {
for _, host := range api.hostsZen {
if api.isOnline(*host) {
count++
}
}
}
api.mu.RUnlock()
writeJSON(w, onlineHostsResponse{
APIResponse: APIResponse{Status: "ok"},
OnlineHosts: count,
})
}

func writeJSON(w http.ResponseWriter, obj interface{}) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
err := json.NewEncoder(w).Encode(obj)
Expand Down
11 changes: 10 additions & 1 deletion web/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,21 @@ export const getHost = async (
.catch(error => console.log(error))
}

export const getStatus = async (): Promise<{ status: string, message: string, version: string, nodes: NodeStatus[] }> => {
export const getStatus = async ():
Promise<{ status: string, message: string, version: string, nodes: NodeStatus[] }> => {
const url = '/status'
return instance.get(url)
.then(response => response.data)
.catch(error => console.log(error))
}

export const getOnlineHosts = async (network: string):
Promise<{ status: string, message: string, onlineHosts: number }> => {
const url = '/hosts/online?network=' + network
return instance.get(url)
.then(response => response.data)
.catch(error => console.log(error))
}

export * from './types'
export * from './helpers'
6 changes: 6 additions & 0 deletions web/src/components/Header/Header.css
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@
.header-dark-mode select:focus {
border: 1px solid transparent;
outline: 2px solid var(--outlineDark);
}

@media screen and (max-width: 1000px) {
.header-container {
padding-bottom: 0.75rem;
}
}
9 changes: 9 additions & 0 deletions web/src/components/NetworkSelector/NetworkSelector.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.network-selector-container {
margin: 0 1rem;
position: relative;
}

.network-selector-select {
Expand All @@ -12,6 +13,14 @@
outline: 2px solid var(--outlineLight);
}

.network-selector-text {
position: absolute;
right: 0;
font-size: 0.8rem;
margin-top: 0.5rem;
white-space: nowrap;
}

@media screen and (max-width: 1000px) {
.network-selector-container {
margin: 0 0.5rem;
Expand Down
13 changes: 12 additions & 1 deletion web/src/components/NetworkSelector/NetworkSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './NetworkSelector.css'
import React, { useState, useEffect } from 'react'
import { useLocation, useNavigate } from 'react-router-dom'
import { useExcludedPaths } from '../../api'
import { useExcludedPaths, getOnlineHosts } from '../../api'

type NetworkSelectorProps = {
network: string,
Expand All @@ -13,6 +13,7 @@ export const NetworkSelector = (props: NetworkSelectorProps) => {
const navigate = useNavigate()
const [network, switchNetwork] = useState(props.network)
const excludedPaths = useExcludedPaths()
const [onlineHosts, setOnlineHosts] = useState(0)
useEffect(() => {
if (excludedPaths.includes(location.pathname)) return
if (location.pathname.indexOf('/zen') === 0) {
Expand All @@ -22,6 +23,13 @@ export const NetworkSelector = (props: NetworkSelectorProps) => {
useEffect(() => {
switchNetwork(props.network)
}, [props.network])
useEffect(() => {
if (network === '') return
getOnlineHosts(network)
.then(data => {
if (data && data.status === 'ok') setOnlineHosts(data.onlineHosts)
})
}, [network])
return (
<div className="network-selector-container">
<select
Expand All @@ -36,6 +44,9 @@ export const NetworkSelector = (props: NetworkSelectorProps) => {
<option value="mainnet">Mainnet</option>
<option value="zen">Zen</option>
</select>
<div className="network-selector-text">
Online hosts: {onlineHosts}
</div>
</div>
)
}

0 comments on commit 0480cfb

Please sign in to comment.