mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-04 04:13:56 +08:00
💋 Sync 2026-10-04 04:16:09
This commit is contained in:
1 parent
f6b2df73ec
commit
f62992fd80
745 files changed
+212416
-1173
No files matched your search
@@ -0,0 +1,241 @@
|
||||
.fluent-dashboard {
|
||||
--fluent-dashboard-border: var(--fluent-card-border, var(--inputborder-color, color-mix(in srgb, currentColor 16%, transparent)));
|
||||
--fluent-dashboard-muted: var(--fluent-text-secondary, color-mix(in srgb, currentColor 68%, transparent));
|
||||
--fluent-dashboard-surface: var(--fluent-card-bg, rgba(var(--primary-rgbbody, 255, 255, 255), 0.7));
|
||||
--fluent-dashboard-shadow: var(--fluent-card-shadow, 0 .1rem .3rem var(--input-boxcolor, color-mix(in srgb, CanvasText 8%, transparent)));
|
||||
color: var(--fluent-text, CanvasText);
|
||||
container-type: inline-size;
|
||||
}
|
||||
|
||||
.fluent-dashboard, .fluent-dashboard * {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.fluent-dashboard__header {
|
||||
color: highlighttext;
|
||||
background: linear-gradient(120deg, Highlight, color-mix(in srgb, Highlight 68%, CanvasText));
|
||||
border-radius: .75rem;
|
||||
justify-content: space-between;
|
||||
align-items: end;
|
||||
gap: 1rem;
|
||||
margin-block-end: 1rem;
|
||||
padding: 1.25rem;
|
||||
display: flex;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fluent-dashboard__header h1, .fluent-dashboard__header p {
|
||||
color: inherit;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fluent-dashboard__header h1 {
|
||||
font-size: clamp(1.5rem, 4vw, 2.25rem);
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
.fluent-dashboard__header h1 + p {
|
||||
opacity: .82;
|
||||
margin-block-start: .4rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__updated {
|
||||
opacity: .86;
|
||||
flex: none;
|
||||
font-size: .85rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__grid {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 1rem;
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.fluent-dashboard__card {
|
||||
min-width: 0;
|
||||
color: inherit;
|
||||
background: var(--fluent-dashboard-surface);
|
||||
border: 1px solid var(--fluent-dashboard-border);
|
||||
box-shadow: var(--fluent-dashboard-shadow);
|
||||
border-radius: .75rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fluent-dashboard__card--wide {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
|
||||
.fluent-dashboard__card-title {
|
||||
color: inherit;
|
||||
border-block-end: 1px solid var(--fluent-dashboard-border);
|
||||
margin: 0;
|
||||
padding: 1rem 1.1rem .85rem 1.35rem;
|
||||
font-size: 1rem;
|
||||
font-weight: 650;
|
||||
line-height: 1.25;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fluent-dashboard__card-title:before {
|
||||
content: "";
|
||||
background: highlight;
|
||||
border-radius: 1rem;
|
||||
width: .2rem;
|
||||
position: absolute;
|
||||
inset: 1rem auto .85rem .7rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__card-content {
|
||||
padding: 1rem 1.1rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__details {
|
||||
grid-template-columns: minmax(8rem, 36%) minmax(0, 1fr);
|
||||
gap: .6rem 1rem;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.fluent-dashboard__details-label {
|
||||
color: var(--fluent-dashboard-muted);
|
||||
}
|
||||
|
||||
.fluent-dashboard__details-value {
|
||||
overflow-wrap: anywhere;
|
||||
min-width: 0;
|
||||
font-weight: 550;
|
||||
}
|
||||
|
||||
.fluent-dashboard__meter + .fluent-dashboard__meter {
|
||||
margin-block-start: 1.1rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__meter-label {
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
margin-block-end: .45rem;
|
||||
font-size: .85rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.fluent-dashboard__meter-label span:last-child {
|
||||
color: var(--fluent-dashboard-muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.fluent-dashboard__meter-track {
|
||||
background: color-mix(in srgb, currentColor 12%, transparent);
|
||||
border-radius: 1rem;
|
||||
height: .5rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fluent-dashboard__meter-value {
|
||||
border-radius: inherit;
|
||||
background: highlight;
|
||||
height: 100%;
|
||||
transition: width .2s;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.fluent-dashboard__table-wrap {
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.fluent-dashboard__table {
|
||||
width: 100%;
|
||||
color: inherit;
|
||||
border-collapse: collapse;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.fluent-dashboard__table th, .fluent-dashboard__table td {
|
||||
text-align: start;
|
||||
vertical-align: middle;
|
||||
border-block-end: 1px solid var(--fluent-dashboard-border);
|
||||
padding: .7rem .65rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__table th {
|
||||
color: var(--fluent-dashboard-muted);
|
||||
letter-spacing: .02em;
|
||||
text-transform: uppercase;
|
||||
font-size: .78rem;
|
||||
font-weight: 650;
|
||||
}
|
||||
|
||||
.fluent-dashboard__table tbody tr:last-child td {
|
||||
border-block-end: 0;
|
||||
}
|
||||
|
||||
.fluent-dashboard__status {
|
||||
white-space: nowrap;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
font-size: .82rem;
|
||||
font-weight: 600;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.fluent-dashboard__status:before {
|
||||
content: "";
|
||||
background: currentColor;
|
||||
border-radius: 50%;
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__status--up {
|
||||
color: color-mix(in srgb, LinkText 75%, Highlight);
|
||||
}
|
||||
|
||||
.fluent-dashboard__status--down {
|
||||
color: color-mix(in srgb, currentColor 58%, transparent);
|
||||
}
|
||||
|
||||
.fluent-dashboard__table .fluent-dashboard__empty {
|
||||
color: var(--fluent-dashboard-muted);
|
||||
text-align: center;
|
||||
padding-block: 1.5rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@container (width <= 44rem) {
|
||||
.fluent-dashboard__grid {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.fluent-dashboard__card--wide {
|
||||
grid-column: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 575px) {
|
||||
.fluent-dashboard__header {
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__details {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
gap: .2rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__details-value + .fluent-dashboard__details-label {
|
||||
margin-block-start: .45rem;
|
||||
}
|
||||
|
||||
.fluent-dashboard__card-content {
|
||||
padding: .85rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.fluent-dashboard__meter-value {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,654 @@
|
||||
"use strict";
|
||||
"require view";
|
||||
"require dom";
|
||||
"require poll";
|
||||
"require rpc";
|
||||
"require network";
|
||||
// WARN: generated by rsbuild - do not edit
|
||||
|
||||
// The require scope
|
||||
var __webpack_require__ = {};
|
||||
|
||||
// webpack/runtime/define_property_getters
|
||||
(() => {
|
||||
__webpack_require__.d = (exports, getters, values) => {
|
||||
var define = (defs, kind) => {
|
||||
for(var key in defs) {
|
||||
if(__webpack_require__.o(defs, key) && !__webpack_require__.o(exports, key)) {
|
||||
Object.defineProperty(exports, key, { enumerable: true, [kind]: defs[key] });
|
||||
}
|
||||
}
|
||||
};
|
||||
define(getters, "get");
|
||||
define(values, "value");
|
||||
};
|
||||
})();
|
||||
// webpack/runtime/has_own_property
|
||||
(() => {
|
||||
__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
|
||||
})();
|
||||
// webpack/runtime/make_namespace_object
|
||||
(() => {
|
||||
// define __esModule on exports
|
||||
__webpack_require__.r = (exports) => {
|
||||
if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
||||
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
||||
}
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
};
|
||||
})();
|
||||
var __webpack_exports__ = {};
|
||||
// ESM COMPAT FLAG
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
|
||||
// EXPORTS
|
||||
__webpack_require__.d(__webpack_exports__, {
|
||||
main: () => (/* binding */ main)
|
||||
});
|
||||
|
||||
;// CONCATENATED MODULE: ../node_modules/.pnpm/@lazulikao+luci-types@https_685a81b9ead15f36368ce6e6ebcf4a27/node_modules/@lazulikao/luci-types/src/jsx/jsx-factory.ts
|
||||
const Fragment = Symbol.for("jsx.fragment");
|
||||
function jsx_factory_e(e, t) {
|
||||
let { children: n, ...r } = null === t || "object" != typeof t || Array.isArray(t) ? {} : t, o = function e(t, n = []) {
|
||||
for (let r of t)null != r && "boolean" != typeof r && (Array.isArray(r) ? e(r, n) : n.push(r instanceof Node ? r : String(r)));
|
||||
return n;
|
||||
}(null == n ? [] : Array.isArray(n) ? n : [
|
||||
n
|
||||
]);
|
||||
if (e === Fragment) {
|
||||
let e = document.createDocumentFragment();
|
||||
return e.append(...o), e;
|
||||
}
|
||||
if ("function" == typeof e) {
|
||||
let t = Reflect.apply(e, void 0, [
|
||||
{
|
||||
...r,
|
||||
children: o
|
||||
}
|
||||
]);
|
||||
if (!(t instanceof Node)) throw TypeError("JSX components must return a DOM Node");
|
||||
return t;
|
||||
}
|
||||
if ("string" != typeof e) throw TypeError("JSX element types must be tag names or component functions");
|
||||
let f = {}, l = {
|
||||
...r
|
||||
};
|
||||
for (let [e, t] of Object.entries(l))e.startsWith("on") && "function" == typeof t ? (f[e] = t, delete l[e]) : "boolean" == typeof t && (t ? l[e] = e : delete l[e]);
|
||||
let s = Object.keys(l).length > 0 ? o.length > 1 ? E(e, l, o) : E(e, l, o[0]) : o.length > 1 ? E(e, {}, o) : E(e, {}, o[0]);
|
||||
for (let [e, t] of Object.entries(f)){
|
||||
let n = e.slice(2).toLowerCase();
|
||||
s.addEventListener(n, t);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
function jsx(t, n) {
|
||||
return jsx_factory_e(t, n);
|
||||
}
|
||||
function jsxs(t, n) {
|
||||
return jsx_factory_e(t, n);
|
||||
}
|
||||
function jsxDEV(t, n) {
|
||||
return jsx_factory_e(t, n);
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ../node_modules/.pnpm/@lazulikao+luci-types@https_685a81b9ead15f36368ce6e6ebcf4a27/node_modules/@lazulikao/luci-types/src/jsx/jsx-runtime.ts
|
||||
|
||||
|
||||
;// CONCATENATED MODULE: ./web/fluentdashboard/model.ts
|
||||
function model_t(t) {
|
||||
return null === t || "object" != typeof t || Array.isArray(t) ? {} : t;
|
||||
}
|
||||
function model_e(t) {
|
||||
return "string" == typeof t ? t : "";
|
||||
}
|
||||
function model_r(t) {
|
||||
return "number" == typeof t && Number.isFinite(t) ? t : 0;
|
||||
}
|
||||
function model_o(e, i = "free") {
|
||||
let n = model_t(e);
|
||||
return {
|
||||
total: model_r(n.total),
|
||||
free: model_r(n[i] ?? n.free)
|
||||
};
|
||||
}
|
||||
function normalizeSystemSnapshot(i, n, a) {
|
||||
let l = model_t(i), m = model_t(n), u = model_t(l.release), f = model_t(a), s = Array.isArray(m.load) ? m.load.map(model_r) : [];
|
||||
return {
|
||||
hostname: model_e(l.hostname),
|
||||
model: model_e(l.model),
|
||||
architecture: model_e(l.system),
|
||||
target: model_e(u.target),
|
||||
firmware: model_e(u.description),
|
||||
kernel: model_e(l.kernel),
|
||||
luciVersion: [
|
||||
model_e(f.branch),
|
||||
model_e(f.revision)
|
||||
].filter(Boolean).join(" "),
|
||||
uptime: model_r(m.uptime),
|
||||
localtime: model_r(m.localtime),
|
||||
load: s,
|
||||
memory: model_o(m.memory, "available"),
|
||||
swap: model_o(m.swap),
|
||||
root: model_o(m.root),
|
||||
tmp: model_o(m.tmp)
|
||||
};
|
||||
}
|
||||
function usedPercent(t) {
|
||||
return t.total <= 0 ? 0 : Math.min(100, Math.max(0, (t.total - t.free) / t.total * 100));
|
||||
}
|
||||
function formatBytes(t) {
|
||||
if (!Number.isFinite(t) || t <= 0) return "0 B";
|
||||
let e = [
|
||||
"B",
|
||||
"KiB",
|
||||
"MiB",
|
||||
"GiB",
|
||||
"TiB"
|
||||
], r = Math.min(Math.floor(Math.log(t) / Math.log(1024)), e.length - 1), o = t / 1024 ** r;
|
||||
return `${o >= 10 || 0 === r ? o.toFixed(0) : o.toFixed(1)} ${e[r]}`;
|
||||
}
|
||||
function formatDuration(t) {
|
||||
if (!Number.isFinite(t) || t <= 0) return "-";
|
||||
let e = Math.floor(t / 86400), r = Math.floor(t % 86400 / 3600), o = Math.floor(t % 3600 / 60);
|
||||
return [
|
||||
e > 0 ? `${e}d` : "",
|
||||
`${r}h`,
|
||||
`${o}m`
|
||||
].filter(Boolean).join(" ");
|
||||
}
|
||||
function formatLoad(t) {
|
||||
return 0 === t.length ? "-" : t.slice(0, 3).map((t)=>(t / 65535).toFixed(2)).join(" / ");
|
||||
}
|
||||
function formatLocalTime(t) {
|
||||
return !Number.isFinite(t) || t <= 0 ? "-" : new Intl.DateTimeFormat(void 0, {
|
||||
dateStyle: "medium",
|
||||
timeStyle: "medium",
|
||||
timeZone: "UTC"
|
||||
}).format(new Date(1000 * t));
|
||||
}
|
||||
|
||||
;// CONCATENATED MODULE: ./web/fluentdashboard/index.tsx
|
||||
|
||||
|
||||
let fluentdashboard_l = rpc.declare({
|
||||
object: "system",
|
||||
method: "board"
|
||||
}), fluentdashboard_o = rpc.declare({
|
||||
object: "system",
|
||||
method: "info"
|
||||
}), c = rpc.declare({
|
||||
object: "luci",
|
||||
method: "getVersion"
|
||||
}), fluentdashboard_u = rpc.declare({
|
||||
object: "luci-rpc",
|
||||
method: "getDHCPLeases",
|
||||
expect: {
|
||||
"": {}
|
||||
}
|
||||
});
|
||||
function fluentdashboard_h(e) {
|
||||
return null === e || "object" != typeof e || Array.isArray(e) ? {} : e;
|
||||
}
|
||||
function fluentdashboard_m(e) {
|
||||
return "string" == typeof e ? e : "";
|
||||
}
|
||||
function p(e) {
|
||||
return "number" == typeof e && Number.isFinite(e) ? e : 0;
|
||||
}
|
||||
async function fluentdashboard_f(e, t) {
|
||||
try {
|
||||
return await e;
|
||||
} catch {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
function y(e, t = !1) {
|
||||
let r = e.getL3Device() ?? e.getDevice();
|
||||
return {
|
||||
name: e.getName(),
|
||||
protocol: e.getI18n(),
|
||||
up: e.isUp(),
|
||||
addresses: t ? e.getIP6Addrs() : e.getIPAddrs(),
|
||||
gateway: t ? e.getGateway6Addr() : e.getGatewayAddr(),
|
||||
uptime: e.getUptime(),
|
||||
device: r?.getName() ?? "",
|
||||
rx: r?.getRXBytes() ?? 0,
|
||||
tx: r?.getTXBytes() ?? 0
|
||||
};
|
||||
}
|
||||
async function g() {
|
||||
await fluentdashboard_f(network.flushCache(), {});
|
||||
let [e, t, r, a, s, n, d, u] = await Promise.all([
|
||||
fluentdashboard_f(fluentdashboard_l(), {}),
|
||||
fluentdashboard_f(fluentdashboard_o(), {}),
|
||||
fluentdashboard_f(c(), {}),
|
||||
fluentdashboard_f(network.getWANNetworks(), []),
|
||||
fluentdashboard_f(network.getWAN6Networks(), []),
|
||||
fluentdashboard_f(network.getNetworks(), []),
|
||||
fluentdashboard_f(network.getWifiDevices(), []),
|
||||
fluentdashboard_f(network.getWifiNetworks(), [])
|
||||
]), h = u.map((e)=>{
|
||||
let t = d.find((t)=>t.getName() === e.getWifiDeviceName());
|
||||
return {
|
||||
radio: t?.getName() ?? e.getWifiDeviceName() ?? "",
|
||||
hardware: t?.getI18n() ?? "",
|
||||
up: e.isUp() && !t?.isDisabled(),
|
||||
ssid: e.getActiveSSID() || e.getSSID() || e.getMeshID() || "",
|
||||
mode: e.getActiveModeI18n() || e.getMode(),
|
||||
channel: e.getChannel(),
|
||||
frequency: e.getFrequency() ?? "",
|
||||
encryption: e.getActiveEncryption()
|
||||
};
|
||||
});
|
||||
for (let e of d)h.some((t)=>t.radio === e.getName()) || h.push({
|
||||
radio: e.getName(),
|
||||
hardware: e.getI18n(),
|
||||
up: e.isUp() && !e.isDisabled(),
|
||||
ssid: "",
|
||||
mode: "",
|
||||
channel: null,
|
||||
frequency: "",
|
||||
encryption: ""
|
||||
});
|
||||
return {
|
||||
system: normalizeSystemSnapshot(e, t, r),
|
||||
wan4: a.map((e)=>y(e)),
|
||||
wan6: s.map((e)=>y(e, !0)),
|
||||
interfaces: n.filter((e)=>"loopback" !== e.getName()).map((e)=>y(e)),
|
||||
wireless: h,
|
||||
updatedAt: new Date()
|
||||
};
|
||||
}
|
||||
async function w() {
|
||||
let [e, t, r] = await Promise.all([
|
||||
fluentdashboard_f(fluentdashboard_u(), {}),
|
||||
fluentdashboard_f(network.getWifiNetworks(), []),
|
||||
fluentdashboard_f(network.getHostHints(), null)
|
||||
]), a = await Promise.all(t.map(async (e)=>({
|
||||
wifi: e,
|
||||
peers: await fluentdashboard_f(e.getAssocList(), [])
|
||||
}))), s = [];
|
||||
for (let { wifi: e, peers: t } of a)for (let a of t){
|
||||
let t = r?.getHostnameByMACAddr(a.mac) || r?.getIPAddrByMACAddr(a.mac) || r?.getIP6AddrByMACAddr(a.mac) || "";
|
||||
s.push({
|
||||
network: e.getActiveSSID() || e.getSSID() || e.getName(),
|
||||
hostname: t,
|
||||
mac: a.mac,
|
||||
signal: a.signal,
|
||||
noise: a.noise ?? null,
|
||||
rxRate: a.rx?.rate ?? 0,
|
||||
txRate: a.tx?.rate ?? 0
|
||||
});
|
||||
}
|
||||
return {
|
||||
leases: function(e) {
|
||||
let t = fluentdashboard_h(e), r = [];
|
||||
if (Array.isArray(t.dhcp_leases)) for (let e of t.dhcp_leases){
|
||||
let t = fluentdashboard_h(e);
|
||||
r.push({
|
||||
family: "IPv4",
|
||||
hostname: fluentdashboard_m(t.hostname),
|
||||
address: fluentdashboard_m(t.ipaddr),
|
||||
identifier: fluentdashboard_m(t.macaddr),
|
||||
expires: !1 !== t.expires && p(t.expires)
|
||||
});
|
||||
}
|
||||
if (Array.isArray(t.dhcp6_leases)) for (let e of t.dhcp6_leases){
|
||||
let t = fluentdashboard_h(e), a = Array.isArray(t.ip6addrs) ? t.ip6addrs.filter((e)=>"string" == typeof e) : [];
|
||||
r.push({
|
||||
family: "IPv6",
|
||||
hostname: fluentdashboard_m(t.hostname),
|
||||
address: a.join(", ") || fluentdashboard_m(t.ip6addr),
|
||||
identifier: fluentdashboard_m(t.duid),
|
||||
expires: !1 !== t.expires && p(t.expires)
|
||||
});
|
||||
}
|
||||
return r;
|
||||
}(e),
|
||||
clients: s
|
||||
};
|
||||
}
|
||||
function b(e) {
|
||||
return null == e || "" === e ? "-" : String(e);
|
||||
}
|
||||
function v(t) {
|
||||
return jsx("span", {
|
||||
class: `fluent-dashboard__status fluent-dashboard__status--${t ? "up" : "down"}`,
|
||||
children: t ? _("Online") : _("Offline")
|
||||
});
|
||||
}
|
||||
function A(r, a, s, n = !1) {
|
||||
return jsxs("div", {
|
||||
class: `fluent-dashboard__card${n ? " fluent-dashboard__card--wide" : ""}`,
|
||||
"data-dashboard-section": r,
|
||||
children: [
|
||||
jsx("h2", {
|
||||
class: "fluent-dashboard__card-title",
|
||||
children: a
|
||||
}),
|
||||
jsx("div", {
|
||||
class: "fluent-dashboard__card-content",
|
||||
children: s
|
||||
})
|
||||
]
|
||||
});
|
||||
}
|
||||
function S(r, a, s) {
|
||||
return jsx("div", {
|
||||
class: "fluent-dashboard__table-wrap",
|
||||
children: jsxs("table", {
|
||||
class: "fluent-dashboard__table",
|
||||
children: [
|
||||
jsx("thead", {
|
||||
children: jsx("tr", {
|
||||
children: r.map((t)=>jsx("th", {
|
||||
children: t
|
||||
}))
|
||||
})
|
||||
}),
|
||||
jsx("tbody", {
|
||||
children: a.length ? a.map((t)=>jsx("tr", {
|
||||
children: t.map((t)=>jsx("td", {
|
||||
children: t instanceof Node ? t : b(t)
|
||||
}))
|
||||
})) : jsx("tr", {
|
||||
children: jsx("td", {
|
||||
class: "fluent-dashboard__empty",
|
||||
colSpan: r.length,
|
||||
children: s
|
||||
})
|
||||
})
|
||||
})
|
||||
]
|
||||
})
|
||||
});
|
||||
}
|
||||
function x(t) {
|
||||
return A("system", _("System"), jsx("div", {
|
||||
class: "fluent-dashboard__details",
|
||||
children: [
|
||||
[
|
||||
_("Hostname"),
|
||||
t.hostname
|
||||
],
|
||||
[
|
||||
_("Model"),
|
||||
t.model
|
||||
],
|
||||
[
|
||||
_("Architecture"),
|
||||
t.architecture
|
||||
],
|
||||
[
|
||||
_("Target Platform"),
|
||||
t.target
|
||||
],
|
||||
[
|
||||
_("Firmware Version"),
|
||||
t.firmware
|
||||
],
|
||||
[
|
||||
_("Kernel Version"),
|
||||
t.kernel
|
||||
],
|
||||
[
|
||||
_("LuCI Version"),
|
||||
t.luciVersion
|
||||
],
|
||||
[
|
||||
_("Local Time"),
|
||||
formatLocalTime(t.localtime)
|
||||
],
|
||||
[
|
||||
_("Uptime"),
|
||||
formatDuration(t.uptime)
|
||||
],
|
||||
[
|
||||
_("Load Average"),
|
||||
formatLoad(t.load)
|
||||
]
|
||||
].flatMap(([t, r])=>[
|
||||
jsx("div", {
|
||||
class: "fluent-dashboard__details-label",
|
||||
children: t
|
||||
}),
|
||||
jsx("div", {
|
||||
class: "fluent-dashboard__details-value",
|
||||
children: r instanceof Node ? r : b(r)
|
||||
})
|
||||
])
|
||||
}));
|
||||
}
|
||||
function I(a) {
|
||||
let s = [
|
||||
[
|
||||
_("Memory"),
|
||||
a.memory
|
||||
],
|
||||
[
|
||||
_("Swap"),
|
||||
a.swap
|
||||
],
|
||||
[
|
||||
_("Root storage"),
|
||||
a.root
|
||||
],
|
||||
[
|
||||
_("Temporary storage"),
|
||||
a.tmp
|
||||
]
|
||||
];
|
||||
return A("resources", _("Resources"), s.map(([a, s])=>{
|
||||
let n, i;
|
||||
return n = Math.max(0, s.total - s.free), i = usedPercent(s), jsxs("div", {
|
||||
class: "fluent-dashboard__meter",
|
||||
children: [
|
||||
jsxs("div", {
|
||||
class: "fluent-dashboard__meter-label",
|
||||
children: [
|
||||
jsx("span", {
|
||||
children: a
|
||||
}),
|
||||
jsx("span", {
|
||||
children: `${formatBytes(n)} / ${formatBytes(s.total)}`
|
||||
})
|
||||
]
|
||||
}),
|
||||
jsx("div", {
|
||||
class: "fluent-dashboard__meter-track",
|
||||
role: "progressbar",
|
||||
"aria-valuemin": 0,
|
||||
"aria-valuemax": 100,
|
||||
"aria-valuenow": Math.round(i),
|
||||
children: jsx("span", {
|
||||
class: "fluent-dashboard__meter-value",
|
||||
style: `width:${i.toFixed(1)}%`
|
||||
})
|
||||
})
|
||||
]
|
||||
});
|
||||
}));
|
||||
}
|
||||
function N(e) {
|
||||
let t = [
|
||||
...e.wan4.map((e)=>[
|
||||
"IPv4",
|
||||
e
|
||||
]),
|
||||
...e.wan6.map((e)=>[
|
||||
"IPv6",
|
||||
e
|
||||
])
|
||||
];
|
||||
return A("internet", _("Internet"), S([
|
||||
_("Family"),
|
||||
_("Interface"),
|
||||
_("Status"),
|
||||
_("Protocol"),
|
||||
_("Address"),
|
||||
_("Gateway"),
|
||||
_("Uptime")
|
||||
], t.map(([e, t])=>[
|
||||
e,
|
||||
t.name,
|
||||
v(t.up),
|
||||
t.protocol,
|
||||
t.addresses.join(", "),
|
||||
t.gateway,
|
||||
formatDuration(t.uptime)
|
||||
]), _("No Internet connection information is available.")), !0);
|
||||
}
|
||||
function D(e) {
|
||||
return A("interfaces", _("Interfaces"), S([
|
||||
_("Interface"),
|
||||
_("Device"),
|
||||
_("Status"),
|
||||
_("Address"),
|
||||
_("Received"),
|
||||
_("Transmitted")
|
||||
], e.map((e)=>[
|
||||
e.name,
|
||||
e.device,
|
||||
v(e.up),
|
||||
e.addresses.join(", "),
|
||||
formatBytes(e.rx),
|
||||
formatBytes(e.tx)
|
||||
]), _("No network interfaces were found.")), !0);
|
||||
}
|
||||
function k(t) {
|
||||
return A("wireless", _("Wireless"), S([
|
||||
_("Radio"),
|
||||
_("SSID"),
|
||||
_("Status"),
|
||||
_("Mode"),
|
||||
_("Channel"),
|
||||
_("Encryption")
|
||||
], t.map((t)=>[
|
||||
jsx("span", {
|
||||
title: t.hardware,
|
||||
children: b(t.radio)
|
||||
}),
|
||||
t.ssid,
|
||||
v(t.up),
|
||||
t.mode,
|
||||
null === t.channel ? "-" : t.frequency ? `${t.channel} (${t.frequency} GHz)` : t.channel,
|
||||
t.encryption
|
||||
]), _("No wireless radios were found.")), !0);
|
||||
}
|
||||
function C(e) {
|
||||
return A("leases", _("Active DHCP Leases"), S([
|
||||
_("Family"),
|
||||
_("Hostname"),
|
||||
_("Address"),
|
||||
_("MAC / DUID"),
|
||||
_("Expires")
|
||||
], e.map((e)=>{
|
||||
var t;
|
||||
return [
|
||||
e.family,
|
||||
e.hostname,
|
||||
e.address,
|
||||
e.identifier,
|
||||
!1 === (t = e.expires) ? _("Unlimited") : t <= 0 ? _("Expired") : formatDuration(t)
|
||||
];
|
||||
}), _("There are no active DHCP leases.")), !0);
|
||||
}
|
||||
function P(e) {
|
||||
return e > 0 ? `${(e / 1000).toFixed(1)} ${_("Mbit/s")}` : "-";
|
||||
}
|
||||
function M(e) {
|
||||
return A("clients", _("Wireless Clients"), S([
|
||||
_("Network"),
|
||||
_("Host"),
|
||||
_("MAC address"),
|
||||
_("Signal"),
|
||||
_("RX / TX Rate")
|
||||
], e.map((e)=>[
|
||||
e.network,
|
||||
e.hostname,
|
||||
e.mac,
|
||||
null === e.noise ? `${e.signal} dBm` : `${e.signal} / ${e.noise} dBm`,
|
||||
`${P(e.rxRate)} / ${P(e.txRate)}`
|
||||
]), _("No wireless clients are connected.")), !0);
|
||||
}
|
||||
class $ extends L.view {
|
||||
handleSave = null;
|
||||
handleSaveApply = null;
|
||||
handleReset = null;
|
||||
root = null;
|
||||
load() {
|
||||
return Promise.all([
|
||||
g(),
|
||||
w()
|
||||
]);
|
||||
}
|
||||
replaceSection(e, t) {
|
||||
this.root?.querySelector(`[data-dashboard-section="${e}"]`)?.replaceWith(t);
|
||||
}
|
||||
async refreshSummary() {
|
||||
if (!this.root?.isConnected) return;
|
||||
let e = await g();
|
||||
if (!this.root?.isConnected) return;
|
||||
this.replaceSection("system", x(e.system)), this.replaceSection("resources", I(e.system)), this.replaceSection("internet", N(e)), this.replaceSection("interfaces", D(e.interfaces)), this.replaceSection("wireless", k(e.wireless));
|
||||
let t = this.root.querySelector("[data-dashboard-updated]");
|
||||
t && (t.textContent = e.updatedAt.toLocaleTimeString());
|
||||
}
|
||||
async refreshDetails() {
|
||||
if (!this.root?.isConnected) return;
|
||||
let e = await w();
|
||||
this.root?.isConnected && (this.replaceSection("leases", C(e.leases)), this.replaceSection("clients", M(e.clients)));
|
||||
}
|
||||
render([r, a]) {
|
||||
return document.getElementById("fluent-dashboard-styles") || document.head.appendChild(jsx("link", {
|
||||
id: "fluent-dashboard-styles",
|
||||
rel: "stylesheet",
|
||||
href: L.resource("view/fluentdashboard/index.css")
|
||||
})), this.root = jsxs("div", {
|
||||
class: "fluent-dashboard",
|
||||
children: [
|
||||
jsxs("div", {
|
||||
class: "fluent-dashboard__header",
|
||||
children: [
|
||||
jsxs("div", {
|
||||
children: [
|
||||
jsx("h1", {
|
||||
children: _("Fluent Dashboard")
|
||||
}),
|
||||
jsx("p", {
|
||||
children: _("A live overview of this OpenWrt device.")
|
||||
})
|
||||
]
|
||||
}),
|
||||
jsxs("p", {
|
||||
class: "fluent-dashboard__updated",
|
||||
children: [
|
||||
_("Updated"),
|
||||
" ",
|
||||
jsx("time", {
|
||||
"data-dashboard-updated": "",
|
||||
children: r.updatedAt.toLocaleTimeString()
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
}),
|
||||
jsxs("div", {
|
||||
class: "fluent-dashboard__grid",
|
||||
children: [
|
||||
x(r.system),
|
||||
I(r.system),
|
||||
N(r),
|
||||
D(r.interfaces),
|
||||
k(r.wireless),
|
||||
C(a.leases),
|
||||
M(a.clients)
|
||||
]
|
||||
})
|
||||
]
|
||||
}), poll.add(()=>this.refreshSummary(), 5), poll.add(()=>this.refreshDetails(), 15), this.root;
|
||||
}
|
||||
}
|
||||
const main = $;
|
||||
|
||||
|
||||
return main;
|
||||
Reference in new issue
Block a user