Add button to remove peers
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
import { flip } from "svelte/animate";
|
import { flip } from "svelte/animate";
|
||||||
import { formatDataVolume } from "util/Formatting";
|
import { formatDataVolume } from "util/Formatting";
|
||||||
import SortButton from "layout/SortButton.svelte";
|
import SortButton from "layout/SortButton.svelte";
|
||||||
|
import { loading_run } from "lib/Loading";
|
||||||
|
import { admin_decommission_node } from "lib/AdminAPI";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
peers = $bindable([])
|
peers = $bindable([])
|
||||||
@@ -33,6 +35,11 @@ let {
|
|||||||
}[]
|
}[]
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
|
// If not all peers are online we show the decommission button
|
||||||
|
let all_reachable = $derived(peers.reduce((acc, val) => {
|
||||||
|
return val.reachable ? acc : false
|
||||||
|
}, true))
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
for (let peer of peers) {
|
for (let peer of peers) {
|
||||||
peer.avg_network_total = peer.avg_network_tx + peer.avg_network_rx
|
peer.avg_network_total = peer.avg_network_tx + peer.avg_network_rx
|
||||||
@@ -74,6 +81,16 @@ let sort = (field: string) => {
|
|||||||
})
|
})
|
||||||
peers = peers
|
peers = peers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const decommission = (id: string) => {
|
||||||
|
loading_run(async () => {
|
||||||
|
try {
|
||||||
|
await admin_decommission_node(id)
|
||||||
|
} catch (err) {
|
||||||
|
alert(JSON.stringify(err))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="table_scroll">
|
<div class="table_scroll">
|
||||||
@@ -92,16 +109,17 @@ let sort = (field: string) => {
|
|||||||
<td><SortButton field="cache_threshold" active_field={sort_field} asc={asc} sort_func={sort}>CThresh</SortButton></td>
|
<td><SortButton field="cache_threshold" active_field={sort_field} asc={asc} sort_func={sort}>CThresh</SortButton></td>
|
||||||
<td><SortButton field="free_space" active_field={sort_field} asc={asc} sort_func={sort}>Free</SortButton></td>
|
<td><SortButton field="free_space" active_field={sort_field} asc={asc} sort_func={sort}>Free</SortButton></td>
|
||||||
<td><SortButton field="min_free_space" active_field={sort_field} asc={asc} sort_func={sort}>Min free</SortButton></td>
|
<td><SortButton field="min_free_space" active_field={sort_field} asc={asc} sort_func={sort}>Min free</SortButton></td>
|
||||||
|
{#if !all_reachable}<td></td>{/if}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each peers as peer (peer.ip)}
|
{#each peers as peer (peer.id)}
|
||||||
<tr style="border: none;"
|
<tr style="border: none;"
|
||||||
class:highlight_red={!peer.reachable}
|
class:highlight_red={!peer.reachable}
|
||||||
class:highlight_yellow={peer.free_space < peer.min_free_space / 2}
|
class:highlight_yellow={peer.free_space < peer.min_free_space / 2}
|
||||||
class:highlight_blue={peer.free_space < peer.min_free_space}
|
class:highlight_blue={peer.free_space < peer.min_free_space}
|
||||||
class:highlight_green={peer.reachable}
|
class:highlight_green={peer.reachable}
|
||||||
animate:flip={{duration: 1000}}
|
animate:flip={{duration: 500}}
|
||||||
>
|
>
|
||||||
<td>{peer.hostname}</td>
|
<td>{peer.hostname}</td>
|
||||||
<td>{peer.unreachable_count}</td>
|
<td>{peer.unreachable_count}</td>
|
||||||
@@ -115,6 +133,13 @@ let sort = (field: string) => {
|
|||||||
<td>{formatDataVolume(peer.cache_threshold, 3)}</td>
|
<td>{formatDataVolume(peer.cache_threshold, 3)}</td>
|
||||||
<td>{formatDataVolume(peer.free_space, 3)}</td>
|
<td>{formatDataVolume(peer.free_space, 3)}</td>
|
||||||
<td>{formatDataVolume(peer.min_free_space, 3)}</td>
|
<td>{formatDataVolume(peer.min_free_space, 3)}</td>
|
||||||
|
{#if !all_reachable}
|
||||||
|
<td>
|
||||||
|
<button class="button flat delete" onclick={() => decommission(peer.id)}>
|
||||||
|
<i class="icon small">delete</i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
@@ -135,6 +160,7 @@ let sort = (field: string) => {
|
|||||||
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.cache_threshold, 0), 4)}</td>
|
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.cache_threshold, 0), 4)}</td>
|
||||||
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.free_space, 0), 4)}</td>
|
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.free_space, 0), 4)}</td>
|
||||||
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.min_free_space, 0), 3)}</td>
|
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.min_free_space, 0), 3)}</td>
|
||||||
|
{#if !all_reachable}<td></td>{/if}
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Average</td>
|
<td>Average</td>
|
||||||
@@ -153,6 +179,7 @@ let sort = (field: string) => {
|
|||||||
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.cache_threshold, 0) / peers.length, 4)}</td>
|
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.cache_threshold, 0) / peers.length, 4)}</td>
|
||||||
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.free_space, 0) / peers.length, 4)}</td>
|
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.free_space, 0) / peers.length, 4)}</td>
|
||||||
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.min_free_space, 0) / peers.length, 3)}</td>
|
<td>{formatDataVolume(peers.reduce((acc, val) => acc += val.min_free_space, 0) / peers.length, 3)}</td>
|
||||||
|
{#if !all_reachable}<td></td>{/if}
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -167,4 +194,7 @@ let sort = (field: string) => {
|
|||||||
tr {
|
tr {
|
||||||
text-align: initial;
|
text-align: initial;
|
||||||
}
|
}
|
||||||
|
.delete {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { countries } from "country-data-list"
|
import { countries } from "country-data-list"
|
||||||
import { check_response, get_endpoint } from "./NovaAPI"
|
import { check_response, get_endpoint, type GenericResponse } from "./NovaAPI"
|
||||||
|
|
||||||
export const country_name = (country: string) => {
|
export const country_name = (country: string) => {
|
||||||
if (country !== "" && countries[country] !== undefined) {
|
if (country !== "" && countries[country] !== undefined) {
|
||||||
@@ -27,3 +27,15 @@ export const get_admin_invoices = async (year: number, month: number) => {
|
|||||||
)
|
)
|
||||||
) as Invoice[]
|
) as Invoice[]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const admin_decommission_node = async (peer_id: string) => {
|
||||||
|
let form = new FormData()
|
||||||
|
form.set("peer_id", peer_id)
|
||||||
|
|
||||||
|
return await check_response(
|
||||||
|
await fetch(
|
||||||
|
get_endpoint() + "/admin/decommission_node",
|
||||||
|
{ method: "POST", body: form }
|
||||||
|
)
|
||||||
|
) as GenericResponse
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user