Browse Source

resolve conflict

feature/nostr-signer
dskvr 2 years ago
parent
commit
6874490791
  1. 4
      README.md
  2. 2
      package.json
  3. 24
      relays.yaml
  4. 24
      src/components/FooterComponent.vue
  5. 13
      src/components/GroupByAvailability.vue
  6. 4
      src/components/GroupByNone.vue
  7. 40
      src/components/HeaderComponent.vue
  8. 9
      src/components/LeafletComponent.vue
  9. 6
      src/components/LeafletSingleComponent.vue
  10. 4
      src/components/NavComponent.vue
  11. 2
      src/components/PreferencesComponent.vue
  12. 11
      src/components/RefreshComponent.vue
  13. 101
      src/components/RelayGroupedListComponent.vue
  14. 41
      src/components/RelayListComponent.vue
  15. 0
      src/components/RelaySingleComponent.vue
  16. 28
      src/components/TableHeaders.vue
  17. 8
      src/lib/relays-lib.js
  18. 44
      src/pages/HomePage.vue
  19. 217
      src/pages/SingleRelay.vue

4
README.md

@ -1,6 +1,8 @@
> this project is alpha! changes are fast and hard. branching model and tests will come with beta.
# nostr-watch
A client-side nostr network status built with Vue3, [nostr-js](https://github.com/jb55/nostr-js) and [nostr-relay-inspector](https://github.com/dskvr/nostr-relay-inspector). Goal is to produce a client-side app that collects detailed information about nostr relays and the network in general to assist users, developers and relay operators alike.
A client-side nostr network status built with Vue3, [nostr-js](https://github.com/jb55/nostr-js) and [nostr-relay-inspector](https://github.com/dskvr/nostr-relay-inspector). Goal is to produce a client-side app that collects detailed information about nostr relays and the network in general to assist users, developers and relay operators alike
## Features
- [x] Real-time relay status

2
package.json

@ -1,6 +1,6 @@
{
"name": "nostr-watch",
"version": "0.0.22",
"version": "0.0.23",
"private": true,
"scripts": {
"build": "vue-cli-service build",

24
relays.yaml

@ -1,5 +1,9 @@
relays:
- wss://sg.qemura.xyz
- wss://relay.nyx.ma
- wss://nostr.bongbong.com
- wss://nostr-3.orba.ca
- wss://wizards.wormrobot.org
- wss://satstacker.cloud
- wss://freedom-relay.herokuapp.com/ws
- wss://nostr-relay.freeberty.net
@ -95,6 +99,24 @@ relays:
- wss://nostr.einundzwanzig.space
- wss://nostr.d11n.net
- wss://nostr1.tunnelsats.com
- wss://nostr.tunnelsats.com
- wss://nostr.leximaster.com
- wss://nostr.hugo.md
- wss://nostr.robotechy.com
- wss://nostr.mtandao.xyz
- wss://relay.stoner.com
- wss://nostr.mado.io
- wss://nostr.gruntwerk.org
- wss://nostr.utxo.lol
- wss://jiggytom.ddns.net
- wss://nostr-relay.digitalmob.ro
- wss://nostr.walletofsatoshi.com
- wss://nostr.roundrockbitcoiners.com
- wss://nostr.orangepill.dev
- wss://nostr1.starbackr.me
- wss://nostr-relay.alekberg.net
- wss://nostr.blocs.fr
- wss://nostr.f44.dev
- wss://nostr.demovement.net
- wss://nostr.mustardnodes.com
- wss://nostr.ethtozero.fr
- wss://nostr.hackerman.pro

24
src/components/FooterComponent.vue

@ -1,29 +1,7 @@
<template>
<section id="footer">
<span>Updated {{ refreshData.sinceLast }} ago</span>
<span><button @click="invalidate(true)">Update Now</button></span>
<span><input type="checkbox" id="checkbox" v-model="preferences.refresh" /><label for="">Refresh Automatically</label></span>
<span v-if="preferences.refresh"> Next refresh in: {{ refreshData.untilNext }}</span>
<span v-if="preferences.refresh">
Refresh Every
<input type="radio" id="1w" :value="1000*60*60*24*7" v-model="cacheExpiration" />
<label for="1w">1 Week</label>
<input type="radio" id="1d" :value="1000*60*60*24" v-model="cacheExpiration" />
<label for="1d">1 day</label>
<input type="radio" id="30m" :value="1000*60*30" v-model="cacheExpiration" />
<label for="30m">30 minutes</label>
<input type="radio" id="10m" :value="1000*60*10" v-model="cacheExpiration" />
<label for="10m">10 minutes</label>
<input type="radio" id="1m" :value="1000*60" v-model="cacheExpiration" />
<label for="1m">1 Minute</label>
</span>
<span class="credit"><a href="http://sandwich.farm">Another 🥪 by sandwich.farm</a>, built with <a href="https://github.com/jb55/nostr-js">nostr-js</a> and <a href="https://github.com/dskvr/nostr-relay-inspector">nostr-relay-inspector</a>, inspired by <a href="https://github.com/fiatjaf/nostr-relay-registry">nostr-relay-registry</a></span>
</section>
</template>
<script>
</script>

13
src/pages/groups/GroupByAvailability.vue → src/components/GroupByAvailability.vue

@ -1,5 +1,6 @@
<template>
<table>
<RelayGroupedListComponent
section="public"
:relays="relays"
@ -29,16 +30,6 @@
:alerts="alerts"
:connections="connections"
/>
<RelayGroupedListComponent
section="processing"
:relays="relays"
:result="result"
:messages="messages"
:alerts="alerts"
:connections="connections"
:showJson="false"
/>
</table>
</template>
@ -46,7 +37,7 @@
import { defineComponent} from 'vue'
import RelayGroupedListComponent from '../lists/RelayGroupedListComponent.vue'
import RelayGroupedListComponent from './RelayGroupedListComponent.vue'
export default defineComponent({
title: "nostr.watch registry & network status",

4
src/pages/groups/GroupByNone.vue → src/components/GroupByNone.vue

@ -13,7 +13,7 @@
<script>
import { defineComponent} from 'vue'
import RelayListComponent from '../lists/RelayListComponent.vue'
import RelayListComponent from './RelayListComponent.vue'
export default defineComponent({
title: "nostr.watch registry & network status",
@ -84,7 +84,7 @@ export default defineComponent({
}
},
mounted(){
console.log(this.relays)
// console.log(this.relays)
},
data() {
return {}

40
src/components/HeaderComponent.vue

@ -0,0 +1,40 @@
<template>
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<h1>nostr.watch<sup>{{version}}</sup></h1>
</column>
</row>
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<NavComponent :relays="relays" />
</column>
</row>
</template>
<script>
import { version } from '../../package.json'
import { defineComponent} from 'vue'
import NavComponent from './NavComponent.vue'
export default defineComponent({
title: "nostr.watch registry & network status",
name: 'GroupByNone',
components: {
NavComponent,
},
props: {
relays: {
type: Array,
default(){
return []
}
},
},
data(){
return {
version: version
}
}
})
</script>

9
src/components/LeafletComponent.vue

@ -26,8 +26,8 @@
v-for="([relay, entry]) in Object.entries(geo)"
:lat-lng="getLatLng(entry)"
:key="relay"
:radius="3"
:weight="6"
:radius="2"
:weight="4"
:color="getCircleColor(relay)"
:fillOpacity="1"
:class="relay"
@ -114,7 +114,6 @@ export default {
}
},
},
};
@ -123,7 +122,7 @@ export default {
<style scoped>
.leaflet-container {
position:relative;
z-index:1000;
z-index:900;
margin:0;
padding:0;
height:250px !important;
@ -142,7 +141,7 @@ export default {
button {
position: relative;
z-index:1001;
z-index:901;
top: -30px;
background:rgba(255,255,255,0.5);
border:0;

6
src/components/LeafletSingleComponent.vue

@ -24,8 +24,8 @@
<l-circle-marker
:lat-lng="center"
:radius="3"
:weight="6"
:radius="2"
:weight="4"
:color="markerColor"
:fillOpacity="1"
:class="relay"
@ -60,7 +60,7 @@ export default {
const relay = this.relay
console.log(this.geo[this.relay]?.lat, this.geo[this.relay]?.lon)
//console.log(this.geo[this.relay]?.lat, this.geo[this.relay]?.lon)
if(!this.geo[this.relay]?.lat || !this.geo[this.relay]?.lon)
return 'transparent'

4
src/components/NavComponent.vue

@ -1,9 +1,9 @@
<template>
<nav class="menu">
<ul>
<!-- <router-link :to="`/`" active-class="active" :class="">Home</router-link> -->
<router-link :to="`/`" active-class="active">Home</router-link>
<a href="https://github.com/dskvr/nostr-watch/edit/main/relays.yaml" target="_blank">Add Relay</a>
<a href="relays.json"><code>{...}</code></a>
<a href="/relays.json"><code>{...}</code></a>
<span>
<PreferencesComponent :relays="relays" />
</span>

2
src/components/PreferencesComponent.vue

@ -84,7 +84,7 @@ const localMethods = {
},
clearData(){
this.relays.forEach( relay => {
console.log('clearing', relay)
// console.log('clearing', relay)
this.removeCache(`${relay}`)
this.removeCache(`${relay}_inbox`)
})

11
src/components/RefreshComponent.vue

@ -26,16 +26,17 @@ const localMethods = {
return this.timeSince(Date.now()-(this.lastUpdate+this.preferences.cacheExpiration-Date.now()))
},
setRefreshInterval: function(){
clearInterval(this.interval)
this.interval = setInterval(() => {
this.preferences = this.getCache('preferences') || this.preferences
this.refreshData.untilNext = this.timeUntilRefresh()
this.refreshData.sinceLast = this.timeSinceRefresh()
console.log('is expired', this.isExpired())
//console.log('is expired', this.isExpired())
// if(this.isExpired() && this.preferences.refresh)
// this.invalidate(false, this.relay)
if(this.isExpired() && this.preferences.refresh)
this.invalidate(false, this.relay)
}, 1000)
}
@ -60,9 +61,7 @@ export default defineComponent({
},
updated(){
this.setCache('preferences')
// if(this.relays && this.isDone())
// this.setCache('lastUpdate')
this.refreshData.untilNext = this.timeUntilRefresh()
this.refreshData.sinceLast = this.timeSinceRefresh()
},

101
src/pages/lists/RelayGroupedListComponent.vue → src/components/RelayGroupedListComponent.vue

@ -2,9 +2,9 @@
<tr :class="getHeadingClass()">
<vue-final-modal v-model="showModal" classes="modal-container" content-class="modal-content">
<div class="modal__content">
<span>
<pre>
{{ queryJson(section) }}
</span>
</pre>
</div>
</vue-final-modal>
<td colspan="11">
@ -12,36 +12,7 @@
</td>
</tr>
<tr :class="getHeadingClass()" v-if="sort(section).length > 0">
<th class="table-column status-indicator"></th>
<th class="table-column relay"></th>
<th class="table-column verified">
<span class="verified-shape-wrapper">
<span class="shape verified"></span>
</span>
</th>
<th class="table-column location" v-tooltip:top.tooltip="Ping">
🌎
</th>
<th class="table-column latency" v-tooltip:top.tooltip="'Relay Latency on Read'">
</th>
<th class="table-column connect" v-tooltip:top.tooltip="'Relay connection status'">
🔌
</th>
<th class="table-column read" v-tooltip:top.tooltip="'Relay read status'">
👁🗨
</th>
<th class="table-column write" v-tooltip:top.tooltip="'Relay write status'">
</th>
<th class="table-column info" v-tooltip:top.tooltip="'Additional information detected regarding the relay during processing'">
ℹ️
</th>
<!-- <th class="table-column nip nip-20" v-tooltip:top.tooltip="'Does the relay support NIP-20'">
<span>NIP-11</span>
</th> -->
<TableHeaders />
</tr>
<tr v-for="(relay, index) in sort(section)" :key="{relay}" :class="getResultClass(relay, index)" class="relay">
<RelaySingleComponent
@ -55,13 +26,13 @@
</template>
<script>
import { defineComponent} from 'vue'
import { VueFinalModal } from 'vue-final-modal'
import RelaySingleComponent from '../single/RelaySingleComponent.vue'
import RelaySingleComponent from './RelaySingleComponent.vue'
import TableHeaders from './TableHeaders.vue'
import RelaysLib from '../../lib/relays-lib.js'
import RelaysLib from '../lib/relays-lib.js'
const localMethods = {
getHeadingClass(){
@ -82,40 +53,30 @@ const localMethods = {
}
},
sort_by_latency(ascending) {
const self = this
return function (a, b) {
// equal items sort equally
if (self.result?.[a]?.latency.final === self.result?.[b]?.latency.final) {
return 0;
}
// nulls sort after anything else
if (self.result?.[a]?.latency.final === null) {
return 1;
}
if (self.result?.[b]?.latency.final === null) {
return -1;
}
// otherwise, if we're ascending, lowest sorts first
if (ascending) {
return self.result?.[a]?.latency.final - self.result?.[b]?.latency.final;
}
// if descending, highest sorts first
return self.result?.[b]?.latency.final-self.result?.[a]?.latency.final;
};
},
sortByLatency () {
let unsorted
const self = this
return function (a, b) {
// equal items sort equally
if (self.result?.[a]?.latency.final === self.result?.[b]?.latency.final) {
return 0;
}
unsorted = this.relays;
// nulls sort after anything else
if (self.result?.[a]?.latency.final === null) {
return 1;
}
if (self.result?.[b]?.latency.final === null) {
return -1;
}
if (unsorted.length)
return unsorted.sort(this.sort_by_latency(true))
// otherwise, if we're ascending, lowest sorts first
if (ascending) {
return self.result?.[a]?.latency.final - self.result?.[b]?.latency.final;
}
return []
},
// if descending, highest sorts first
return self.result?.[b]?.latency.final-self.result?.[a]?.latency.final;
};
},
queryJson(aggregate){
const relays = this.sort(aggregate)
const result = {}
@ -141,7 +102,8 @@ export default defineComponent({
name: 'RelayListComponent',
components: {
RelaySingleComponent,
VueFinalModal
VueFinalModal,
TableHeaders
},
props: {
showJson: {
@ -239,11 +201,12 @@ export default defineComponent({
align-items: center;
}
::v-deep(.modal-content) {
text-align:left;
position: relative;
display: flex;
flex-direction: column;
max-height: 90%;
max-width:400px;
max-height: 500px;
max-width:800px;
margin: 0 1rem;
padding: 1rem;
border: 1px solid #e2e8f0;

41
src/pages/lists/RelayListComponent.vue → src/components/RelayListComponent.vue

@ -13,36 +13,7 @@
</td>
</tr>
<tr v-if="this.relays.length > 0">
<th class="table-column status-indicator"></th>
<th class="table-column relay"></th>
<th class="table-column verified">
<span class="verified-shape-wrapper">
<span class="shape verified"></span>
</span>
</th>
<th class="table-column location" v-tooltip:top.tooltip="Ping">
🌎
</th>
<th class="table-column latency" v-tooltip:top.tooltip="'Relay Latency on Read'">
</th>
<th class="table-column connect" v-tooltip:top.tooltip="'Relay connection status'">
🔌
</th>
<th class="table-column read" v-tooltip:top.tooltip="'Relay read status'">
👁🗨
</th>
<th class="table-column write" v-tooltip:top.tooltip="'Relay write status'">
</th>
<!-- <th class="table-column info" v-tooltip:top.tooltip="'Additional information detected regarding the relay during processing'">
ℹ️
</th> -->
<!-- <th class="table-column nip nip-20" v-tooltip:top.tooltip="'Does the relay support NIP-20'">
<span>NIP-11</span>
</th> -->
<TableHeaders />
</tr>
<tr v-for="(relay, index) in sort(relays[relay]?.aggregate)" :key="{relay}" class="relay" :class="getResultClass(relay, index)">
<RelaySingleComponent
@ -58,9 +29,10 @@
import { defineComponent} from 'vue'
import { VueFinalModal } from 'vue-final-modal'
import RelaySingleComponent from '../single/RelaySingleComponent.vue'
import RelaySingleComponent from './RelaySingleComponent.vue'
import TableHeaders from './TableHeaders.vue'
import RelaysLib from '../../lib/relays-lib.js'
import RelaysLib from '../lib/relays-lib.js'
const localMethods = {
// getHeadingClass(){
@ -148,7 +120,8 @@ export default defineComponent({
name: 'RelayListComponent',
components: {
RelaySingleComponent,
VueFinalModal
VueFinalModal,
TableHeaders
},
props: {
showJson: {
@ -228,7 +201,7 @@ export default defineComponent({
display: flex;
flex-direction: column;
max-height: 90%;
max-width:400px;
max-width:800px;
margin: 0 1rem;
padding: 1rem;
border: 1px solid #e2e8f0;

0
src/pages/single/RelaySingleComponent.vue → src/components/RelaySingleComponent.vue

28
src/components/TableHeaders.vue

@ -0,0 +1,28 @@
<template>
<th class="table-column status-indicator">
</th>
<th class="table-column relay">
</th>
<th class="table-column verified">
<span class="verified-shape-wrapper">
<span class="shape verified"></span>
</span>
</th>
<th class="table-column location" v-tooltip:top.tooltip="Ping">
🌎
</th>
<th class="table-column latency" v-tooltip:top.tooltip="'Relay Latency on Read'">
</th>
<th class="table-column connect" v-tooltip:top.tooltip="'Relay connection status'">
🔌
</th>
<th class="table-column read" v-tooltip:top.tooltip="'Relay read status'">
👁🗨
</th>
<th class="table-column write" v-tooltip:top.tooltip="'Relay write status'">
</th>
</template>

8
src/lib/relays-lib.js

@ -11,7 +11,7 @@ export default {
this.setCache('lastUpdate')
console.log('invalidate', 'total relays', this.relays.length)
// console.log('invalidate', 'total relays', this.relays.length)
if(single) {
await this.check(single)
@ -19,11 +19,11 @@ export default {
this.messages[single] = this.getCache(`${single}_inbox`)
}
else {
console.log('total relays', this.relays.length)
console.log(this.relays.length)
// console.log('total relays', this.relays.length)
// console.log(this.relays.length)
for(let index = 0; index < this.relays.length; index++) {
let relay = this.relays[index]
console.log('invalidating', relay)
// console.log('invalidating', relay)
await this.delay(20).then( () => {
this.check(relay)
.then(() => {

44
src/pages/HomePage.vue

@ -7,32 +7,12 @@
<div id="wrapper">
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<h1>nostr.watch<sup>{{version}}</sup></h1>
</column>
</row>
<HeaderComponent :relays="relays" />
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<NavComponent :relays="relays" />
</column>
</row>
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="list">
<span>Group By:</span>
<tabs :options="{ useUrlFragment: false }" @clicked="tabClicked" @changed="tabChanged" nav-item-class="nav-item">
<tab name="None">
<GroupByNone
:relays="relays"
:result="result"
:geo="geo"
:messages="messages"
:alerts="alerts"
:connections="connections">
</GroupByNone>
</tab>
<tab name="Availability">
<GroupByAvailability
section="processing"
@ -45,6 +25,17 @@
:showJson="false">
</GroupByAvailability>
</tab>
<tab name="None">
<GroupByNone
:relays="relays"
:result="result"
:geo="geo"
:messages="messages"
:alerts="alerts"
:connections="connections">
</GroupByNone>
</tab>
</tabs>
</column>
</row>
@ -85,15 +76,14 @@ import { Row, Column } from 'vue-grid-responsive';
import RelaysLib from '../lib/relays-lib.js'
import LeafletComponent from '../components/LeafletComponent.vue'
import NavComponent from '../components/NavComponent.vue'
import RefreshComponent from '../components/RefreshComponent.vue'
import HeaderComponent from '../components/HeaderComponent.vue'
import { version } from '../../package.json'
import { relays } from '../../relays.yaml'
import { geo } from '../../cache/geo.yaml'
import GroupByNone from './groups/GroupByNone.vue'
import GroupByAvailability from './groups/GroupByAvailability.vue'
import GroupByNone from '../components/GroupByNone.vue'
import GroupByAvailability from '../components/GroupByAvailability.vue'
export default defineComponent({
title: "nostr.watch registry & network status",
@ -103,11 +93,10 @@ export default defineComponent({
Row,
Column,
LeafletComponent,
NavComponent,
RefreshComponent,
GroupByAvailability,
GroupByNone,
HeaderComponent
},
data() {
@ -122,7 +111,6 @@ export default defineComponent({
count: 0,
storage: null,
geo,
version: version,
hasStorage: false,
// cacheExpiration: 10*60*1000, //10 minutes
}

217
src/pages/SingleRelay.vue

@ -4,116 +4,116 @@
:relay="relay"
:result="result"
/>
<!-- <NavComponent /> -->
<div id="wrapper">
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<h1>{{ relayUrl() }}</h1>
</column>
</row>
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<NavComponent :relays="relays" />
</column>
</row>
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<div style="display: none">{{result}}</div> <!-- ? -->
<br >
<span class="badges">
<span><img :src="badgeCheck('connect')" /></span>
<span><img :src="badgeCheck('read')" /></span>
<span><img :src="badgeCheck('write')" /></span>
</span>
</column>
</row>
<br />
<div id="wrapper">
<row container :gutter="12" v-if="!result?.check?.connect">
<column :xs="12" :md="12" :lg="12" class="title-card">
This relay appears to be offline.
</column>
</row>
<HeaderComponent :relays="relays" />
<br />
<div id="relay-wrapper">
<row container :gutter="12" v-if="result?.check?.connect">
<column :xs="12" :md="12" :lg="12" class="title-card">
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<span v-tooltip:top.tooltip="'Click to copy'" style="display:block">
<h2 @click="copy(relayUrl())">{{ relayUrl() }}</h2>
</span>
</column>
</row>
<row container :gutter="12">
<column :xs="12" :md="12" :lg="12" class="title-card">
<span class="badges">
<span><img :src="badgeCheck('connect')" /></span>
<span><img :src="badgeCheck('read')" /></span>
<span><img :src="badgeCheck('write')" /></span>
</span>
<span v-if="result.info?.supported_nips" class="badges">
<span v-for="(nip) in result.info.supported_nips" :key="`${relay}_${nip}`">
<a :href="nipLink(nip)" target="_blank"><img :src="badgeLink(nip)" /></a>
<span v-for="(nip) in result.info.supported_nips" :key="`${relay}_${nip}`">
<a :href="nipLink(nip)" target="_blank"><img :src="badgeLink(nip)" /></a>
</span>
</span>
</span>
</column>
</row>
<table v-if="result.info">
<tr>
<th colspan="2"><h4>Info</h4></th>
</tr>
<tbody v-if="result.info">
<tr v-for="(value, key) in Object.entries(result.info).filter(value => value[0] != 'id' && value[0] != 'supported_nips')" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td v-if="value[0]!='contact' && value[0]!='pubkey' && value[0]!='software' && value[0]!='version'">{{ value[1] }} </td>
<td v-if="value[0]=='contact'"><SafeMail :email="value[1]" /></td>
<td v-if="value[0]=='pubkey' || value[0]=='version'"><code>{{ value[1] }}</code></td>
<td v-if="value[0]=='software'"><a :href="value[1]">{{ value[1] }}</a></td>
</tr>
</tbody>
<tr v-if="Object.entries(result.info).length == 0 && result.check.connect">
Relay does not have NIP-11 support, or the administrator has not configured the relay to return information.
</tr>
</table>
<h4>Identities</h4>
<table v-if="result.identities">
<tr v-for="(value, key) in Object.entries(result?.identities)" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td><code>{{ value[1] }}</code></td>
</tr>
<tr v-if="Object.entries(result.identities).length==0">
Relay does not provide NIP-05 support and has not registered an administrator key.
</tr>
</table>
<div style="display: none">{{result}}</div> <!-- ? -->
<row container :gutter="12" v-if="!result?.check?.connect">
<column :xs="12" :md="12" :lg="12" class="title-card">
This relay appears to be offline.
</column>
<column :xs="12" :md="6" :lg="6" class="title-card">
</row>
<row container :gutter="12" v-if="result?.check?.connect">
<column :xs="12" :md="12" :lg="12" class="title-card">
<table v-if="result.info">
<tr>
<th colspan="2"><h4>Info</h4></th>
</tr>
<tbody v-if="result.info">
<tr v-for="(value, key) in Object.entries(result.info).filter(value => value[0] != 'id' && value[0] != 'supported_nips')" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td v-if="value[0]!='contact' && value[0]!='pubkey' && value[0]!='software' && value[0]!='version'">{{ value[1] }} </td>
<td v-if="value[0]=='contact'"><SafeMail :email="value[1]" /></td>
<td v-if="value[0]=='pubkey' || value[0]=='version'"><code>{{ value[1] }}</code></td>
<td v-if="value[0]=='software'"><a :href="value[1]">{{ value[1] }}</a></td>
</tr>
</tbody>
<tr v-if="Object.entries(result.info).length == 0 && result.check.connect">
Relay does not have NIP-11 support, or the administrator has not configured the relay to return information.
</tr>
</table>
<h4>GEO {{geo?.countryCode ? getFlag() : ''}}</h4>
<table v-if="geo[relay]">
<tr v-for="(value, key) in Object.entries(geo[relay])" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td>{{ value[1] }} </td>
</tr>
</table>
</column>
<column :xs="12" :md="6" :lg="6" class="title-card">
<h4>DNS</h4>
<table v-if="geo[relay]">
<tr v-for="(value, key) in Object.entries(geo[relay].dns)" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td>{{ value[1] }} </td>
</tr>
</table>
<div style="display: none">{{result}}</div> <!-- ? -->
</column>
</row>
<table v-if="result.identities">
<tr>
<th colspan="2"><h4>Identities</h4></th>
</tr>
<tbody v-if="result.identities">
<tr v-for="(value, key) in Object.entries(result?.identities)" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td><code>{{ value[1] }}</code></td>
</tr>
<tr v-if="Object.entries(result.identities).length==0">
Relay does not provide NIP-05 support and has not registered an administrator key.
</tr>
</tbody>
</table>
</column>
<column :xs="12" :md="6" :lg="6" class="title-card">
<table v-if="geo[relay]">
<tr>
<th colspan="2"><h4>GEO {{geo?.countryCode ? getFlag() : ''}}</h4></th>
</tr>
<tbody v-if="geo[relay]">
<tr v-for="(value, key) in Object.entries(geo[relay])" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td>{{ value[1] }} </td>
</tr>
</tbody>
</table>
</column>
<column :xs="12" :md="6" :lg="6" class="title-card">
<table v-if="geo[relay]">
<tr>
<th colspan="2"><h4>DNS</h4></th>
</tr>
<tbody v-if="geo[relay]">
<tr v-for="(value, key) in Object.entries(geo[relay].dns)" :key="`${value}_${key}`">
<td>{{ value[0] }}</td>
<td>{{ value[1] }} </td>
</tr>
</tbody>
</table>
</column>
</row>
<!-- <RefreshComponent
:relay="relay"
/> -->
</div>
<!-- <RefreshComponent
:relay="relay"
/> -->
<span class="credit"><a href="http://sandwich.farm">Another 🥪 by sandwich.farm</a>, built with <a href="https://github.com/jb55/nostr-js">nostr-js</a> and <a href="https://github.com/dskvr/nostr-relay-inspector">nostr-relay-inspector</a>, inspired by <a href="https://github.com/fiatjaf/nostr-relay-registry">nostr-relay-registry</a></span>
</div>
</template>
@ -123,7 +123,8 @@ import { defineComponent} from 'vue'
import { useStorage } from "vue3-storage";
import LeafletSingleComponent from '../components/LeafletSingleComponent.vue'
import NavComponent from '../components/NavComponent.vue'
import HeaderComponent from '../components/HeaderComponent.vue'
// import NavComponent from '../components/NavComponent.vue'
// import RefreshComponent from '../components/RefreshComponent.vue'
import { Row, Column } from 'vue-grid-responsive';
@ -160,6 +161,14 @@ const localMethods = {
nipLink(key){
return `https://github.com/nostr-protocol/nips/blob/master/${this.nipSignature(key)}.md`
},
async copy(text) {
try {
await navigator.clipboard.writeText(text);
} catch($e) {
//console.log('Cannot copy');
}
},
}
export default defineComponent({
@ -170,8 +179,9 @@ export default defineComponent({
Row,
Column,
LeafletSingleComponent,
NavComponent,
// NavComponent,
SafeMail,
HeaderComponent,
// RefreshComponent,
},
@ -223,13 +233,16 @@ export default defineComponent({
ul, ul li { padding:0; margin:0; list-style:none; }
td { padding:5px 10px; }
th h4 { text-align:center; padding:5px 10px; margin:0 0 6px; background:#f0f0f0; }
table {width:90%; max-width:90%; margin:0 auto 20px ; border: 2px solid #f5f5f5; padding:20px}
table {margin:20px 10px 20px; border: 2px solid #f5f5f5; padding:20px}
tr td:first-child { text-align:right }
tr td:last-child { text-align:left }
.indicator { display: table-cell; width:33% ; font-weight:bold; text-align: center !important; color: white; text-transform: uppercase; font-size:0.8em}
body, .grid-column { padding:0; margin:0; }
.badges { display:block; margin: 10px 0 0}
.badges { display:block; margin: 10px 0 11px}
.badges > span {margin-right:5px}
#wrapper {max-width:800px}
h1 {margin: 25px 0 15px; padding:0 0 10px; border-bottom:3px solid #e9e9e9}
#relay-wrapper { margin: 50px 0 20px; padding: 20px 0}
h2 {cursor:pointer;font-size:40pt; margin: 0px 0 15px; padding:0 0 10px; border-bottom:3px solid #e9e9e9}
</style>

Loading…
Cancel
Save