pre-refactor
This commit is contained in:
@@ -57,29 +57,36 @@ async function pollCertIssue(rid, state) {
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (state.certs?.length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const r = await apiFetch('/api/certs/list');
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const r = await apiFetch('/api/certs/list', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (r.ok) state.certs = r.data || [];
|
||||
else state.error = r.error;
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { certs: [], loading: true, error: null };
|
||||
return { certs: [], loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['acme'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'Certificates' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -2,25 +2,31 @@ import { h, PageHeader, Badge, StatusDot, Empty, Card, esc, enc, att_esc, $val,
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { data: null, loading: true, error: null };
|
||||
return { data: null, loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['*'],
|
||||
async load(state) {
|
||||
async load(state, abortController, entry) {
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
if (state.data) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const res = await apiFetch('/api/status/all');
|
||||
const res = await apiFetch('/api/status/all', { signal: abortController?.signal });
|
||||
if (abortController?.signal.aborted || entry.requestId !== myId) return;
|
||||
if (res.ok) state.data = res.data;
|
||||
else state.error = res.error;
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
},
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'Dashboard', subtitle: 'System overview' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -120,32 +120,41 @@ function addDnsModal(state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (Object.keys(state.config || {}).length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const cfgR = await apiFetch('/api/dhcp/config');
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const cfgR = await apiFetch('/api/dhcp/config', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (cfgR.ok) state.config = cfgR.data || {};
|
||||
const stR = await apiFetch('/api/dhcp/status');
|
||||
const stR = await apiFetch('/api/dhcp/status', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (stR.ok) state.status = stR.data || {};
|
||||
const lsR = await apiFetch('/api/dhcp/leases');
|
||||
const lsR = await apiFetch('/api/dhcp/leases', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (lsR.ok) state.leases = lsR.data || [];
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { config: {}, status: {}, leases: [], loading: true, error: null, activeTab: 'ranges' };
|
||||
return { config: {}, status: {}, leases: [], loading: true, refreshing: false, error: null, activeTab: 'ranges' };
|
||||
},
|
||||
subscribe: ['dnsmasq'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'DHCP & DNS' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -50,12 +50,17 @@ function cfgModal(name, state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (state.ifaces?.length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const [fw, net] = await Promise.all([
|
||||
apiFetch('/api/firewall/zones'),
|
||||
apiFetch('/api/network/interfaces'),
|
||||
apiFetch('/api/firewall/zones', { signal: sig }),
|
||||
apiFetch('/api/network/interfaces', { signal: sig }),
|
||||
]);
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
// Extract zone names from available zones (for the dropdown)
|
||||
state.zones = fw.ok ? (fw.data?.available || []) : [];
|
||||
if (net.ok) {
|
||||
@@ -78,23 +83,25 @@ async function load(state) {
|
||||
state.error = net.error;
|
||||
}
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { ifaces: [], zones: [], loading: true, error: null };
|
||||
return { ifaces: [], zones: [], loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['firewall', 'networkd'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'Interfaces' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -9,27 +9,35 @@ const logTabs = [
|
||||
];
|
||||
|
||||
|
||||
async function fetchLog(state, url) {
|
||||
async function fetchLog(state, url, signal) {
|
||||
state.loading = true;
|
||||
state.error = null;
|
||||
try {
|
||||
const res = await fetch(url);
|
||||
const res = await fetch(url, { signal });
|
||||
if (signal?.aborted) return;
|
||||
const text = await res.text();
|
||||
if (signal?.aborted) return;
|
||||
state.lines = text.split('\n').filter(l => l.length > 0);
|
||||
} catch (e) {
|
||||
if (signal?.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { activeTab: 'journal', lines: [], loading: false, error: null };
|
||||
return { activeTab: 'journal', lines: [], loading: false, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: [],
|
||||
async load(state) {
|
||||
async load(state, abortController, entry) {
|
||||
if (state.lines?.length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const tab = logTabs.find(t => t.key === state.activeTab) || logTabs[0];
|
||||
await fetchLog(state, tab.url);
|
||||
await fetchLog(state, tab.url, abortController?.signal);
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
},
|
||||
onUnmount(state) {
|
||||
state.lines = [];
|
||||
@@ -65,8 +73,8 @@ export default definePage({
|
||||
}, '\u21BB')
|
||||
),
|
||||
h('div', { class: 'card-body log-body' },
|
||||
state.loading
|
||||
? h('div', { class: 'loading' }, 'Loading...')
|
||||
state.loading && !state.refreshing
|
||||
? h('div', { class: 'loading' }, state.refreshing ? 'Refreshing...' : 'Loading...')
|
||||
: state.error
|
||||
? h('div', { class: 'error-msg' }, state.error)
|
||||
: lineVnodes.length > 0
|
||||
|
||||
@@ -44,30 +44,38 @@ function addFwdModal(zones, state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (Object.keys(state.config || {}).length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const r = await apiFetch('/api/firewall/config');
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const r = await apiFetch('/api/firewall/config', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (r.ok) state.config = r.data || {};
|
||||
const zr = await apiFetch('/api/firewall/zones');
|
||||
const zr = await apiFetch('/api/firewall/zones', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (zr.ok) state.activeZones = Object.keys(zr.data?.active || {});
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { config: {}, activeZones: [], loading: true, error: null };
|
||||
return { config: {}, activeZones: [], loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['firewall'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'NAT', subtitle: 'Masquerade & port forwarding' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -82,30 +82,38 @@ function editDomainModal(domain, state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (state.domains?.length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const domainsR = await apiFetch('/api/proxy/domains');
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const domainsR = await apiFetch('/api/proxy/domains', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (domainsR.ok) state.domains = domainsR.data || [];
|
||||
const certsR = await apiFetch('/api/certs/list');
|
||||
const certsR = await apiFetch('/api/certs/list', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (certsR.ok) state.certs = certsR.data || [];
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { domains: [], certs: [], loading: true, error: null };
|
||||
return { domains: [], certs: [], loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['nginx', 'acme'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'Proxy' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -33,31 +33,39 @@ function addRuleModal(zones, state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (Object.keys(state.config || {}).length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const r = await apiFetch('/api/firewall/config');
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const r = await apiFetch('/api/firewall/config', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (r.ok) state.config = r.data || {};
|
||||
else state.error = r.error;
|
||||
const zr = await apiFetch('/api/firewall/zones');
|
||||
const zr = await apiFetch('/api/firewall/zones', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (zr.ok) state.zones = Object.keys(zr.data?.active || {});
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { config: {}, loading: true, error: null, zones: [] };
|
||||
return { config: {}, loading: true, refreshing: false, error: null, zones: [] };
|
||||
},
|
||||
subscribe: ['firewall'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'Rules', subtitle: 'Firewall rich rules' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -76,32 +76,41 @@ function downloadConfigModal(peerName, config, state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (state.peers?.length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const stR = await apiFetch('/api/wireguard/status');
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const stR = await apiFetch('/api/wireguard/status', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (stR.ok) state.status = stR.data || {};
|
||||
const pR = await apiFetch('/api/wireguard/peers');
|
||||
const pR = await apiFetch('/api/wireguard/peers', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (pR.ok) state.peers = pR.data || [];
|
||||
const cfgR = await apiFetch('/api/wireguard/config');
|
||||
const cfgR = await apiFetch('/api/wireguard/config', { signal: sig });
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
if (cfgR.ok) state.config = cfgR.data || {};
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { status: {}, peers: [], config: {}, loading: true, error: null };
|
||||
return { status: {}, peers: [], config: {}, loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['wireguard'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'WireGuard' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -107,24 +107,32 @@ function zoneSvcModal(zoneName, state) {
|
||||
});
|
||||
}
|
||||
|
||||
async function load(state) {
|
||||
async function load(state, abortController, entry) {
|
||||
if (Object.keys(state.zones || {}).length) state.refreshing = true;
|
||||
else state.loading = true;
|
||||
try {
|
||||
const myId = entry ? entry.requestId : 0;
|
||||
const sig = abortController?.signal;
|
||||
const [zRes, svcRes, ifRes] = await Promise.all([
|
||||
apiFetch('/api/firewall/zones'),
|
||||
apiFetch('/api/firewall/services'),
|
||||
apiFetch('/api/firewall/interfaces'),
|
||||
apiFetch('/api/firewall/zones', { signal: sig }),
|
||||
apiFetch('/api/firewall/services', { signal: sig }),
|
||||
apiFetch('/api/firewall/interfaces', { signal: sig }),
|
||||
]);
|
||||
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
|
||||
if (zRes.ok) {
|
||||
const data = zRes.data || {};
|
||||
const activeZones = data.active || {};
|
||||
const availableZones = data.available || [];
|
||||
|
||||
const detailPromises = availableZones.map(name =>
|
||||
apiFetch('/api/firewall/zones/' + enc(name)).catch(() => null)
|
||||
apiFetch('/api/firewall/zones/' + enc(name), { signal: sig }).catch(() => null)
|
||||
);
|
||||
const detailResults = await Promise.all(detailPromises);
|
||||
|
||||
if (abortController?.signal.aborted || (entry && entry.requestId !== myId)) return;
|
||||
|
||||
const zones = {};
|
||||
for (let i = 0; i < availableZones.length; i++) {
|
||||
const name = availableZones[i];
|
||||
@@ -143,23 +151,25 @@ async function load(state) {
|
||||
if (svcRes.ok) state.services = svcRes.data || [];
|
||||
if (ifRes.ok) state.interfaces = ifRes.data || [];
|
||||
} catch (e) {
|
||||
if (abortController?.signal.aborted) return;
|
||||
state.error = String(e);
|
||||
}
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
|
||||
export default definePage({
|
||||
init() {
|
||||
return { zones: {}, services: [], interfaces: [], loading: true, error: null };
|
||||
return { zones: {}, services: [], interfaces: [], loading: true, refreshing: false, error: null };
|
||||
},
|
||||
subscribe: ['firewall'],
|
||||
load,
|
||||
render(state) {
|
||||
if (state.loading) {
|
||||
if (state.loading && !state.refreshing) {
|
||||
return [
|
||||
PageHeader({ title: 'Zones', subtitle: 'Firewall zone management' }),
|
||||
h('div', { class: 'card', key: 'loading' },
|
||||
h('div', { class: 'card-body loading' }, 'Loading...'),
|
||||
h('div', { class: 'card-body loading' }, state.refreshing ? 'Refreshing...' : 'Loading...'),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user