Create auto refresh action as a component

This commit is contained in:
Cristian Ditaputratama 2024-05-08 00:38:10 +07:00
parent cda024ca6f
commit bc90c8bf3c
Signed by: ditatompel
GPG key ID: 31D3D06D77950979
7 changed files with 218 additions and 230 deletions

126
2 Normal file
View file

@ -0,0 +1,126 @@
<script>
import { DataHandler } from '@vincjo/datatables/remote';
import { format, formatDistance } from 'date-fns';
import { loadData } from './api-handler';
import { onMount } from 'svelte';
import {
DtSrThSort,
DtSrThFilter,
DtSrRowCount,
DtSrAutoRefresh
} from '$lib/components/datatables/server';
const handler = new DataHandler([], { rowsPerPage: 1000, totalRows: 0 });
let rows = handler.getRows();
/** @type {string | number} */
let filterState = -1;
/** @type {string | number} */
let filterEnabled = -1;
onMount(() => {
handler.onChange((state) => loadData(state));
handler.invalidate();
});
</script>
<div class="mb-4">
<h1 class="h2 font-extrabold dark:text-white">Crons</h1>
</div>
<div class="dashboard-card">
<div class="flex justify-between">
<div class="invisible flex place-items-center md:visible">
<DtSrAutoRefresh {handler} />
</div>
<div class="flex place-items-center">
<button
id="reloadDt"
name="reloadDt"
class="variant-filled-primary btn"
on:click={() => handler.invalidate()}
>
>Reload</button
>
</div>
</div>
<div class="my-2 overflow-x-auto">
<table class="table table-hover table-compact w-full table-auto">
<thead>
<tr>
<DtSrThSort {handler} orderBy="id">ID</DtSrThSort>
<th>Title</th>
<th>Slug</th>
<th>Description</th>
<DtSrThSort {handler} orderBy="run_every">Run Every</DtSrThSort>
<DtSrThSort {handler} orderBy="last_run">Last Run</DtSrThSort>
<DtSrThSort {handler} orderBy="next_run">Next Run</DtSrThSort>
<DtSrThSort {handler} orderBy="run_time">Run Time</DtSrThSort>
<th>State</th>
<th>Enabled</th>
</tr>
<tr>
<DtSrThFilter {handler} filterBy="title" placeholder="Title" colspan={3} />
<DtSrThFilter {handler} filterBy="description" placeholder="Description" colspan={5} />
<th>
<select
id="fState"
name="fState"
class="select variant-form-material"
bind:value={filterState}
on:change={() => {
handler.filter(filterState, 'cron_state');
}}
>
<option value={-1}>Any</option>
<option value={1}>Running</option>
<option value={0}>Idle</option>
</select>
</th>
<th>
<select
id="fEnabled"
name="fEnabled"
class="select variant-form-material"
bind:value={filterEnabled}
on:change={() => {
handler.filter(filterEnabled, 'is_enabled');
}}
>
<option value={-1}>Any</option>
<option value={1}>Yes</option>
<option value={0}>No</option>
</select>
</th>
</tr>
</thead>
<tbody>
{#each $rows as row (row.id)}
<tr>
<td>{row.id}</td>
<td>{row.title}</td>
<td>{row.slug}</td>
<td>{row.description}</td>
<td>{row.run_every}s</td>
<td>
{format(row.last_run * 1000, 'PP HH:mm')}<br />
{formatDistance(row.last_run * 1000, new Date(), { addSuffix: true })}
</td>
<td>
{format(row.next_run * 1000, 'PP HH:mm')}<br />
{formatDistance(row.next_run * 1000, new Date(), { addSuffix: true })}
</td>
<td>{row.run_time}</td>
<td>{row.cron_state ? 'RUNNING' : 'IDLE'}</td>
<td>{row.is_enabled ? 'ENABLED' : 'DISABLED'}</td>
</tr>
{/each}
</tbody>
</table>
</div>
<div class="flex justify-between mb-2">
<DtSrRowCount {handler} />
</div>
</div>

View file

@ -0,0 +1,58 @@
<script lang="ts">
import { onDestroy } from 'svelte';
import type { DataHandler, Row } from '@vincjo/datatables/remote';
type T = $$Generic<Row>;
export let handler: DataHandler<T>;
let intervalId: number | undefined;
let intervalValue = 0;
const intervalOptions = [
{ value: 0, label: 'No' },
{ value: 5, label: '5s' },
{ value: 10, label: '10s' },
{ value: 30, label: '30s' },
{ value: 60, label: '1m' }
];
const startInterval = () => {
const seconds = intervalValue;
if (isNaN(seconds) || seconds < 0) {
return;
}
if (!intervalOptions.some((option) => option.value === seconds)) {
return;
}
if (intervalId) {
clearInterval(intervalId);
}
if (seconds > 0) {
handler.invalidate();
intervalId = setInterval(() => {
handler.invalidate();
}, seconds * 1000);
}
};
$: startInterval();
onDestroy(() => {
clearInterval(intervalId);
});
</script>
<label for="autoRefreshInterval">Auto Refresh:</label>
<select
class="select ml-2"
id="autoRefreshInterval"
bind:value={intervalValue}
on:change={startInterval}
>
{#each intervalOptions as { value, label }}
<option {value}>{label}</option>
{/each}
</select>

View file

@ -4,3 +4,4 @@ export { default as DtSrRowsPerPage } from './DtSrRowsPerPage.svelte';
export { default as DtSrSearch } from './DtSrSearch.svelte'; export { default as DtSrSearch } from './DtSrSearch.svelte';
export { default as DtSrThFilter } from './DtSrThFilter.svelte'; export { default as DtSrThFilter } from './DtSrThFilter.svelte';
export { default as DtSrThSort } from './DtSrThSort.svelte'; export { default as DtSrThSort } from './DtSrThSort.svelte';
export { default as DtSrAutoRefresh } from './DtSrAutoRefresh.svelte';

View file

@ -2,13 +2,14 @@
import { DataHandler } from '@vincjo/datatables/remote'; import { DataHandler } from '@vincjo/datatables/remote';
import { format, formatDistance } from 'date-fns'; import { format, formatDistance } from 'date-fns';
import { loadData, loadCountries } from './api-handler'; import { loadData, loadCountries } from './api-handler';
import { onMount, onDestroy } from 'svelte'; import { onMount } from 'svelte';
import { import {
DtSrRowsPerPage, DtSrRowsPerPage,
DtSrThSort, DtSrThSort,
DtSrThFilter, DtSrThFilter,
DtSrRowCount, DtSrRowCount,
DtSrPagination DtSrPagination,
DtSrAutoRefresh
} from '$lib/components/datatables/server'; } from '$lib/components/datatables/server';
import { import {
HostPortCell, HostPortCell,
@ -33,10 +34,6 @@
const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 }); const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 });
let rows = handler.getRows(); let rows = handler.getRows();
const reloadData = () => {
handler.invalidate();
};
/** /**
* Array containing network fees. * Array containing network fees.
* For now, I use static data to reduce the amount of API calls. * For now, I use static data to reduce the amount of API calls.
@ -72,45 +69,6 @@
{} {}
); );
/** @type {number | undefined} */
let intervalId;
let intervalValue = 0;
const intervalOptions = [
{ value: 0, label: 'No' },
{ value: 5, label: '5s' },
{ value: 10, label: '10s' },
{ value: 30, label: '30s' },
{ value: 60, label: '1m' }
];
const startInterval = () => {
const seconds = intervalValue;
if (isNaN(seconds) || seconds < 0) {
return;
}
if (!intervalOptions.some((option) => option.value === seconds)) {
return;
}
if (intervalId) {
clearInterval(intervalId);
}
if (seconds > 0) {
reloadData();
intervalId = setInterval(() => {
reloadData();
}, seconds * 1000);
}
};
$: startInterval(); // Automatically start the interval on change
onDestroy(() => {
clearInterval(intervalId); // Clear the interval when the component is destroyed
});
onMount(() => { onMount(() => {
loadCountries().then((data) => { loadCountries().then((data) => {
countries = data; countries = data;
@ -156,24 +114,14 @@
<div class="flex justify-between"> <div class="flex justify-between">
<DtSrRowsPerPage {handler} /> <DtSrRowsPerPage {handler} />
<div class="invisible flex place-items-center md:visible"> <div class="invisible flex place-items-center md:visible">
<label for="autoRefreshInterval">Auto Refresh:</label> <DtSrAutoRefresh {handler} />
<select
class="select ml-2"
id="autoRefreshInterval"
bind:value={intervalValue}
on:change={startInterval}
>
{#each intervalOptions as { value, label }}
<option {value}>{label}</option>
{/each}
</select>
</div> </div>
<div class="flex place-items-center"> <div class="flex place-items-center">
<button <button
id="reloadDt" id="reloadDt"
name="reloadDt" name="reloadDt"
class="variant-filled-primary btn" class="variant-filled-primary btn"
on:click={reloadData}>Reload</button on:click={() => handler.invalidate()}>Reload</button
> >
</div> </div>
</div> </div>

View file

@ -2,14 +2,15 @@
import { DataHandler } from '@vincjo/datatables/remote'; import { DataHandler } from '@vincjo/datatables/remote';
import { format, formatDistance } from 'date-fns'; import { format, formatDistance } from 'date-fns';
import { loadData, loadNodeInfo } from './api-handler'; import { loadData, loadNodeInfo } from './api-handler';
import { onMount, onDestroy } from 'svelte'; import { onMount } from 'svelte';
import { formatHashes, formatBytes } from '$lib/utils/strings'; import { formatHashes, formatBytes } from '$lib/utils/strings';
import { import {
DtSrRowsPerPage, DtSrRowsPerPage,
DtSrThSort, DtSrThSort,
DtSrThFilter, DtSrThFilter,
DtSrRowCount, DtSrRowCount,
DtSrPagination DtSrPagination,
DtSrAutoRefresh
} from '$lib/components/datatables/server'; } from '$lib/components/datatables/server';
/** @param {number | null } runtime */ /** @param {number | null } runtime */
@ -28,49 +29,6 @@
const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 }); const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 });
let rows = handler.getRows(); let rows = handler.getRows();
const reloadData = () => {
handler.invalidate();
};
/** @type {number | undefined} */
let intervalId;
let intervalValue = 0;
const intervalOptions = [
{ value: 0, label: 'No' },
{ value: 5, label: '5s' },
{ value: 10, label: '10s' },
{ value: 30, label: '30s' },
{ value: 60, label: '1m' }
];
const startInterval = () => {
const seconds = intervalValue;
if (isNaN(seconds) || seconds < 0) {
return;
}
if (!intervalOptions.some((option) => option.value === seconds)) {
return;
}
if (intervalId) {
clearInterval(intervalId);
}
if (seconds > 0) {
reloadData();
intervalId = setInterval(() => {
reloadData();
}, seconds * 1000);
}
};
$: startInterval();
onDestroy(() => {
clearInterval(intervalId);
});
onMount(() => { onMount(() => {
pageId = new URLSearchParams(window.location.search).get('node_id') || '0'; pageId = new URLSearchParams(window.location.search).get('node_id') || '0';
loadNodeInfo(pageId).then((data) => { loadNodeInfo(pageId).then((data) => {
@ -134,24 +92,14 @@
<div class="flex justify-between"> <div class="flex justify-between">
<DtSrRowsPerPage {handler} /> <DtSrRowsPerPage {handler} />
<div class="invisible flex place-items-center md:visible"> <div class="invisible flex place-items-center md:visible">
<label for="autoRefreshInterval">Auto Refresh:</label> <DtSrAutoRefresh {handler} />
<select
class="select ml-2"
id="autoRefreshInterval"
bind:value={intervalValue}
on:change={startInterval}
>
{#each intervalOptions as { value, label }}
<option {value}>{label}</option>
{/each}
</select>
</div> </div>
<div class="flex place-items-center"> <div class="flex place-items-center">
<button <button
id="reloadDt" id="reloadDt"
name="reloadDt" name="reloadDt"
class="variant-filled-primary btn" class="variant-filled-primary btn"
on:click={reloadData}>Reload</button on:click={() => handler.invalidate()}>Reload</button
> >
</div> </div>
</div> </div>

View file

@ -2,60 +2,22 @@
import { DataHandler } from '@vincjo/datatables/remote'; import { DataHandler } from '@vincjo/datatables/remote';
import { format, formatDistance } from 'date-fns'; import { format, formatDistance } from 'date-fns';
import { loadData } from './api-handler'; import { loadData } from './api-handler';
import { onMount, onDestroy } from 'svelte'; import { onMount } from 'svelte';
import { DtSrThSort, DtSrThFilter, DtSrRowCount } from '$lib/components/datatables/server'; import {
DtSrThSort,
DtSrThFilter,
DtSrRowCount,
DtSrAutoRefresh
} from '$lib/components/datatables/server';
const handler = new DataHandler([], { rowsPerPage: 1000, totalRows: 0 }); const handler = new DataHandler([], { rowsPerPage: 1000, totalRows: 0 });
let rows = handler.getRows(); let rows = handler.getRows();
const reloadData = () => {
handler.invalidate();
};
/** @type {string | number} */ /** @type {string | number} */
let filterState = -1; let filterState = -1;
/** @type {string | number} */ /** @type {string | number} */
let filterEnabled = -1; let filterEnabled = -1;
/** @type {number | undefined} */
let intervalId;
let intervalValue = 0;
const intervalOptions = [
{ value: 0, label: 'No' },
{ value: 5, label: '5s' },
{ value: 10, label: '10s' },
{ value: 30, label: '30s' },
{ value: 60, label: '1m' }
];
const startInterval = () => {
const seconds = intervalValue;
if (isNaN(seconds) || seconds < 0) {
return;
}
if (!intervalOptions.some((option) => option.value === seconds)) {
return;
}
if (intervalId) {
clearInterval(intervalId);
}
if (seconds > 0) {
reloadData();
intervalId = setInterval(() => {
reloadData();
}, seconds * 1000);
}
};
$: startInterval(); // Automatically start the interval on change
onDestroy(() => {
clearInterval(intervalId); // Clear the interval when the component is destroyed
});
onMount(() => { onMount(() => {
handler.onChange((state) => loadData(state)); handler.onChange((state) => loadData(state));
handler.invalidate(); handler.invalidate();
@ -69,24 +31,16 @@
<div class="dashboard-card"> <div class="dashboard-card">
<div class="flex justify-between"> <div class="flex justify-between">
<div class="invisible flex place-items-center md:visible"> <div class="invisible flex place-items-center md:visible">
<label for="autoRefreshInterval">Auto Refresh:</label> <DtSrAutoRefresh {handler} />
<select
class="select ml-2"
id="autoRefreshInterval"
bind:value={intervalValue}
on:change={startInterval}
>
{#each intervalOptions as { value, label }}
<option {value}>{label}</option>
{/each}
</select>
</div> </div>
<div class="flex place-items-center"> <div class="flex place-items-center">
<button <button
id="reloadDt" id="reloadDt"
name="reloadDt" name="reloadDt"
class="variant-filled-primary btn" class="variant-filled-primary btn"
on:click={reloadData}>Reload</button on:click={() => handler.invalidate()}
>
>Reload</button
> >
</div> </div>
</div> </div>
@ -117,7 +71,7 @@
bind:value={filterState} bind:value={filterState}
on:change={() => { on:change={() => {
handler.filter(filterState, 'cron_state'); handler.filter(filterState, 'cron_state');
reloadData(); handler.invalidate();
}} }}
> >
<option value={-1}>Any</option> <option value={-1}>Any</option>
@ -133,7 +87,7 @@
bind:value={filterEnabled} bind:value={filterEnabled}
on:change={() => { on:change={() => {
handler.filter(filterEnabled, 'is_enabled'); handler.filter(filterEnabled, 'is_enabled');
reloadData(); handler.invalidate();
}} }}
> >
<option value={-1}>Any</option> <option value={-1}>Any</option>

View file

@ -2,14 +2,15 @@
import { DataHandler } from '@vincjo/datatables/remote'; import { DataHandler } from '@vincjo/datatables/remote';
import { format, formatDistance } from 'date-fns'; import { format, formatDistance } from 'date-fns';
import { loadData, createProber, editProber, deleteProber } from './api-handler'; import { loadData, createProber, editProber, deleteProber } from './api-handler';
import { onMount, onDestroy } from 'svelte'; import { onMount } from 'svelte';
import { getModalStore, getToastStore } from '@skeletonlabs/skeleton'; import { getModalStore, getToastStore } from '@skeletonlabs/skeleton';
import { import {
DtSrRowsPerPage, DtSrRowsPerPage,
DtSrThSort, DtSrThSort,
DtSrThFilter, DtSrThFilter,
DtSrRowCount, DtSrRowCount,
DtSrPagination DtSrPagination,
DtSrAutoRefresh
} from '$lib/components/datatables/server'; } from '$lib/components/datatables/server';
const modalStore = getModalStore(); const modalStore = getModalStore();
const toastStore = getToastStore(); const toastStore = getToastStore();
@ -111,49 +112,6 @@
const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 }); const handler = new DataHandler([], { rowsPerPage: 10, totalRows: 0 });
let rows = handler.getRows(); let rows = handler.getRows();
const reloadData = () => {
handler.invalidate();
};
/** @type {number | undefined} */
let intervalId;
let intervalValue = 0;
const intervalOptions = [
{ value: 0, label: 'No' },
{ value: 5, label: '5s' },
{ value: 10, label: '10s' },
{ value: 30, label: '30s' },
{ value: 60, label: '1m' }
];
const startInterval = () => {
const seconds = intervalValue;
if (isNaN(seconds) || seconds < 0) {
return;
}
if (!intervalOptions.some((option) => option.value === seconds)) {
return;
}
if (intervalId) {
clearInterval(intervalId);
}
if (seconds > 0) {
reloadData();
intervalId = setInterval(() => {
reloadData();
}, seconds * 1000);
}
};
$: startInterval(); // Automatically start the interval on change
onDestroy(() => {
clearInterval(intervalId); // Clear the interval when the component is destroyed
});
onMount(() => { onMount(() => {
handler.onChange((state) => loadData(state)); handler.onChange((state) => loadData(state));
handler.invalidate(); handler.invalidate();
@ -169,20 +127,15 @@
<div class="flex justify-between"> <div class="flex justify-between">
<DtSrRowsPerPage {handler} /> <DtSrRowsPerPage {handler} />
<div class="invisible flex place-items-center md:visible"> <div class="invisible flex place-items-center md:visible">
<label for="autoRefreshInterval">Auto Refresh:</label> <DtSrAutoRefresh {handler} />
<select
class="select ml-2"
id="autoRefreshInterval"
bind:value={intervalValue}
on:change={startInterval}
>
{#each intervalOptions as { value, label }}
<option {value}>{label}</option>
{/each}
</select>
</div> </div>
<div class="flex place-items-center"> <div class="flex place-items-center">
<button id="reloadDt" name="reloadDt" class="variant-filled-primary btn" on:click={reloadData} <button
id="reloadDt"
name="reloadDt"
class="variant-filled-primary btn"
on:click={() => handler.invalidate()}
>
>Reload</button >Reload</button
> >
</div> </div>