mirror of
https://github.com/ditatompel/xmr-remote-nodes.git
synced 2024-11-16 17:07:36 +00:00
Use modal window for add prober form
The previous add prober is using new page to show add prober form. In this commit, the add prober form is using modal so it can be more simpler.
This commit is contained in:
parent
50588da322
commit
cda024ca6f
4 changed files with 52 additions and 102 deletions
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { DataHandler } from '@vincjo/datatables/remote';
|
||||
import { format, formatDistance } from 'date-fns';
|
||||
import { loadData, deleteData, editProber } from './api-handler';
|
||||
import { loadData, createProber, editProber, deleteProber } from './api-handler';
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { getModalStore, getToastStore } from '@skeletonlabs/skeleton';
|
||||
import {
|
||||
|
@ -14,6 +14,36 @@
|
|||
const modalStore = getModalStore();
|
||||
const toastStore = getToastStore();
|
||||
|
||||
function showAddModal() {
|
||||
/** @type {import('@skeletonlabs/skeleton').ModalSettings} */
|
||||
const modal = {
|
||||
type: 'prompt',
|
||||
// Data
|
||||
title: 'Enter Name',
|
||||
body: 'Enter a name for the prober',
|
||||
valueAttr: { type: 'text', minlength: 3, maxlength: 50, required: true },
|
||||
response: (r) => {
|
||||
if (!r) return;
|
||||
createProber(r)
|
||||
.then((res) => {
|
||||
if (res.status !== 'ok') {
|
||||
toastStore.trigger({ message: 'Failed to create prober' });
|
||||
} else {
|
||||
toastStore.trigger({
|
||||
message: 'Prober created',
|
||||
background: 'variant-filled-success'
|
||||
});
|
||||
handler.invalidate();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
toastStore.trigger({ message: 'Failed to create prober' });
|
||||
});
|
||||
}
|
||||
};
|
||||
modalStore.trigger(modal);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} proberId
|
||||
* @param {string} proberName
|
||||
|
@ -28,6 +58,7 @@
|
|||
value: proberName,
|
||||
valueAttr: { type: 'text', minlength: 3, maxlength: 50, required: true },
|
||||
response: (r) => {
|
||||
if (!r) return;
|
||||
editProber(proberId, r)
|
||||
.then((res) => {
|
||||
if (res.status !== 'ok') {
|
||||
|
@ -57,7 +88,7 @@
|
|||
/** @param {boolean} r */
|
||||
response: async (r) => {
|
||||
if (r) {
|
||||
deleteData(id)
|
||||
deleteProber(id)
|
||||
.then((res) => {
|
||||
if (res.status !== 'ok') {
|
||||
toastStore.trigger({ message: 'Failed to delete prober' });
|
||||
|
@ -134,7 +165,7 @@
|
|||
</div>
|
||||
|
||||
<div class="dashboard-card">
|
||||
<a class="variant-filled-success btn btn-sm mb-4" href="/app/prober/add">Add Prober</a>
|
||||
<button class="variant-filled-success btn btn-sm mb-4" on:click={showAddModal}>Add Prober</button>
|
||||
<div class="flex justify-between">
|
||||
<DtSrRowsPerPage {handler} />
|
||||
<div class="invisible flex place-items-center md:visible">
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
<script>
|
||||
import { invalidateAll, goto } from '$app/navigation';
|
||||
import { apiUri } from '$lib/utils/common';
|
||||
import { ProgressBar } from '@skeletonlabs/skeleton';
|
||||
|
||||
/**
|
||||
* @typedef formResult
|
||||
* @type {object}
|
||||
* @property {string} status
|
||||
* @property {string} message
|
||||
* @property {null | object} data
|
||||
*/
|
||||
/** @type {formResult} */
|
||||
export let formResult;
|
||||
|
||||
let isProcessing = false;
|
||||
|
||||
/** @param {{ currentTarget: EventTarget & HTMLFormElement}} event */
|
||||
async function handleSubmit(event) {
|
||||
isProcessing = true;
|
||||
const data = new FormData(event.currentTarget);
|
||||
|
||||
const response = await fetch(event.currentTarget.action, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json'
|
||||
},
|
||||
body: JSON.stringify(Object.fromEntries(data))
|
||||
});
|
||||
|
||||
formResult = await response.json();
|
||||
isProcessing = false;
|
||||
|
||||
if (formResult.status === 'ok') {
|
||||
// rerun all `load` functions, following the successful update
|
||||
await invalidateAll();
|
||||
goto('/app/prober/');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mb-4">
|
||||
<h1 class="h2 font-extrabold dark:text-white">Add Prober</h1>
|
||||
</div>
|
||||
{#if !isProcessing}
|
||||
{#if formResult?.status === 'error'}
|
||||
<div class="p-4 mb-4 text-sm rounded-lg bg-gray-700 text-red-400" role="alert">
|
||||
<span class="font-medium">Error:</span>
|
||||
{formResult.message}!
|
||||
</div>
|
||||
{/if}
|
||||
{#if formResult?.status === 'ok'}
|
||||
<div class="p-4 mb-4 text-sm rounded-lg bg-gray-700 text-green-400" role="alert">
|
||||
<span class="font-medium">Success:</span>
|
||||
{formResult.message}!
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<ProgressBar meter="bg-secondary-500" track="bg-secondary-500/30" value={undefined} />
|
||||
<div class="mx-4 p-4 mb-4 text-sm rounded-lg bg-gray-700 text-blue-400" role="alert">
|
||||
<span class="font-medium">Processing...</span>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="dashboard-card">
|
||||
<form
|
||||
class="space-y-4 md:space-y-6"
|
||||
action={apiUri('/api/v1/prober')}
|
||||
method="POST"
|
||||
on:submit|preventDefault={handleSubmit}
|
||||
>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<label for="name" class="label">
|
||||
<span>Name</span>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
id="name"
|
||||
placeholder="Prober name"
|
||||
autocomplete="off"
|
||||
class="input variant-form-material"
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full rounded-lg bg-primary-600 px-5 py-2.5 text-center text-sm font-medium hover:bg-primary-700"
|
||||
>Submit</button
|
||||
>
|
||||
</form>
|
||||
</div>
|
|
@ -8,10 +8,14 @@ export const loadData = async (state) => {
|
|||
return json.data.items ?? [];
|
||||
};
|
||||
|
||||
export const deleteData = async (id) => {
|
||||
const response = await fetch(apiUri(`/api/v1/prober/${id}`), {
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
export const createProber = async (name) => {
|
||||
const response = await fetch(apiUri('/api/v1/prober'), {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ name })
|
||||
});
|
||||
const json = await response.json();
|
||||
return json;
|
||||
|
@ -30,6 +34,15 @@ export const editProber = async (id, name) => {
|
|||
return json;
|
||||
};
|
||||
|
||||
export const deleteProber = async (id) => {
|
||||
const response = await fetch(apiUri(`/api/v1/prober/${id}`), {
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
});
|
||||
const json = await response.json();
|
||||
return json;
|
||||
};
|
||||
|
||||
const getParams = ({ pageNumber, rowsPerPage, sort, filters }) => {
|
||||
let params = `page=${pageNumber}&limit=${rowsPerPage}`;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ func V1Api(app *fiber.App) {
|
|||
v1 := app.Group("/api/v1")
|
||||
|
||||
v1.Get("/prober", Prober)
|
||||
v1.Post("/prober", Prober)
|
||||
v1.Post("/prober", CookieProtected, Prober)
|
||||
v1.Patch("/prober/:id", CookieProtected, Prober)
|
||||
v1.Delete("/prober/:id", CookieProtected, Prober)
|
||||
v1.Get("/nodes", MoneroNodes)
|
||||
|
|
Loading…
Reference in a new issue