Compare commits

...

3 commits

Author SHA1 Message Date
f1b9ffde33
chore: Modal window is works for all networks 2024-11-23 18:56:41 +07:00
b780783df0
feat: Added more information on monero node details page
These following information added to Monero Node details:

- CORS capable
- Country, City, ASNumber (if any)
- Monitored Since

This commit also add some styling to TOR, I2P information.
2024-11-23 18:49:06 +07:00
84ad053413
Use int64 for DateEntered field
The `DateEntered` value expected to be a timestamp, so using int64
instead of uint make it easier to manipulate time.
2024-11-23 18:31:21 +07:00
3 changed files with 524 additions and 410 deletions

View file

@ -50,7 +50,7 @@ templ RemoteNodes(data monero.Nodes, countries []monero.Countries, q monero.Quer
<li>Nodes with 0% uptime within 1 month with more than 300 check attempt will be removed. You can always add your node again latter.</li>
<li>You can filter remote node by selecting on <strong>nettype</strong>, <strong>protocol</strong>, <strong>country</strong>, <strong>tor</strong>, and <strong>online status</strong> option.</li>
<li>If you want to add more remote node, you can add them using <a href="/add-node" class="link">/add-node</a> page.</li>
<li>I deliberately cut the long Tor addresses, click the <span class="text-orange-300">👁 torhostname...</span> to see the full Tor address.</li>
<li>I deliberately cut the long Tor and I2P addresses, click the <span class="text-orange-300">👁 hostname...</span> to open more detailed information about the Node.</li>
<li>You can found larger remote nodes database from <a href="https://monero.fail/" target="_blank" rel="noopener" class="external">monero.fail</a>.</li>
<li>If you are developer or power user who like to fetch Monero remote node above in JSON format, you can read <a href="https://insights.ditatompel.com/en/blog/2022/01/public-api-monero-remote-node-list/" class="external">Public API Monero Remote Node List</a> blog post for more detailed information.</li>
</ul>
@ -206,10 +206,16 @@ templ TableNodes(data monero.Nodes, countries []monero.Countries, q monero.Query
@cellHostPort(row.ID, row.Port, row.Hostname, row.IPAddresses, row.IsTor, row.IsI2P, row.IPv6Only)
</td>
<td>
@cellNettype(row.Nettype, row.Height)
@fmtNettype(row.Nettype)
<br/>
{ fmt.Sprintf("%d", row.Height) }
</td>
<td>
@cellProtocol(row.Protocol, row.CORSCapable)
@fmtProtocol(row.Protocol)
if row.CORSCapable {
<br/>
(CORS 💪)
}
</td>
<td>
@cellCountry(row.CountryCode, row.CountryName, row.City, row.ASNName, row.ASN)
@ -259,7 +265,12 @@ templ Node(data monero.Node) {
</dt>
<dd>
<ul>
<li class="uppercase">{ data.Protocol }</li>
<li class="uppercase">
@fmtProtocol(data.Protocol)
if data.CORSCapable {
<span class="ml-2">(CORS 💪)</span>
}
</li>
</ul>
</dd>
</dl>
@ -270,7 +281,14 @@ templ Node(data monero.Node) {
</dt>
<dd>
<ul>
<li class="uppercase">{ data.Nettype }</li>
<li class="uppercase">
if data.IsI2P {
<span class="badge bg-green-600 mr-2">I2P</span>
} else if data.IsTor {
<span class="badge bg-purple-800 mr-2">TOR</span>
}
@fmtNettype(data.Nettype)
</li>
</ul>
</dd>
</dl>
@ -287,6 +305,32 @@ templ Node(data monero.Node) {
</dd>
</dl>
}
if data.CountryCode != "" {
<dl class="flex flex-col sm:flex-row gap-1">
<dt class="min-w-40">
<span class="block text-white text-bold">Country:</span>
</dt>
<dd>
<ul>
<li class="whitespace-break-spaces">
@cellCountry(data.CountryCode, data.CountryName, data.City, data.ASNName, data.ASN)
</li>
</ul>
</dd>
</dl>
}
<dl class="flex flex-col sm:flex-row gap-1">
<dt class="min-w-40">
<span class="block text-white text-bold">Monitored Since:</span>
</dt>
<dd>
<ul>
<li class="whitespace-break-spaces">
{ time.Unix(data.DateEntered, 0).UTC().Format("Jan 2, 2006 15:04 MST") } (about { utils.TimeSince(data.DateEntered) })
</li>
</ul>
</dd>
</dl>
</div>
}
@ -413,6 +457,26 @@ templ TableLogs(hxPath string, data monero.FetchLogs, q monero.QueryLogs, p pagi
</div>
}
templ fmtNettype(nettype string) {
switch nettype {
case "stagenet":
<span class="font-semibold uppercase text-sky-500">{ nettype }</span>
case "testnet":
<span class="font-semibold uppercase text-rose-500">{ nettype }</span>
default:
<span class="font-semibold uppercase text-green-500">{ nettype }</span>
}
}
templ fmtProtocol(protocol string) {
switch protocol {
case "http":
<span class="font-semibold uppercase text-sky-500">{ protocol }</span>
default:
<span class="font-semibold uppercase text-green-500">{ protocol }</span>
}
}
templ cellHostPort(id, port uint, hostname, ips string, isTor, isI2P, ipv6Only bool) {
if isTor {
<button
@ -447,7 +511,19 @@ templ cellHostPort(id, port uint, hostname, ips string, isTor, isI2P, ipv6Only b
.i2p:<span class="text-indigo-400">{ fmt.Sprintf("%d", port) }</span>
<span class="badge bg-green-600">I2P</span>
} else {
{ ip.FormatHostname(hostname) }:<span class="text-indigo-400">{ fmt.Sprintf("%d", port) }</span>
<button
class="text-orange-400 hover:brightness-125"
hx-get={ fmt.Sprintf("/remote-nodes/id/%d", id) }
hx-push-url="false"
hx-target="#modal-section"
aria-haspopup="dialog"
aria-expanded="false"
aria-controls="modal-section"
data-hs-overlay="#modal-section"
>
👁 { ip.FormatHostname(hostname) }
</button>
:<span class="text-indigo-400">{ fmt.Sprintf("%d", port) }</span>
<br/>
<div class="max-w-40 text-ellipsis overflow-x-auto md:overflow-hidden hover:overflow-visible">
<span class="whitespace-break-spaces text-gray-400">{ strings.ReplaceAll(ips, ",", " ") }</span>
@ -458,32 +534,6 @@ templ cellHostPort(id, port uint, hostname, ips string, isTor, isI2P, ipv6Only b
}
}
templ cellNettype(nettype string, height uint) {
switch nettype {
case "stagenet":
<span class="font-semibold uppercase text-sky-500">{ nettype }</span>
case "testnet":
<span class="font-semibold uppercase text-rose-500">{ nettype }</span>
default:
<span class="font-semibold uppercase text-green-500">{ nettype }</span>
}
<br/>
{ fmt.Sprintf("%d", height) }
}
templ cellProtocol(protocol string, cors bool) {
switch protocol {
case "http":
<span class="font-semibold uppercase text-sky-500">{ protocol }</span>
default:
<span class="font-semibold uppercase text-green-500">{ protocol }</span>
}
if cors {
<br/>
(CORS 💪)
}
}
templ cellCountry(cc, countryName, city, asnName string, asn uint) {
if cc != "" {
if city != "" {

File diff suppressed because it is too large Load diff

View file

@ -53,7 +53,7 @@ type Node struct {
City string `json:"city" db:"city"`
Latitude float64 `json:"latitude" db:"lat"`
Longitude float64 `json:"longitude" db:"lon"`
DateEntered uint `json:"date_entered,omitempty" db:"date_entered"`
DateEntered int64 `json:"date_entered,omitempty" db:"date_entered"`
LastChecked int64 `json:"last_checked" db:"last_checked"`
FailedCount uint `json:"failed_count,omitempty" db:"failed_count"`
LastCheckStatus types.JSONText `json:"last_check_statuses" db:"last_check_status"`