move nomad network sidebar to own vue component
This commit is contained in:
@@ -251,61 +251,11 @@
|
||||
@peer-click="onPeerClick"/>
|
||||
|
||||
<!-- nomadnetwork sidebar -->
|
||||
<div v-if="tab === 'nomadnetwork'" class="flex flex-col w-80 min-w-80">
|
||||
<div class="flex-1 flex flex-col bg-white border-r overflow-hidden">
|
||||
|
||||
<!-- search -->
|
||||
<div v-if="nodesCount > 0" class="p-1 border-b border-gray-300">
|
||||
<input v-model="nodesSearchTerm" type="text" :placeholder="`Search ${nodesCount} Nodes...`" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
</div>
|
||||
|
||||
<!-- nodes -->
|
||||
<div class="flex h-full overflow-y-auto">
|
||||
<div v-if="searchedNodes.length > 0" class="w-full">
|
||||
<div @click="onNodeClick(node)" v-for="node of searchedNodes" class="flex cursor-pointer p-2 border-l-2" :class="[ node.destination_hash === selectedNode?.destination_hash ? 'bg-gray-100 border-blue-500' : 'bg-white border-transparent hover:bg-gray-50 hover:border-gray-200' ]">
|
||||
<div class="my-auto mr-2">
|
||||
<div class="bg-gray-200 text-gray-500 p-2 rounded">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-gray-900">{{ node.name }}</div>
|
||||
<div class="text-gray-500 text-sm">{{ formatTimeAgo(node.updated_at) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="mx-auto my-auto text-center leading-5">
|
||||
|
||||
<!-- no nodes at all -->
|
||||
<div v-if="nodesCount === 0" class="flex flex-col">
|
||||
<div class="mx-auto mb-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="font-semibold">No Nodes Discovered</div>
|
||||
<div>Waiting for a node to announce!</div>
|
||||
</div>
|
||||
|
||||
<!-- is searching, but no results -->
|
||||
<div v-if="nodesSearchTerm !== '' && nodesCount > 0" class="flex flex-col">
|
||||
<div class="mx-auto mb-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="font-semibold">No Search Results</div>
|
||||
<div>Your search didn't match any Nodes!</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<NomadNetworkSidebar
|
||||
v-if="tab === 'nomadnetwork'"
|
||||
:nodes="nodes"
|
||||
:selected-destination-hash="selectedNode?.destination_hash"
|
||||
@node-click="onNodeClick"/>
|
||||
|
||||
<!-- main view -->
|
||||
<div class="flex flex-col flex-1 overflow-hidden min-w-full sm:min-w-[500px]">
|
||||
@@ -1092,10 +1042,12 @@
|
||||
<script>
|
||||
import SidebarLink from "./SidebarLink.vue";
|
||||
import MessagesSidebar from "./messages/MessagesSidebar.vue";
|
||||
import NomadNetworkSidebar from "./nomadnetwork/NomadNetworkSidebar.vue";
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
NomadNetworkSidebar,
|
||||
MessagesSidebar,
|
||||
SidebarLink,
|
||||
},
|
||||
@@ -1125,12 +1077,12 @@ export default {
|
||||
lxmfDeliveryAnnounces: [],
|
||||
|
||||
tab: "messages",
|
||||
|
||||
peers: {},
|
||||
selectedPeer: null,
|
||||
selectedPeerPath: null,
|
||||
|
||||
nodes: {},
|
||||
nodesSearchTerm: "",
|
||||
selectedNode: null,
|
||||
selectedNodePath: null,
|
||||
|
||||
@@ -3019,26 +2971,6 @@ export default {
|
||||
return [];
|
||||
|
||||
},
|
||||
nodesCount() {
|
||||
return Object.keys(this.nodes).length;
|
||||
},
|
||||
nodesOrderedByLatestAnnounce() {
|
||||
const nodes = Object.values(this.nodes);
|
||||
return nodes.sort(function(nodeA, nodeB) {
|
||||
// order by updated_at desc
|
||||
const nodeAUpdatedAt = new Date(nodeA.updated_at).getTime();
|
||||
const nodeBUpdatedAt = new Date(nodeB.updated_at).getTime();
|
||||
return nodeBUpdatedAt - nodeAUpdatedAt;
|
||||
});
|
||||
},
|
||||
searchedNodes() {
|
||||
return this.nodesOrderedByLatestAnnounce.filter((node) => {
|
||||
const search = this.nodesSearchTerm.toLowerCase();
|
||||
const matchesAppData = node.name.toLowerCase().includes(search);
|
||||
const matchesDestinationHash = node.destination_hash.toLowerCase().includes(search);
|
||||
return matchesAppData || matchesDestinationHash;
|
||||
});
|
||||
},
|
||||
unreadConversationsCount() {
|
||||
return this.conversations.filter((conversation) => {
|
||||
return conversation.is_unread;
|
||||
|
||||
108
src/frontend/components/nomadnetwork/NomadNetworkSidebar.vue
Normal file
108
src/frontend/components/nomadnetwork/NomadNetworkSidebar.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="flex flex-col w-80 min-w-80">
|
||||
<div class="flex-1 flex flex-col bg-white border-r overflow-hidden">
|
||||
|
||||
<!-- search -->
|
||||
<div v-if="nodesCount > 0" class="p-1 border-b border-gray-300">
|
||||
<input v-model="nodesSearchTerm" type="text" :placeholder="`Search ${nodesCount} Nodes...`" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
|
||||
</div>
|
||||
|
||||
<!-- nodes -->
|
||||
<div class="flex h-full overflow-y-auto">
|
||||
<div v-if="searchedNodes.length > 0" class="w-full">
|
||||
<div @click="onNodeClick(node)" v-for="node of searchedNodes" class="flex cursor-pointer p-2 border-l-2" :class="[ node.destination_hash === selectedDestinationHash ? 'bg-gray-100 border-blue-500' : 'bg-white border-transparent hover:bg-gray-50 hover:border-gray-200' ]">
|
||||
<div class="my-auto mr-2">
|
||||
<div class="bg-gray-200 text-gray-500 p-2 rounded">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 14.25h13.5m-13.5 0a3 3 0 0 1-3-3m3 3a3 3 0 1 0 0 6h13.5a3 3 0 1 0 0-6m-16.5-3a3 3 0 0 1 3-3h13.5a3 3 0 0 1 3 3m-19.5 0a4.5 4.5 0 0 1 .9-2.7L5.737 5.1a3.375 3.375 0 0 1 2.7-1.35h7.126c1.062 0 2.062.5 2.7 1.35l2.587 3.45a4.5 4.5 0 0 1 .9 2.7m0 0a3 3 0 0 1-3 3m0 3h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Zm-3 6h.008v.008h-.008v-.008Zm0-6h.008v.008h-.008v-.008Z" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-gray-900">{{ node.name }}</div>
|
||||
<div class="text-gray-500 text-sm">{{ formatTimeAgo(node.updated_at) }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="mx-auto my-auto text-center leading-5">
|
||||
|
||||
<!-- no nodes at all -->
|
||||
<div v-if="nodesCount === 0" class="flex flex-col">
|
||||
<div class="mx-auto mb-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 5.25h.008v.008H12v-.008Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="font-semibold">No Nodes Discovered</div>
|
||||
<div>Waiting for a node to announce!</div>
|
||||
</div>
|
||||
|
||||
<!-- is searching, but no results -->
|
||||
<div v-if="nodesSearchTerm !== '' && nodesCount > 0" class="flex flex-col">
|
||||
<div class="mx-auto mb-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="font-semibold">No Search Results</div>
|
||||
<div>Your search didn't match any Nodes!</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import Utils from "../../js/Utils";
|
||||
|
||||
export default {
|
||||
name: 'NomadNetworkSidebar',
|
||||
props: {
|
||||
nodes: Object,
|
||||
selectedDestinationHash: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
nodesSearchTerm: "",
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
onNodeClick(node) {
|
||||
this.$emit("node-click", node);
|
||||
},
|
||||
formatTimeAgo: function(datetimeString) {
|
||||
return Utils.formatTimeAgo(datetimeString);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
nodesCount() {
|
||||
return Object.keys(this.nodes).length;
|
||||
},
|
||||
nodesOrderedByLatestAnnounce() {
|
||||
const nodes = Object.values(this.nodes);
|
||||
return nodes.sort(function(nodeA, nodeB) {
|
||||
// order by updated_at desc
|
||||
const nodeAUpdatedAt = new Date(nodeA.updated_at).getTime();
|
||||
const nodeBUpdatedAt = new Date(nodeB.updated_at).getTime();
|
||||
return nodeBUpdatedAt - nodeAUpdatedAt;
|
||||
});
|
||||
},
|
||||
searchedNodes() {
|
||||
return this.nodesOrderedByLatestAnnounce.filter((node) => {
|
||||
const search = this.nodesSearchTerm.toLowerCase();
|
||||
const matchesAppData = node.name.toLowerCase().includes(search);
|
||||
const matchesDestinationHash = node.destination_hash.toLowerCase().includes(search);
|
||||
return matchesAppData || matchesDestinationHash;
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user