diff --git a/pulse-test-staging/VERSION b/pulse-test-staging/VERSION
deleted file mode 100644
index f5eaf8d6b..000000000
--- a/pulse-test-staging/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-4.0.0-rc.1-test
diff --git a/pulse-test-staging/frontend-modern/.gitignore b/pulse-test-staging/frontend-modern/.gitignore
deleted file mode 100644
index 7cc38cf5c..000000000
--- a/pulse-test-staging/frontend-modern/.gitignore
+++ /dev/null
@@ -1,32 +0,0 @@
-# Dependencies
-node_modules
-.pnp
-.pnp.js
-
-# Testing
-coverage
-
-# Production
-dist
-dist-ssr
-*.local
-
-# Editor directories and files
-.vscode/*
-!.vscode/extensions.json
-.idea
-.DS_Store
-*.suo
-*.ntvs*
-*.njsproj
-*.sln
-*.sw?
-
-# Logs
-logs
-*.log
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-lerna-debug.log*
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/_metadata.json b/pulse-test-staging/frontend-modern/.vite/deps/_metadata.json
deleted file mode 100644
index 162d6a624..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/_metadata.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "hash": "c68cb1be",
- "configHash": "5ad14a4a",
- "lockfileHash": "ed97e1da",
- "browserHash": "e2aaadd5",
- "optimized": {
- "solid-js/web": {
- "src": "../../node_modules/solid-js/web/dist/dev.js",
- "file": "solid-js_web.js",
- "fileHash": "772f198c",
- "needsInterop": false
- },
- "solid-js": {
- "src": "../../node_modules/solid-js/dist/dev.js",
- "file": "solid-js.js",
- "fileHash": "c1c8cb80",
- "needsInterop": false
- },
- "solid-js/store": {
- "src": "../../node_modules/solid-js/store/dist/dev.js",
- "file": "solid-js_store.js",
- "fileHash": "a2c5a714",
- "needsInterop": false
- }
- },
- "chunks": {
- "chunk-IZS3CG5R": {
- "file": "chunk-IZS3CG5R.js"
- }
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/chunk-IZS3CG5R.js b/pulse-test-staging/frontend-modern/.vite/deps/chunk-IZS3CG5R.js
deleted file mode 100644
index 1e76867ad..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/chunk-IZS3CG5R.js
+++ /dev/null
@@ -1,1810 +0,0 @@
-// node_modules/solid-js/dist/dev.js
-var taskIdCounter = 1;
-var isCallbackScheduled = false;
-var isPerformingWork = false;
-var taskQueue = [];
-var currentTask = null;
-var shouldYieldToHost = null;
-var yieldInterval = 5;
-var deadline = 0;
-var maxYieldInterval = 300;
-var scheduleCallback = null;
-var scheduledCallback = null;
-var maxSigned31BitInt = 1073741823;
-function setupScheduler() {
- const channel = new MessageChannel(), port = channel.port2;
- scheduleCallback = () => port.postMessage(null);
- channel.port1.onmessage = () => {
- if (scheduledCallback !== null) {
- const currentTime = performance.now();
- deadline = currentTime + yieldInterval;
- const hasTimeRemaining = true;
- try {
- const hasMoreWork = scheduledCallback(hasTimeRemaining, currentTime);
- if (!hasMoreWork) {
- scheduledCallback = null;
- } else port.postMessage(null);
- } catch (error) {
- port.postMessage(null);
- throw error;
- }
- }
- };
- if (navigator && navigator.scheduling && navigator.scheduling.isInputPending) {
- const scheduling = navigator.scheduling;
- shouldYieldToHost = () => {
- const currentTime = performance.now();
- if (currentTime >= deadline) {
- if (scheduling.isInputPending()) {
- return true;
- }
- return currentTime >= maxYieldInterval;
- } else {
- return false;
- }
- };
- } else {
- shouldYieldToHost = () => performance.now() >= deadline;
- }
-}
-function enqueue(taskQueue2, task) {
- function findIndex() {
- let m = 0;
- let n = taskQueue2.length - 1;
- while (m <= n) {
- const k = n + m >> 1;
- const cmp = task.expirationTime - taskQueue2[k].expirationTime;
- if (cmp > 0) m = k + 1;
- else if (cmp < 0) n = k - 1;
- else return k;
- }
- return m;
- }
- taskQueue2.splice(findIndex(), 0, task);
-}
-function requestCallback(fn, options) {
- if (!scheduleCallback) setupScheduler();
- let startTime = performance.now(), timeout = maxSigned31BitInt;
- if (options && options.timeout) timeout = options.timeout;
- const newTask = {
- id: taskIdCounter++,
- fn,
- startTime,
- expirationTime: startTime + timeout
- };
- enqueue(taskQueue, newTask);
- if (!isCallbackScheduled && !isPerformingWork) {
- isCallbackScheduled = true;
- scheduledCallback = flushWork;
- scheduleCallback();
- }
- return newTask;
-}
-function cancelCallback(task) {
- task.fn = null;
-}
-function flushWork(hasTimeRemaining, initialTime) {
- isCallbackScheduled = false;
- isPerformingWork = true;
- try {
- return workLoop(hasTimeRemaining, initialTime);
- } finally {
- currentTask = null;
- isPerformingWork = false;
- }
-}
-function workLoop(hasTimeRemaining, initialTime) {
- let currentTime = initialTime;
- currentTask = taskQueue[0] || null;
- while (currentTask !== null) {
- if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {
- break;
- }
- const callback = currentTask.fn;
- if (callback !== null) {
- currentTask.fn = null;
- const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;
- callback(didUserCallbackTimeout);
- currentTime = performance.now();
- if (currentTask === taskQueue[0]) {
- taskQueue.shift();
- }
- } else taskQueue.shift();
- currentTask = taskQueue[0] || null;
- }
- return currentTask !== null;
-}
-var sharedConfig = {
- context: void 0,
- registry: void 0,
- effects: void 0,
- done: false,
- getContextId() {
- return getContextId(this.context.count);
- },
- getNextContextId() {
- return getContextId(this.context.count++);
- }
-};
-function getContextId(count) {
- const num = String(count), len = num.length - 1;
- return sharedConfig.context.id + (len ? String.fromCharCode(96 + len) : "") + num;
-}
-function setHydrateContext(context) {
- sharedConfig.context = context;
-}
-function nextHydrateContext() {
- return {
- ...sharedConfig.context,
- id: sharedConfig.getNextContextId(),
- count: 0
- };
-}
-var IS_DEV = true;
-var equalFn = (a, b) => a === b;
-var $PROXY = Symbol("solid-proxy");
-var SUPPORTS_PROXY = typeof Proxy === "function";
-var $TRACK = Symbol("solid-track");
-var $DEVCOMP = Symbol("solid-dev-component");
-var signalOptions = {
- equals: equalFn
-};
-var ERROR = null;
-var runEffects = runQueue;
-var STALE = 1;
-var PENDING = 2;
-var UNOWNED = {
- owned: null,
- cleanups: null,
- context: null,
- owner: null
-};
-var NO_INIT = {};
-var Owner = null;
-var Transition = null;
-var Scheduler = null;
-var ExternalSourceConfig = null;
-var Listener = null;
-var Updates = null;
-var Effects = null;
-var ExecCount = 0;
-var DevHooks = {
- afterUpdate: null,
- afterCreateOwner: null,
- afterCreateSignal: null,
- afterRegisterGraph: null
-};
-function createRoot(fn, detachedOwner) {
- const listener = Listener, owner = Owner, unowned = fn.length === 0, current = detachedOwner === void 0 ? owner : detachedOwner, root = unowned ? {
- owned: null,
- cleanups: null,
- context: null,
- owner: null
- } : {
- owned: null,
- cleanups: null,
- context: current ? current.context : null,
- owner: current
- }, updateFn = unowned ? () => fn(() => {
- throw new Error("Dispose method must be an explicit argument to createRoot function");
- }) : () => fn(() => untrack(() => cleanNode(root)));
- DevHooks.afterCreateOwner && DevHooks.afterCreateOwner(root);
- Owner = root;
- Listener = null;
- try {
- return runUpdates(updateFn, true);
- } finally {
- Listener = listener;
- Owner = owner;
- }
-}
-function createSignal(value, options) {
- options = options ? Object.assign({}, signalOptions, options) : signalOptions;
- const s = {
- value,
- observers: null,
- observerSlots: null,
- comparator: options.equals || void 0
- };
- {
- if (options.name) s.name = options.name;
- if (options.internal) {
- s.internal = true;
- } else {
- registerGraph(s);
- if (DevHooks.afterCreateSignal) DevHooks.afterCreateSignal(s);
- }
- }
- const setter = (value2) => {
- if (typeof value2 === "function") {
- if (Transition && Transition.running && Transition.sources.has(s)) value2 = value2(s.tValue);
- else value2 = value2(s.value);
- }
- return writeSignal(s, value2);
- };
- return [readSignal.bind(s), setter];
-}
-function createComputed(fn, value, options) {
- const c = createComputation(fn, value, true, STALE, options);
- if (Scheduler && Transition && Transition.running) Updates.push(c);
- else updateComputation(c);
-}
-function createRenderEffect(fn, value, options) {
- const c = createComputation(fn, value, false, STALE, options);
- if (Scheduler && Transition && Transition.running) Updates.push(c);
- else updateComputation(c);
-}
-function createEffect(fn, value, options) {
- runEffects = runUserEffects;
- const c = createComputation(fn, value, false, STALE, options), s = SuspenseContext && useContext(SuspenseContext);
- if (s) c.suspense = s;
- if (!options || !options.render) c.user = true;
- Effects ? Effects.push(c) : updateComputation(c);
-}
-function createReaction(onInvalidate, options) {
- let fn;
- const c = createComputation(() => {
- fn ? fn() : untrack(onInvalidate);
- fn = void 0;
- }, void 0, false, 0, options), s = SuspenseContext && useContext(SuspenseContext);
- if (s) c.suspense = s;
- c.user = true;
- return (tracking) => {
- fn = tracking;
- updateComputation(c);
- };
-}
-function createMemo(fn, value, options) {
- options = options ? Object.assign({}, signalOptions, options) : signalOptions;
- const c = createComputation(fn, value, true, 0, options);
- c.observers = null;
- c.observerSlots = null;
- c.comparator = options.equals || void 0;
- if (Scheduler && Transition && Transition.running) {
- c.tState = STALE;
- Updates.push(c);
- } else updateComputation(c);
- return readSignal.bind(c);
-}
-function isPromise(v) {
- return v && typeof v === "object" && "then" in v;
-}
-function createResource(pSource, pFetcher, pOptions) {
- let source;
- let fetcher;
- let options;
- if (typeof pFetcher === "function") {
- source = pSource;
- fetcher = pFetcher;
- options = pOptions || {};
- } else {
- source = true;
- fetcher = pSource;
- options = pFetcher || {};
- }
- let pr = null, initP = NO_INIT, id = null, loadedUnderTransition = false, scheduled = false, resolved = "initialValue" in options, dynamic = typeof source === "function" && createMemo(source);
- const contexts = /* @__PURE__ */ new Set(), [value, setValue] = (options.storage || createSignal)(options.initialValue), [error, setError] = createSignal(void 0), [track, trigger] = createSignal(void 0, {
- equals: false
- }), [state, setState] = createSignal(resolved ? "ready" : "unresolved");
- if (sharedConfig.context) {
- id = sharedConfig.getNextContextId();
- if (options.ssrLoadFrom === "initial") initP = options.initialValue;
- else if (sharedConfig.load && sharedConfig.has(id)) initP = sharedConfig.load(id);
- }
- function loadEnd(p, v, error2, key) {
- if (pr === p) {
- pr = null;
- key !== void 0 && (resolved = true);
- if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {
- value: v
- }));
- initP = NO_INIT;
- if (Transition && p && loadedUnderTransition) {
- Transition.promises.delete(p);
- loadedUnderTransition = false;
- runUpdates(() => {
- Transition.running = true;
- completeLoad(v, error2);
- }, false);
- } else completeLoad(v, error2);
- }
- return v;
- }
- function completeLoad(v, err) {
- runUpdates(() => {
- if (err === void 0) setValue(() => v);
- setState(err !== void 0 ? "errored" : resolved ? "ready" : "unresolved");
- setError(err);
- for (const c of contexts.keys()) c.decrement();
- contexts.clear();
- }, false);
- }
- function read() {
- const c = SuspenseContext && useContext(SuspenseContext), v = value(), err = error();
- if (err !== void 0 && !pr) throw err;
- if (Listener && !Listener.user && c) {
- createComputed(() => {
- track();
- if (pr) {
- if (c.resolved && Transition && loadedUnderTransition) Transition.promises.add(pr);
- else if (!contexts.has(c)) {
- c.increment();
- contexts.add(c);
- }
- }
- });
- }
- return v;
- }
- function load(refetching = true) {
- if (refetching !== false && scheduled) return;
- scheduled = false;
- const lookup = dynamic ? dynamic() : source;
- loadedUnderTransition = Transition && Transition.running;
- if (lookup == null || lookup === false) {
- loadEnd(pr, untrack(value));
- return;
- }
- if (Transition && pr) Transition.promises.delete(pr);
- let error2;
- const p = initP !== NO_INIT ? initP : untrack(() => {
- try {
- return fetcher(lookup, {
- value: value(),
- refetching
- });
- } catch (fetcherError) {
- error2 = fetcherError;
- }
- });
- if (error2 !== void 0) {
- loadEnd(pr, void 0, castError(error2), lookup);
- return;
- } else if (!isPromise(p)) {
- loadEnd(pr, p, void 0, lookup);
- return p;
- }
- pr = p;
- if ("v" in p) {
- if (p.s === 1) loadEnd(pr, p.v, void 0, lookup);
- else loadEnd(pr, void 0, castError(p.v), lookup);
- return p;
- }
- scheduled = true;
- queueMicrotask(() => scheduled = false);
- runUpdates(() => {
- setState(resolved ? "refreshing" : "pending");
- trigger();
- }, false);
- return p.then((v) => loadEnd(p, v, void 0, lookup), (e) => loadEnd(p, void 0, castError(e), lookup));
- }
- Object.defineProperties(read, {
- state: {
- get: () => state()
- },
- error: {
- get: () => error()
- },
- loading: {
- get() {
- const s = state();
- return s === "pending" || s === "refreshing";
- }
- },
- latest: {
- get() {
- if (!resolved) return read();
- const err = error();
- if (err && !pr) throw err;
- return value();
- }
- }
- });
- let owner = Owner;
- if (dynamic) createComputed(() => (owner = Owner, load(false)));
- else load(false);
- return [read, {
- refetch: (info) => runWithOwner(owner, () => load(info)),
- mutate: setValue
- }];
-}
-function createDeferred(source, options) {
- let t, timeout = options ? options.timeoutMs : void 0;
- const node = createComputation(() => {
- if (!t || !t.fn) t = requestCallback(() => setDeferred(() => node.value), timeout !== void 0 ? {
- timeout
- } : void 0);
- return source();
- }, void 0, true);
- const [deferred, setDeferred] = createSignal(Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value, options);
- updateComputation(node);
- setDeferred(() => Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);
- return deferred;
-}
-function createSelector(source, fn = equalFn, options) {
- const subs = /* @__PURE__ */ new Map();
- const node = createComputation((p) => {
- const v = source();
- for (const [key, val] of subs.entries()) if (fn(key, v) !== fn(key, p)) {
- for (const c of val.values()) {
- c.state = STALE;
- if (c.pure) Updates.push(c);
- else Effects.push(c);
- }
- }
- return v;
- }, void 0, true, STALE, options);
- updateComputation(node);
- return (key) => {
- const listener = Listener;
- if (listener) {
- let l;
- if (l = subs.get(key)) l.add(listener);
- else subs.set(key, l = /* @__PURE__ */ new Set([listener]));
- onCleanup(() => {
- l.delete(listener);
- !l.size && subs.delete(key);
- });
- }
- return fn(key, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);
- };
-}
-function batch(fn) {
- return runUpdates(fn, false);
-}
-function untrack(fn) {
- if (!ExternalSourceConfig && Listener === null) return fn();
- const listener = Listener;
- Listener = null;
- try {
- if (ExternalSourceConfig) return ExternalSourceConfig.untrack(fn);
- return fn();
- } finally {
- Listener = listener;
- }
-}
-function on(deps, fn, options) {
- const isArray = Array.isArray(deps);
- let prevInput;
- let defer = options && options.defer;
- return (prevValue) => {
- let input;
- if (isArray) {
- input = Array(deps.length);
- for (let i = 0; i < deps.length; i++) input[i] = deps[i]();
- } else input = deps();
- if (defer) {
- defer = false;
- return prevValue;
- }
- const result = untrack(() => fn(input, prevInput, prevValue));
- prevInput = input;
- return result;
- };
-}
-function onMount(fn) {
- createEffect(() => untrack(fn));
-}
-function onCleanup(fn) {
- if (Owner === null) console.warn("cleanups created outside a `createRoot` or `render` will never be run");
- else if (Owner.cleanups === null) Owner.cleanups = [fn];
- else Owner.cleanups.push(fn);
- return fn;
-}
-function catchError(fn, handler) {
- ERROR || (ERROR = Symbol("error"));
- Owner = createComputation(void 0, void 0, true);
- Owner.context = {
- ...Owner.context,
- [ERROR]: [handler]
- };
- if (Transition && Transition.running) Transition.sources.add(Owner);
- try {
- return fn();
- } catch (err) {
- handleError(err);
- } finally {
- Owner = Owner.owner;
- }
-}
-function getListener() {
- return Listener;
-}
-function getOwner() {
- return Owner;
-}
-function runWithOwner(o, fn) {
- const prev = Owner;
- const prevListener = Listener;
- Owner = o;
- Listener = null;
- try {
- return runUpdates(fn, true);
- } catch (err) {
- handleError(err);
- } finally {
- Owner = prev;
- Listener = prevListener;
- }
-}
-function enableScheduling(scheduler = requestCallback) {
- Scheduler = scheduler;
-}
-function startTransition(fn) {
- if (Transition && Transition.running) {
- fn();
- return Transition.done;
- }
- const l = Listener;
- const o = Owner;
- return Promise.resolve().then(() => {
- Listener = l;
- Owner = o;
- let t;
- if (Scheduler || SuspenseContext) {
- t = Transition || (Transition = {
- sources: /* @__PURE__ */ new Set(),
- effects: [],
- promises: /* @__PURE__ */ new Set(),
- disposed: /* @__PURE__ */ new Set(),
- queue: /* @__PURE__ */ new Set(),
- running: true
- });
- t.done || (t.done = new Promise((res) => t.resolve = res));
- t.running = true;
- }
- runUpdates(fn, false);
- Listener = Owner = null;
- return t ? t.done : void 0;
- });
-}
-var [transPending, setTransPending] = createSignal(false);
-function useTransition() {
- return [transPending, startTransition];
-}
-function resumeEffects(e) {
- Effects.push.apply(Effects, e);
- e.length = 0;
-}
-function devComponent(Comp, props) {
- const c = createComputation(() => untrack(() => {
- Object.assign(Comp, {
- [$DEVCOMP]: true
- });
- return Comp(props);
- }), void 0, true, 0);
- c.props = props;
- c.observers = null;
- c.observerSlots = null;
- c.name = Comp.name;
- c.component = Comp;
- updateComputation(c);
- return c.tValue !== void 0 ? c.tValue : c.value;
-}
-function registerGraph(value) {
- if (Owner) {
- if (Owner.sourceMap) Owner.sourceMap.push(value);
- else Owner.sourceMap = [value];
- value.graph = Owner;
- }
- if (DevHooks.afterRegisterGraph) DevHooks.afterRegisterGraph(value);
-}
-function createContext(defaultValue, options) {
- const id = Symbol("context");
- return {
- id,
- Provider: createProvider(id, options),
- defaultValue
- };
-}
-function useContext(context) {
- let value;
- return Owner && Owner.context && (value = Owner.context[context.id]) !== void 0 ? value : context.defaultValue;
-}
-function children(fn) {
- const children2 = createMemo(fn);
- const memo = createMemo(() => resolveChildren(children2()), void 0, {
- name: "children"
- });
- memo.toArray = () => {
- const c = memo();
- return Array.isArray(c) ? c : c != null ? [c] : [];
- };
- return memo;
-}
-var SuspenseContext;
-function getSuspenseContext() {
- return SuspenseContext || (SuspenseContext = createContext());
-}
-function enableExternalSource(factory, untrack2 = (fn) => fn()) {
- if (ExternalSourceConfig) {
- const {
- factory: oldFactory,
- untrack: oldUntrack
- } = ExternalSourceConfig;
- ExternalSourceConfig = {
- factory: (fn, trigger) => {
- const oldSource = oldFactory(fn, trigger);
- const source = factory((x) => oldSource.track(x), trigger);
- return {
- track: (x) => source.track(x),
- dispose() {
- source.dispose();
- oldSource.dispose();
- }
- };
- },
- untrack: (fn) => oldUntrack(() => untrack2(fn))
- };
- } else {
- ExternalSourceConfig = {
- factory,
- untrack: untrack2
- };
- }
-}
-function readSignal() {
- const runningTransition = Transition && Transition.running;
- if (this.sources && (runningTransition ? this.tState : this.state)) {
- if ((runningTransition ? this.tState : this.state) === STALE) updateComputation(this);
- else {
- const updates = Updates;
- Updates = null;
- runUpdates(() => lookUpstream(this), false);
- Updates = updates;
- }
- }
- if (Listener) {
- const sSlot = this.observers ? this.observers.length : 0;
- if (!Listener.sources) {
- Listener.sources = [this];
- Listener.sourceSlots = [sSlot];
- } else {
- Listener.sources.push(this);
- Listener.sourceSlots.push(sSlot);
- }
- if (!this.observers) {
- this.observers = [Listener];
- this.observerSlots = [Listener.sources.length - 1];
- } else {
- this.observers.push(Listener);
- this.observerSlots.push(Listener.sources.length - 1);
- }
- }
- if (runningTransition && Transition.sources.has(this)) return this.tValue;
- return this.value;
-}
-function writeSignal(node, value, isComp) {
- let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;
- if (!node.comparator || !node.comparator(current, value)) {
- if (Transition) {
- const TransitionRunning = Transition.running;
- if (TransitionRunning || !isComp && Transition.sources.has(node)) {
- Transition.sources.add(node);
- node.tValue = value;
- }
- if (!TransitionRunning) node.value = value;
- } else node.value = value;
- if (node.observers && node.observers.length) {
- runUpdates(() => {
- for (let i = 0; i < node.observers.length; i += 1) {
- const o = node.observers[i];
- const TransitionRunning = Transition && Transition.running;
- if (TransitionRunning && Transition.disposed.has(o)) continue;
- if (TransitionRunning ? !o.tState : !o.state) {
- if (o.pure) Updates.push(o);
- else Effects.push(o);
- if (o.observers) markDownstream(o);
- }
- if (!TransitionRunning) o.state = STALE;
- else o.tState = STALE;
- }
- if (Updates.length > 1e6) {
- Updates = [];
- if (IS_DEV) throw new Error("Potential Infinite Loop Detected.");
- throw new Error();
- }
- }, false);
- }
- }
- return value;
-}
-function updateComputation(node) {
- if (!node.fn) return;
- cleanNode(node);
- const time = ExecCount;
- runComputation(node, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value, time);
- if (Transition && !Transition.running && Transition.sources.has(node)) {
- queueMicrotask(() => {
- runUpdates(() => {
- Transition && (Transition.running = true);
- Listener = Owner = node;
- runComputation(node, node.tValue, time);
- Listener = Owner = null;
- }, false);
- });
- }
-}
-function runComputation(node, value, time) {
- let nextValue;
- const owner = Owner, listener = Listener;
- Listener = Owner = node;
- try {
- nextValue = node.fn(value);
- } catch (err) {
- if (node.pure) {
- if (Transition && Transition.running) {
- node.tState = STALE;
- node.tOwned && node.tOwned.forEach(cleanNode);
- node.tOwned = void 0;
- } else {
- node.state = STALE;
- node.owned && node.owned.forEach(cleanNode);
- node.owned = null;
- }
- }
- node.updatedAt = time + 1;
- return handleError(err);
- } finally {
- Listener = listener;
- Owner = owner;
- }
- if (!node.updatedAt || node.updatedAt <= time) {
- if (node.updatedAt != null && "observers" in node) {
- writeSignal(node, nextValue, true);
- } else if (Transition && Transition.running && node.pure) {
- Transition.sources.add(node);
- node.tValue = nextValue;
- } else node.value = nextValue;
- node.updatedAt = time;
- }
-}
-function createComputation(fn, init, pure, state = STALE, options) {
- const c = {
- fn,
- state,
- updatedAt: null,
- owned: null,
- sources: null,
- sourceSlots: null,
- cleanups: null,
- value: init,
- owner: Owner,
- context: Owner ? Owner.context : null,
- pure
- };
- if (Transition && Transition.running) {
- c.state = 0;
- c.tState = state;
- }
- if (Owner === null) console.warn("computations created outside a `createRoot` or `render` will never be disposed");
- else if (Owner !== UNOWNED) {
- if (Transition && Transition.running && Owner.pure) {
- if (!Owner.tOwned) Owner.tOwned = [c];
- else Owner.tOwned.push(c);
- } else {
- if (!Owner.owned) Owner.owned = [c];
- else Owner.owned.push(c);
- }
- }
- if (options && options.name) c.name = options.name;
- if (ExternalSourceConfig && c.fn) {
- const [track, trigger] = createSignal(void 0, {
- equals: false
- });
- const ordinary = ExternalSourceConfig.factory(c.fn, trigger);
- onCleanup(() => ordinary.dispose());
- const triggerInTransition = () => startTransition(trigger).then(() => inTransition.dispose());
- const inTransition = ExternalSourceConfig.factory(c.fn, triggerInTransition);
- c.fn = (x) => {
- track();
- return Transition && Transition.running ? inTransition.track(x) : ordinary.track(x);
- };
- }
- DevHooks.afterCreateOwner && DevHooks.afterCreateOwner(c);
- return c;
-}
-function runTop(node) {
- const runningTransition = Transition && Transition.running;
- if ((runningTransition ? node.tState : node.state) === 0) return;
- if ((runningTransition ? node.tState : node.state) === PENDING) return lookUpstream(node);
- if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node);
- const ancestors = [node];
- while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
- if (runningTransition && Transition.disposed.has(node)) return;
- if (runningTransition ? node.tState : node.state) ancestors.push(node);
- }
- for (let i = ancestors.length - 1; i >= 0; i--) {
- node = ancestors[i];
- if (runningTransition) {
- let top = node, prev = ancestors[i + 1];
- while ((top = top.owner) && top !== prev) {
- if (Transition.disposed.has(top)) return;
- }
- }
- if ((runningTransition ? node.tState : node.state) === STALE) {
- updateComputation(node);
- } else if ((runningTransition ? node.tState : node.state) === PENDING) {
- const updates = Updates;
- Updates = null;
- runUpdates(() => lookUpstream(node, ancestors[0]), false);
- Updates = updates;
- }
- }
-}
-function runUpdates(fn, init) {
- if (Updates) return fn();
- let wait = false;
- if (!init) Updates = [];
- if (Effects) wait = true;
- else Effects = [];
- ExecCount++;
- try {
- const res = fn();
- completeUpdates(wait);
- return res;
- } catch (err) {
- if (!wait) Effects = null;
- Updates = null;
- handleError(err);
- }
-}
-function completeUpdates(wait) {
- if (Updates) {
- if (Scheduler && Transition && Transition.running) scheduleQueue(Updates);
- else runQueue(Updates);
- Updates = null;
- }
- if (wait) return;
- let res;
- if (Transition) {
- if (!Transition.promises.size && !Transition.queue.size) {
- const sources = Transition.sources;
- const disposed = Transition.disposed;
- Effects.push.apply(Effects, Transition.effects);
- res = Transition.resolve;
- for (const e2 of Effects) {
- "tState" in e2 && (e2.state = e2.tState);
- delete e2.tState;
- }
- Transition = null;
- runUpdates(() => {
- for (const d of disposed) cleanNode(d);
- for (const v of sources) {
- v.value = v.tValue;
- if (v.owned) {
- for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);
- }
- if (v.tOwned) v.owned = v.tOwned;
- delete v.tValue;
- delete v.tOwned;
- v.tState = 0;
- }
- setTransPending(false);
- }, false);
- } else if (Transition.running) {
- Transition.running = false;
- Transition.effects.push.apply(Transition.effects, Effects);
- Effects = null;
- setTransPending(true);
- return;
- }
- }
- const e = Effects;
- Effects = null;
- if (e.length) runUpdates(() => runEffects(e), false);
- else DevHooks.afterUpdate && DevHooks.afterUpdate();
- if (res) res();
-}
-function runQueue(queue) {
- for (let i = 0; i < queue.length; i++) runTop(queue[i]);
-}
-function scheduleQueue(queue) {
- for (let i = 0; i < queue.length; i++) {
- const item = queue[i];
- const tasks = Transition.queue;
- if (!tasks.has(item)) {
- tasks.add(item);
- Scheduler(() => {
- tasks.delete(item);
- runUpdates(() => {
- Transition.running = true;
- runTop(item);
- }, false);
- Transition && (Transition.running = false);
- });
- }
- }
-}
-function runUserEffects(queue) {
- let i, userLength = 0;
- for (i = 0; i < queue.length; i++) {
- const e = queue[i];
- if (!e.user) runTop(e);
- else queue[userLength++] = e;
- }
- if (sharedConfig.context) {
- if (sharedConfig.count) {
- sharedConfig.effects || (sharedConfig.effects = []);
- sharedConfig.effects.push(...queue.slice(0, userLength));
- return;
- }
- setHydrateContext();
- }
- if (sharedConfig.effects && (sharedConfig.done || !sharedConfig.count)) {
- queue = [...sharedConfig.effects, ...queue];
- userLength += sharedConfig.effects.length;
- delete sharedConfig.effects;
- }
- for (i = 0; i < userLength; i++) runTop(queue[i]);
-}
-function lookUpstream(node, ignore) {
- const runningTransition = Transition && Transition.running;
- if (runningTransition) node.tState = 0;
- else node.state = 0;
- for (let i = 0; i < node.sources.length; i += 1) {
- const source = node.sources[i];
- if (source.sources) {
- const state = runningTransition ? source.tState : source.state;
- if (state === STALE) {
- if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);
- } else if (state === PENDING) lookUpstream(source, ignore);
- }
- }
-}
-function markDownstream(node) {
- const runningTransition = Transition && Transition.running;
- for (let i = 0; i < node.observers.length; i += 1) {
- const o = node.observers[i];
- if (runningTransition ? !o.tState : !o.state) {
- if (runningTransition) o.tState = PENDING;
- else o.state = PENDING;
- if (o.pure) Updates.push(o);
- else Effects.push(o);
- o.observers && markDownstream(o);
- }
- }
-}
-function cleanNode(node) {
- let i;
- if (node.sources) {
- while (node.sources.length) {
- const source = node.sources.pop(), index = node.sourceSlots.pop(), obs = source.observers;
- if (obs && obs.length) {
- const n = obs.pop(), s = source.observerSlots.pop();
- if (index < obs.length) {
- n.sourceSlots[s] = index;
- obs[index] = n;
- source.observerSlots[index] = s;
- }
- }
- }
- }
- if (node.tOwned) {
- for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]);
- delete node.tOwned;
- }
- if (Transition && Transition.running && node.pure) {
- reset(node, true);
- } else if (node.owned) {
- for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]);
- node.owned = null;
- }
- if (node.cleanups) {
- for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i]();
- node.cleanups = null;
- }
- if (Transition && Transition.running) node.tState = 0;
- else node.state = 0;
- delete node.sourceMap;
-}
-function reset(node, top) {
- if (!top) {
- node.tState = 0;
- Transition.disposed.add(node);
- }
- if (node.owned) {
- for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);
- }
-}
-function castError(err) {
- if (err instanceof Error) return err;
- return new Error(typeof err === "string" ? err : "Unknown error", {
- cause: err
- });
-}
-function runErrors(err, fns, owner) {
- try {
- for (const f of fns) f(err);
- } catch (e) {
- handleError(e, owner && owner.owner || null);
- }
-}
-function handleError(err, owner = Owner) {
- const fns = ERROR && owner && owner.context && owner.context[ERROR];
- const error = castError(err);
- if (!fns) throw error;
- if (Effects) Effects.push({
- fn() {
- runErrors(error, fns, owner);
- },
- state: STALE
- });
- else runErrors(error, fns, owner);
-}
-function resolveChildren(children2) {
- if (typeof children2 === "function" && !children2.length) return resolveChildren(children2());
- if (Array.isArray(children2)) {
- const results = [];
- for (let i = 0; i < children2.length; i++) {
- const result = resolveChildren(children2[i]);
- Array.isArray(result) ? results.push.apply(results, result) : results.push(result);
- }
- return results;
- }
- return children2;
-}
-function createProvider(id, options) {
- return function provider(props) {
- let res;
- createRenderEffect(() => res = untrack(() => {
- Owner.context = {
- ...Owner.context,
- [id]: props.value
- };
- return children(() => props.children);
- }), void 0, options);
- return res;
- };
-}
-function onError(fn) {
- ERROR || (ERROR = Symbol("error"));
- if (Owner === null) console.warn("error handlers created outside a `createRoot` or `render` will never be run");
- else if (Owner.context === null || !Owner.context[ERROR]) {
- Owner.context = {
- ...Owner.context,
- [ERROR]: [fn]
- };
- mutateContext(Owner, ERROR, [fn]);
- } else Owner.context[ERROR].push(fn);
-}
-function mutateContext(o, key, value) {
- if (o.owned) {
- for (let i = 0; i < o.owned.length; i++) {
- if (o.owned[i].context === o.context) mutateContext(o.owned[i], key, value);
- if (!o.owned[i].context) {
- o.owned[i].context = o.context;
- mutateContext(o.owned[i], key, value);
- } else if (!o.owned[i].context[key]) {
- o.owned[i].context[key] = value;
- mutateContext(o.owned[i], key, value);
- }
- }
- }
-}
-function observable(input) {
- return {
- subscribe(observer) {
- if (!(observer instanceof Object) || observer == null) {
- throw new TypeError("Expected the observer to be an object.");
- }
- const handler = typeof observer === "function" ? observer : observer.next && observer.next.bind(observer);
- if (!handler) {
- return {
- unsubscribe() {
- }
- };
- }
- const dispose2 = createRoot((disposer) => {
- createEffect(() => {
- const v = input();
- untrack(() => handler(v));
- });
- return disposer;
- });
- if (getOwner()) onCleanup(dispose2);
- return {
- unsubscribe() {
- dispose2();
- }
- };
- },
- [Symbol.observable || "@@observable"]() {
- return this;
- }
- };
-}
-function from(producer, initalValue = void 0) {
- const [s, set] = createSignal(initalValue, {
- equals: false
- });
- if ("subscribe" in producer) {
- const unsub = producer.subscribe((v) => set(() => v));
- onCleanup(() => "unsubscribe" in unsub ? unsub.unsubscribe() : unsub());
- } else {
- const clean = producer(set);
- onCleanup(clean);
- }
- return s;
-}
-var FALLBACK = Symbol("fallback");
-function dispose(d) {
- for (let i = 0; i < d.length; i++) d[i]();
-}
-function mapArray(list, mapFn, options = {}) {
- let items = [], mapped = [], disposers = [], len = 0, indexes = mapFn.length > 1 ? [] : null;
- onCleanup(() => dispose(disposers));
- return () => {
- let newItems = list() || [], newLen = newItems.length, i, j;
- newItems[$TRACK];
- return untrack(() => {
- let newIndices, newIndicesNext, temp, tempdisposers, tempIndexes, start, end, newEnd, item;
- if (newLen === 0) {
- if (len !== 0) {
- dispose(disposers);
- disposers = [];
- items = [];
- mapped = [];
- len = 0;
- indexes && (indexes = []);
- }
- if (options.fallback) {
- items = [FALLBACK];
- mapped[0] = createRoot((disposer) => {
- disposers[0] = disposer;
- return options.fallback();
- });
- len = 1;
- }
- } else if (len === 0) {
- mapped = new Array(newLen);
- for (j = 0; j < newLen; j++) {
- items[j] = newItems[j];
- mapped[j] = createRoot(mapper);
- }
- len = newLen;
- } else {
- temp = new Array(newLen);
- tempdisposers = new Array(newLen);
- indexes && (tempIndexes = new Array(newLen));
- for (start = 0, end = Math.min(len, newLen); start < end && items[start] === newItems[start]; start++) ;
- for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && items[end] === newItems[newEnd]; end--, newEnd--) {
- temp[newEnd] = mapped[end];
- tempdisposers[newEnd] = disposers[end];
- indexes && (tempIndexes[newEnd] = indexes[end]);
- }
- newIndices = /* @__PURE__ */ new Map();
- newIndicesNext = new Array(newEnd + 1);
- for (j = newEnd; j >= start; j--) {
- item = newItems[j];
- i = newIndices.get(item);
- newIndicesNext[j] = i === void 0 ? -1 : i;
- newIndices.set(item, j);
- }
- for (i = start; i <= end; i++) {
- item = items[i];
- j = newIndices.get(item);
- if (j !== void 0 && j !== -1) {
- temp[j] = mapped[i];
- tempdisposers[j] = disposers[i];
- indexes && (tempIndexes[j] = indexes[i]);
- j = newIndicesNext[j];
- newIndices.set(item, j);
- } else disposers[i]();
- }
- for (j = start; j < newLen; j++) {
- if (j in temp) {
- mapped[j] = temp[j];
- disposers[j] = tempdisposers[j];
- if (indexes) {
- indexes[j] = tempIndexes[j];
- indexes[j](j);
- }
- } else mapped[j] = createRoot(mapper);
- }
- mapped = mapped.slice(0, len = newLen);
- items = newItems.slice(0);
- }
- return mapped;
- });
- function mapper(disposer) {
- disposers[j] = disposer;
- if (indexes) {
- const [s, set] = createSignal(j, {
- name: "index"
- });
- indexes[j] = set;
- return mapFn(newItems[j], s);
- }
- return mapFn(newItems[j]);
- }
- };
-}
-function indexArray(list, mapFn, options = {}) {
- let items = [], mapped = [], disposers = [], signals = [], len = 0, i;
- onCleanup(() => dispose(disposers));
- return () => {
- const newItems = list() || [], newLen = newItems.length;
- newItems[$TRACK];
- return untrack(() => {
- if (newLen === 0) {
- if (len !== 0) {
- dispose(disposers);
- disposers = [];
- items = [];
- mapped = [];
- len = 0;
- signals = [];
- }
- if (options.fallback) {
- items = [FALLBACK];
- mapped[0] = createRoot((disposer) => {
- disposers[0] = disposer;
- return options.fallback();
- });
- len = 1;
- }
- return mapped;
- }
- if (items[0] === FALLBACK) {
- disposers[0]();
- disposers = [];
- items = [];
- mapped = [];
- len = 0;
- }
- for (i = 0; i < newLen; i++) {
- if (i < items.length && items[i] !== newItems[i]) {
- signals[i](() => newItems[i]);
- } else if (i >= items.length) {
- mapped[i] = createRoot(mapper);
- }
- }
- for (; i < items.length; i++) {
- disposers[i]();
- }
- len = signals.length = disposers.length = newLen;
- items = newItems.slice(0);
- return mapped = mapped.slice(0, len);
- });
- function mapper(disposer) {
- disposers[i] = disposer;
- const [s, set] = createSignal(newItems[i], {
- name: "value"
- });
- signals[i] = set;
- return mapFn(s, i);
- }
- };
-}
-var hydrationEnabled = false;
-function enableHydration() {
- hydrationEnabled = true;
-}
-function createComponent(Comp, props) {
- if (hydrationEnabled) {
- if (sharedConfig.context) {
- const c = sharedConfig.context;
- setHydrateContext(nextHydrateContext());
- const r = devComponent(Comp, props || {});
- setHydrateContext(c);
- return r;
- }
- }
- return devComponent(Comp, props || {});
-}
-function trueFn() {
- return true;
-}
-var propTraps = {
- get(_, property, receiver) {
- if (property === $PROXY) return receiver;
- return _.get(property);
- },
- has(_, property) {
- if (property === $PROXY) return true;
- return _.has(property);
- },
- set: trueFn,
- deleteProperty: trueFn,
- getOwnPropertyDescriptor(_, property) {
- return {
- configurable: true,
- enumerable: true,
- get() {
- return _.get(property);
- },
- set: trueFn,
- deleteProperty: trueFn
- };
- },
- ownKeys(_) {
- return _.keys();
- }
-};
-function resolveSource(s) {
- return !(s = typeof s === "function" ? s() : s) ? {} : s;
-}
-function resolveSources() {
- for (let i = 0, length = this.length; i < length; ++i) {
- const v = this[i]();
- if (v !== void 0) return v;
- }
-}
-function mergeProps(...sources) {
- let proxy = false;
- for (let i = 0; i < sources.length; i++) {
- const s = sources[i];
- proxy = proxy || !!s && $PROXY in s;
- sources[i] = typeof s === "function" ? (proxy = true, createMemo(s)) : s;
- }
- if (SUPPORTS_PROXY && proxy) {
- return new Proxy({
- get(property) {
- for (let i = sources.length - 1; i >= 0; i--) {
- const v = resolveSource(sources[i])[property];
- if (v !== void 0) return v;
- }
- },
- has(property) {
- for (let i = sources.length - 1; i >= 0; i--) {
- if (property in resolveSource(sources[i])) return true;
- }
- return false;
- },
- keys() {
- const keys = [];
- for (let i = 0; i < sources.length; i++) keys.push(...Object.keys(resolveSource(sources[i])));
- return [...new Set(keys)];
- }
- }, propTraps);
- }
- const sourcesMap = {};
- const defined = /* @__PURE__ */ Object.create(null);
- for (let i = sources.length - 1; i >= 0; i--) {
- const source = sources[i];
- if (!source) continue;
- const sourceKeys = Object.getOwnPropertyNames(source);
- for (let i2 = sourceKeys.length - 1; i2 >= 0; i2--) {
- const key = sourceKeys[i2];
- if (key === "__proto__" || key === "constructor") continue;
- const desc = Object.getOwnPropertyDescriptor(source, key);
- if (!defined[key]) {
- defined[key] = desc.get ? {
- enumerable: true,
- configurable: true,
- get: resolveSources.bind(sourcesMap[key] = [desc.get.bind(source)])
- } : desc.value !== void 0 ? desc : void 0;
- } else {
- const sources2 = sourcesMap[key];
- if (sources2) {
- if (desc.get) sources2.push(desc.get.bind(source));
- else if (desc.value !== void 0) sources2.push(() => desc.value);
- }
- }
- }
- }
- const target = {};
- const definedKeys = Object.keys(defined);
- for (let i = definedKeys.length - 1; i >= 0; i--) {
- const key = definedKeys[i], desc = defined[key];
- if (desc && desc.get) Object.defineProperty(target, key, desc);
- else target[key] = desc ? desc.value : void 0;
- }
- return target;
-}
-function splitProps(props, ...keys) {
- if (SUPPORTS_PROXY && $PROXY in props) {
- const blocked = new Set(keys.length > 1 ? keys.flat() : keys[0]);
- const res = keys.map((k) => {
- return new Proxy({
- get(property) {
- return k.includes(property) ? props[property] : void 0;
- },
- has(property) {
- return k.includes(property) && property in props;
- },
- keys() {
- return k.filter((property) => property in props);
- }
- }, propTraps);
- });
- res.push(new Proxy({
- get(property) {
- return blocked.has(property) ? void 0 : props[property];
- },
- has(property) {
- return blocked.has(property) ? false : property in props;
- },
- keys() {
- return Object.keys(props).filter((k) => !blocked.has(k));
- }
- }, propTraps));
- return res;
- }
- const otherObject = {};
- const objects = keys.map(() => ({}));
- for (const propName of Object.getOwnPropertyNames(props)) {
- const desc = Object.getOwnPropertyDescriptor(props, propName);
- const isDefaultDesc = !desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable;
- let blocked = false;
- let objectIndex = 0;
- for (const k of keys) {
- if (k.includes(propName)) {
- blocked = true;
- isDefaultDesc ? objects[objectIndex][propName] = desc.value : Object.defineProperty(objects[objectIndex], propName, desc);
- }
- ++objectIndex;
- }
- if (!blocked) {
- isDefaultDesc ? otherObject[propName] = desc.value : Object.defineProperty(otherObject, propName, desc);
- }
- }
- return [...objects, otherObject];
-}
-function lazy(fn) {
- let comp;
- let p;
- const wrap = (props) => {
- const ctx = sharedConfig.context;
- if (ctx) {
- const [s, set] = createSignal();
- sharedConfig.count || (sharedConfig.count = 0);
- sharedConfig.count++;
- (p || (p = fn())).then((mod) => {
- !sharedConfig.done && setHydrateContext(ctx);
- sharedConfig.count--;
- set(() => mod.default);
- setHydrateContext();
- });
- comp = s;
- } else if (!comp) {
- const [s] = createResource(() => (p || (p = fn())).then((mod) => mod.default));
- comp = s;
- }
- let Comp;
- return createMemo(() => (Comp = comp()) ? untrack(() => {
- if (IS_DEV) Object.assign(Comp, {
- [$DEVCOMP]: true
- });
- if (!ctx || sharedConfig.done) return Comp(props);
- const c = sharedConfig.context;
- setHydrateContext(ctx);
- const r = Comp(props);
- setHydrateContext(c);
- return r;
- }) : "");
- };
- wrap.preload = () => p || ((p = fn()).then((mod) => comp = () => mod.default), p);
- return wrap;
-}
-var counter = 0;
-function createUniqueId() {
- const ctx = sharedConfig.context;
- return ctx ? sharedConfig.getNextContextId() : `cl-${counter++}`;
-}
-var narrowedError = (name) => `Attempting to access a stale value from <${name}> that could possibly be undefined. This may occur because you are reading the accessor returned from the component at a time where it has already been unmounted. We recommend cleaning up any stale timers or async, or reading from the initial condition.`;
-function For(props) {
- const fallback = "fallback" in props && {
- fallback: () => props.fallback
- };
- return createMemo(mapArray(() => props.each, props.children, fallback || void 0), void 0, {
- name: "value"
- });
-}
-function Index(props) {
- const fallback = "fallback" in props && {
- fallback: () => props.fallback
- };
- return createMemo(indexArray(() => props.each, props.children, fallback || void 0), void 0, {
- name: "value"
- });
-}
-function Show(props) {
- const keyed = props.keyed;
- const conditionValue = createMemo(() => props.when, void 0, {
- name: "condition value"
- });
- const condition = keyed ? conditionValue : createMemo(conditionValue, void 0, {
- equals: (a, b) => !a === !b,
- name: "condition"
- });
- return createMemo(() => {
- const c = condition();
- if (c) {
- const child = props.children;
- const fn = typeof child === "function" && child.length > 0;
- return fn ? untrack(() => child(keyed ? c : () => {
- if (!untrack(condition)) throw narrowedError("Show");
- return conditionValue();
- })) : child;
- }
- return props.fallback;
- }, void 0, {
- name: "value"
- });
-}
-function Switch(props) {
- const chs = children(() => props.children);
- const switchFunc = createMemo(() => {
- const ch = chs();
- const mps = Array.isArray(ch) ? ch : [ch];
- let func = () => void 0;
- for (let i = 0; i < mps.length; i++) {
- const index = i;
- const mp = mps[i];
- const prevFunc = func;
- const conditionValue = createMemo(() => prevFunc() ? void 0 : mp.when, void 0, {
- name: "condition value"
- });
- const condition = mp.keyed ? conditionValue : createMemo(conditionValue, void 0, {
- equals: (a, b) => !a === !b,
- name: "condition"
- });
- func = () => prevFunc() || (condition() ? [index, conditionValue, mp] : void 0);
- }
- return func;
- });
- return createMemo(() => {
- const sel = switchFunc()();
- if (!sel) return props.fallback;
- const [index, conditionValue, mp] = sel;
- const child = mp.children;
- const fn = typeof child === "function" && child.length > 0;
- return fn ? untrack(() => child(mp.keyed ? conditionValue() : () => {
- var _a;
- if (((_a = untrack(switchFunc)()) == null ? void 0 : _a[0]) !== index) throw narrowedError("Match");
- return conditionValue();
- })) : child;
- }, void 0, {
- name: "eval conditions"
- });
-}
-function Match(props) {
- return props;
-}
-var Errors;
-function resetErrorBoundaries() {
- Errors && [...Errors].forEach((fn) => fn());
-}
-function ErrorBoundary(props) {
- let err;
- if (sharedConfig.context && sharedConfig.load) err = sharedConfig.load(sharedConfig.getContextId());
- const [errored, setErrored] = createSignal(err, {
- name: "errored"
- });
- Errors || (Errors = /* @__PURE__ */ new Set());
- Errors.add(setErrored);
- onCleanup(() => Errors.delete(setErrored));
- return createMemo(() => {
- let e;
- if (e = errored()) {
- const f = props.fallback;
- if (typeof f !== "function" || f.length == 0) console.error(e);
- return typeof f === "function" && f.length ? untrack(() => f(e, () => setErrored())) : f;
- }
- return catchError(() => props.children, setErrored);
- }, void 0, {
- name: "value"
- });
-}
-var suspenseListEquals = (a, b) => a.showContent === b.showContent && a.showFallback === b.showFallback;
-var SuspenseListContext = createContext();
-function SuspenseList(props) {
- let [wrapper, setWrapper] = createSignal(() => ({
- inFallback: false
- })), show;
- const listContext = useContext(SuspenseListContext);
- const [registry, setRegistry] = createSignal([]);
- if (listContext) {
- show = listContext.register(createMemo(() => wrapper()().inFallback));
- }
- const resolved = createMemo((prev) => {
- const reveal = props.revealOrder, tail = props.tail, {
- showContent = true,
- showFallback = true
- } = show ? show() : {}, reg = registry(), reverse = reveal === "backwards";
- if (reveal === "together") {
- const all = reg.every((inFallback2) => !inFallback2());
- const res2 = reg.map(() => ({
- showContent: all && showContent,
- showFallback
- }));
- res2.inFallback = !all;
- return res2;
- }
- let stop = false;
- let inFallback = prev.inFallback;
- const res = [];
- for (let i = 0, len = reg.length; i < len; i++) {
- const n = reverse ? len - i - 1 : i, s = reg[n]();
- if (!stop && !s) {
- res[n] = {
- showContent,
- showFallback
- };
- } else {
- const next = !stop;
- if (next) inFallback = true;
- res[n] = {
- showContent: next,
- showFallback: !tail || next && tail === "collapsed" ? showFallback : false
- };
- stop = true;
- }
- }
- if (!stop) inFallback = false;
- res.inFallback = inFallback;
- return res;
- }, {
- inFallback: false
- });
- setWrapper(() => resolved);
- return createComponent(SuspenseListContext.Provider, {
- value: {
- register: (inFallback) => {
- let index;
- setRegistry((registry2) => {
- index = registry2.length;
- return [...registry2, inFallback];
- });
- return createMemo(() => resolved()[index], void 0, {
- equals: suspenseListEquals
- });
- }
- },
- get children() {
- return props.children;
- }
- });
-}
-function Suspense(props) {
- let counter2 = 0, show, ctx, p, flicker, error;
- const [inFallback, setFallback] = createSignal(false), SuspenseContext2 = getSuspenseContext(), store = {
- increment: () => {
- if (++counter2 === 1) setFallback(true);
- },
- decrement: () => {
- if (--counter2 === 0) setFallback(false);
- },
- inFallback,
- effects: [],
- resolved: false
- }, owner = getOwner();
- if (sharedConfig.context && sharedConfig.load) {
- const key = sharedConfig.getContextId();
- let ref = sharedConfig.load(key);
- if (ref) {
- if (typeof ref !== "object" || ref.s !== 1) p = ref;
- else sharedConfig.gather(key);
- }
- if (p && p !== "$$f") {
- const [s, set] = createSignal(void 0, {
- equals: false
- });
- flicker = s;
- p.then(() => {
- if (sharedConfig.done) return set();
- sharedConfig.gather(key);
- setHydrateContext(ctx);
- set();
- setHydrateContext();
- }, (err) => {
- error = err;
- set();
- });
- }
- }
- const listContext = useContext(SuspenseListContext);
- if (listContext) show = listContext.register(store.inFallback);
- let dispose2;
- onCleanup(() => dispose2 && dispose2());
- return createComponent(SuspenseContext2.Provider, {
- value: store,
- get children() {
- return createMemo(() => {
- if (error) throw error;
- ctx = sharedConfig.context;
- if (flicker) {
- flicker();
- return flicker = void 0;
- }
- if (ctx && p === "$$f") setHydrateContext();
- const rendered = createMemo(() => props.children);
- return createMemo((prev) => {
- const inFallback2 = store.inFallback(), {
- showContent = true,
- showFallback = true
- } = show ? show() : {};
- if ((!inFallback2 || p && p !== "$$f") && showContent) {
- store.resolved = true;
- dispose2 && dispose2();
- dispose2 = ctx = p = void 0;
- resumeEffects(store.effects);
- return rendered();
- }
- if (!showFallback) return;
- if (dispose2) return prev;
- return createRoot((disposer) => {
- dispose2 = disposer;
- if (ctx) {
- setHydrateContext({
- id: ctx.id + "F",
- count: 0
- });
- ctx = void 0;
- }
- return props.fallback;
- }, owner);
- });
- });
- }
- });
-}
-var DEV = {
- hooks: DevHooks,
- writeSignal,
- registerGraph
-};
-if (globalThis) {
- if (!globalThis.Solid$$) globalThis.Solid$$ = true;
- else console.warn("You appear to have multiple instances of Solid. This can lead to unexpected behavior.");
-}
-
-export {
- requestCallback,
- cancelCallback,
- sharedConfig,
- equalFn,
- $PROXY,
- $TRACK,
- $DEVCOMP,
- createRoot,
- createSignal,
- createComputed,
- createRenderEffect,
- createEffect,
- createReaction,
- createMemo,
- createResource,
- createDeferred,
- createSelector,
- batch,
- untrack,
- on,
- onMount,
- onCleanup,
- catchError,
- getListener,
- getOwner,
- runWithOwner,
- enableScheduling,
- startTransition,
- useTransition,
- createContext,
- useContext,
- children,
- enableExternalSource,
- onError,
- observable,
- from,
- mapArray,
- indexArray,
- enableHydration,
- createComponent,
- mergeProps,
- splitProps,
- lazy,
- createUniqueId,
- For,
- Index,
- Show,
- Switch,
- Match,
- resetErrorBoundaries,
- ErrorBoundary,
- SuspenseList,
- Suspense,
- DEV
-};
-//# sourceMappingURL=chunk-IZS3CG5R.js.map
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/chunk-IZS3CG5R.js.map b/pulse-test-staging/frontend-modern/.vite/deps/chunk-IZS3CG5R.js.map
deleted file mode 100644
index 6dc08dfb3..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/chunk-IZS3CG5R.js.map
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": 3,
- "sources": ["../../node_modules/solid-js/dist/dev.js"],
- "sourcesContent": ["let taskIdCounter = 1,\n isCallbackScheduled = false,\n isPerformingWork = false,\n taskQueue = [],\n currentTask = null,\n shouldYieldToHost = null,\n yieldInterval = 5,\n deadline = 0,\n maxYieldInterval = 300,\n scheduleCallback = null,\n scheduledCallback = null;\nconst maxSigned31BitInt = 1073741823;\nfunction setupScheduler() {\n const channel = new MessageChannel(),\n port = channel.port2;\n scheduleCallback = () => port.postMessage(null);\n channel.port1.onmessage = () => {\n if (scheduledCallback !== null) {\n const currentTime = performance.now();\n deadline = currentTime + yieldInterval;\n const hasTimeRemaining = true;\n try {\n const hasMoreWork = scheduledCallback(hasTimeRemaining, currentTime);\n if (!hasMoreWork) {\n scheduledCallback = null;\n } else port.postMessage(null);\n } catch (error) {\n port.postMessage(null);\n throw error;\n }\n }\n };\n if (navigator && navigator.scheduling && navigator.scheduling.isInputPending) {\n const scheduling = navigator.scheduling;\n shouldYieldToHost = () => {\n const currentTime = performance.now();\n if (currentTime >= deadline) {\n if (scheduling.isInputPending()) {\n return true;\n }\n return currentTime >= maxYieldInterval;\n } else {\n return false;\n }\n };\n } else {\n shouldYieldToHost = () => performance.now() >= deadline;\n }\n}\nfunction enqueue(taskQueue, task) {\n function findIndex() {\n let m = 0;\n let n = taskQueue.length - 1;\n while (m <= n) {\n const k = n + m >> 1;\n const cmp = task.expirationTime - taskQueue[k].expirationTime;\n if (cmp > 0) m = k + 1;else if (cmp < 0) n = k - 1;else return k;\n }\n return m;\n }\n taskQueue.splice(findIndex(), 0, task);\n}\nfunction requestCallback(fn, options) {\n if (!scheduleCallback) setupScheduler();\n let startTime = performance.now(),\n timeout = maxSigned31BitInt;\n if (options && options.timeout) timeout = options.timeout;\n const newTask = {\n id: taskIdCounter++,\n fn,\n startTime,\n expirationTime: startTime + timeout\n };\n enqueue(taskQueue, newTask);\n if (!isCallbackScheduled && !isPerformingWork) {\n isCallbackScheduled = true;\n scheduledCallback = flushWork;\n scheduleCallback();\n }\n return newTask;\n}\nfunction cancelCallback(task) {\n task.fn = null;\n}\nfunction flushWork(hasTimeRemaining, initialTime) {\n isCallbackScheduled = false;\n isPerformingWork = true;\n try {\n return workLoop(hasTimeRemaining, initialTime);\n } finally {\n currentTask = null;\n isPerformingWork = false;\n }\n}\nfunction workLoop(hasTimeRemaining, initialTime) {\n let currentTime = initialTime;\n currentTask = taskQueue[0] || null;\n while (currentTask !== null) {\n if (currentTask.expirationTime > currentTime && (!hasTimeRemaining || shouldYieldToHost())) {\n break;\n }\n const callback = currentTask.fn;\n if (callback !== null) {\n currentTask.fn = null;\n const didUserCallbackTimeout = currentTask.expirationTime <= currentTime;\n callback(didUserCallbackTimeout);\n currentTime = performance.now();\n if (currentTask === taskQueue[0]) {\n taskQueue.shift();\n }\n } else taskQueue.shift();\n currentTask = taskQueue[0] || null;\n }\n return currentTask !== null;\n}\n\nconst sharedConfig = {\n context: undefined,\n registry: undefined,\n effects: undefined,\n done: false,\n getContextId() {\n return getContextId(this.context.count);\n },\n getNextContextId() {\n return getContextId(this.context.count++);\n }\n};\nfunction getContextId(count) {\n const num = String(count),\n len = num.length - 1;\n return sharedConfig.context.id + (len ? String.fromCharCode(96 + len) : \"\") + num;\n}\nfunction setHydrateContext(context) {\n sharedConfig.context = context;\n}\nfunction nextHydrateContext() {\n return {\n ...sharedConfig.context,\n id: sharedConfig.getNextContextId(),\n count: 0\n };\n}\n\nconst IS_DEV = true;\nconst equalFn = (a, b) => a === b;\nconst $PROXY = Symbol(\"solid-proxy\");\nconst SUPPORTS_PROXY = typeof Proxy === \"function\";\nconst $TRACK = Symbol(\"solid-track\");\nconst $DEVCOMP = Symbol(\"solid-dev-component\");\nconst signalOptions = {\n equals: equalFn\n};\nlet ERROR = null;\nlet runEffects = runQueue;\nconst STALE = 1;\nconst PENDING = 2;\nconst UNOWNED = {\n owned: null,\n cleanups: null,\n context: null,\n owner: null\n};\nconst NO_INIT = {};\nvar Owner = null;\nlet Transition = null;\nlet Scheduler = null;\nlet ExternalSourceConfig = null;\nlet Listener = null;\nlet Updates = null;\nlet Effects = null;\nlet ExecCount = 0;\nconst DevHooks = {\n afterUpdate: null,\n afterCreateOwner: null,\n afterCreateSignal: null,\n afterRegisterGraph: null\n};\nfunction createRoot(fn, detachedOwner) {\n const listener = Listener,\n owner = Owner,\n unowned = fn.length === 0,\n current = detachedOwner === undefined ? owner : detachedOwner,\n root = unowned ? {\n owned: null,\n cleanups: null,\n context: null,\n owner: null\n } : {\n owned: null,\n cleanups: null,\n context: current ? current.context : null,\n owner: current\n },\n updateFn = unowned ? () => fn(() => {\n throw new Error(\"Dispose method must be an explicit argument to createRoot function\");\n }) : () => fn(() => untrack(() => cleanNode(root)));\n DevHooks.afterCreateOwner && DevHooks.afterCreateOwner(root);\n Owner = root;\n Listener = null;\n try {\n return runUpdates(updateFn, true);\n } finally {\n Listener = listener;\n Owner = owner;\n }\n}\nfunction createSignal(value, options) {\n options = options ? Object.assign({}, signalOptions, options) : signalOptions;\n const s = {\n value,\n observers: null,\n observerSlots: null,\n comparator: options.equals || undefined\n };\n {\n if (options.name) s.name = options.name;\n if (options.internal) {\n s.internal = true;\n } else {\n registerGraph(s);\n if (DevHooks.afterCreateSignal) DevHooks.afterCreateSignal(s);\n }\n }\n const setter = value => {\n if (typeof value === \"function\") {\n if (Transition && Transition.running && Transition.sources.has(s)) value = value(s.tValue);else value = value(s.value);\n }\n return writeSignal(s, value);\n };\n return [readSignal.bind(s), setter];\n}\nfunction createComputed(fn, value, options) {\n const c = createComputation(fn, value, true, STALE, options );\n if (Scheduler && Transition && Transition.running) Updates.push(c);else updateComputation(c);\n}\nfunction createRenderEffect(fn, value, options) {\n const c = createComputation(fn, value, false, STALE, options );\n if (Scheduler && Transition && Transition.running) Updates.push(c);else updateComputation(c);\n}\nfunction createEffect(fn, value, options) {\n runEffects = runUserEffects;\n const c = createComputation(fn, value, false, STALE, options ),\n s = SuspenseContext && useContext(SuspenseContext);\n if (s) c.suspense = s;\n if (!options || !options.render) c.user = true;\n Effects ? Effects.push(c) : updateComputation(c);\n}\nfunction createReaction(onInvalidate, options) {\n let fn;\n const c = createComputation(() => {\n fn ? fn() : untrack(onInvalidate);\n fn = undefined;\n }, undefined, false, 0, options ),\n s = SuspenseContext && useContext(SuspenseContext);\n if (s) c.suspense = s;\n c.user = true;\n return tracking => {\n fn = tracking;\n updateComputation(c);\n };\n}\nfunction createMemo(fn, value, options) {\n options = options ? Object.assign({}, signalOptions, options) : signalOptions;\n const c = createComputation(fn, value, true, 0, options );\n c.observers = null;\n c.observerSlots = null;\n c.comparator = options.equals || undefined;\n if (Scheduler && Transition && Transition.running) {\n c.tState = STALE;\n Updates.push(c);\n } else updateComputation(c);\n return readSignal.bind(c);\n}\nfunction isPromise(v) {\n return v && typeof v === \"object\" && \"then\" in v;\n}\nfunction createResource(pSource, pFetcher, pOptions) {\n let source;\n let fetcher;\n let options;\n if (typeof pFetcher === \"function\") {\n source = pSource;\n fetcher = pFetcher;\n options = pOptions || {};\n } else {\n source = true;\n fetcher = pSource;\n options = pFetcher || {};\n }\n let pr = null,\n initP = NO_INIT,\n id = null,\n loadedUnderTransition = false,\n scheduled = false,\n resolved = \"initialValue\" in options,\n dynamic = typeof source === \"function\" && createMemo(source);\n const contexts = new Set(),\n [value, setValue] = (options.storage || createSignal)(options.initialValue),\n [error, setError] = createSignal(undefined),\n [track, trigger] = createSignal(undefined, {\n equals: false\n }),\n [state, setState] = createSignal(resolved ? \"ready\" : \"unresolved\");\n if (sharedConfig.context) {\n id = sharedConfig.getNextContextId();\n if (options.ssrLoadFrom === \"initial\") initP = options.initialValue;else if (sharedConfig.load && sharedConfig.has(id)) initP = sharedConfig.load(id);\n }\n function loadEnd(p, v, error, key) {\n if (pr === p) {\n pr = null;\n key !== undefined && (resolved = true);\n if ((p === initP || v === initP) && options.onHydrated) queueMicrotask(() => options.onHydrated(key, {\n value: v\n }));\n initP = NO_INIT;\n if (Transition && p && loadedUnderTransition) {\n Transition.promises.delete(p);\n loadedUnderTransition = false;\n runUpdates(() => {\n Transition.running = true;\n completeLoad(v, error);\n }, false);\n } else completeLoad(v, error);\n }\n return v;\n }\n function completeLoad(v, err) {\n runUpdates(() => {\n if (err === undefined) setValue(() => v);\n setState(err !== undefined ? \"errored\" : resolved ? \"ready\" : \"unresolved\");\n setError(err);\n for (const c of contexts.keys()) c.decrement();\n contexts.clear();\n }, false);\n }\n function read() {\n const c = SuspenseContext && useContext(SuspenseContext),\n v = value(),\n err = error();\n if (err !== undefined && !pr) throw err;\n if (Listener && !Listener.user && c) {\n createComputed(() => {\n track();\n if (pr) {\n if (c.resolved && Transition && loadedUnderTransition) Transition.promises.add(pr);else if (!contexts.has(c)) {\n c.increment();\n contexts.add(c);\n }\n }\n });\n }\n return v;\n }\n function load(refetching = true) {\n if (refetching !== false && scheduled) return;\n scheduled = false;\n const lookup = dynamic ? dynamic() : source;\n loadedUnderTransition = Transition && Transition.running;\n if (lookup == null || lookup === false) {\n loadEnd(pr, untrack(value));\n return;\n }\n if (Transition && pr) Transition.promises.delete(pr);\n let error;\n const p = initP !== NO_INIT ? initP : untrack(() => {\n try {\n return fetcher(lookup, {\n value: value(),\n refetching\n });\n } catch (fetcherError) {\n error = fetcherError;\n }\n });\n if (error !== undefined) {\n loadEnd(pr, undefined, castError(error), lookup);\n return;\n } else if (!isPromise(p)) {\n loadEnd(pr, p, undefined, lookup);\n return p;\n }\n pr = p;\n if (\"v\" in p) {\n if (p.s === 1) loadEnd(pr, p.v, undefined, lookup);else loadEnd(pr, undefined, castError(p.v), lookup);\n return p;\n }\n scheduled = true;\n queueMicrotask(() => scheduled = false);\n runUpdates(() => {\n setState(resolved ? \"refreshing\" : \"pending\");\n trigger();\n }, false);\n return p.then(v => loadEnd(p, v, undefined, lookup), e => loadEnd(p, undefined, castError(e), lookup));\n }\n Object.defineProperties(read, {\n state: {\n get: () => state()\n },\n error: {\n get: () => error()\n },\n loading: {\n get() {\n const s = state();\n return s === \"pending\" || s === \"refreshing\";\n }\n },\n latest: {\n get() {\n if (!resolved) return read();\n const err = error();\n if (err && !pr) throw err;\n return value();\n }\n }\n });\n let owner = Owner;\n if (dynamic) createComputed(() => (owner = Owner, load(false)));else load(false);\n return [read, {\n refetch: info => runWithOwner(owner, () => load(info)),\n mutate: setValue\n }];\n}\nfunction createDeferred(source, options) {\n let t,\n timeout = options ? options.timeoutMs : undefined;\n const node = createComputation(() => {\n if (!t || !t.fn) t = requestCallback(() => setDeferred(() => node.value), timeout !== undefined ? {\n timeout\n } : undefined);\n return source();\n }, undefined, true);\n const [deferred, setDeferred] = createSignal(Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value, options);\n updateComputation(node);\n setDeferred(() => Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);\n return deferred;\n}\nfunction createSelector(source, fn = equalFn, options) {\n const subs = new Map();\n const node = createComputation(p => {\n const v = source();\n for (const [key, val] of subs.entries()) if (fn(key, v) !== fn(key, p)) {\n for (const c of val.values()) {\n c.state = STALE;\n if (c.pure) Updates.push(c);else Effects.push(c);\n }\n }\n return v;\n }, undefined, true, STALE, options );\n updateComputation(node);\n return key => {\n const listener = Listener;\n if (listener) {\n let l;\n if (l = subs.get(key)) l.add(listener);else subs.set(key, l = new Set([listener]));\n onCleanup(() => {\n l.delete(listener);\n !l.size && subs.delete(key);\n });\n }\n return fn(key, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value);\n };\n}\nfunction batch(fn) {\n return runUpdates(fn, false);\n}\nfunction untrack(fn) {\n if (!ExternalSourceConfig && Listener === null) return fn();\n const listener = Listener;\n Listener = null;\n try {\n if (ExternalSourceConfig) return ExternalSourceConfig.untrack(fn);\n return fn();\n } finally {\n Listener = listener;\n }\n}\nfunction on(deps, fn, options) {\n const isArray = Array.isArray(deps);\n let prevInput;\n let defer = options && options.defer;\n return prevValue => {\n let input;\n if (isArray) {\n input = Array(deps.length);\n for (let i = 0; i < deps.length; i++) input[i] = deps[i]();\n } else input = deps();\n if (defer) {\n defer = false;\n return prevValue;\n }\n const result = untrack(() => fn(input, prevInput, prevValue));\n prevInput = input;\n return result;\n };\n}\nfunction onMount(fn) {\n createEffect(() => untrack(fn));\n}\nfunction onCleanup(fn) {\n if (Owner === null) console.warn(\"cleanups created outside a `createRoot` or `render` will never be run\");else if (Owner.cleanups === null) Owner.cleanups = [fn];else Owner.cleanups.push(fn);\n return fn;\n}\nfunction catchError(fn, handler) {\n ERROR || (ERROR = Symbol(\"error\"));\n Owner = createComputation(undefined, undefined, true);\n Owner.context = {\n ...Owner.context,\n [ERROR]: [handler]\n };\n if (Transition && Transition.running) Transition.sources.add(Owner);\n try {\n return fn();\n } catch (err) {\n handleError(err);\n } finally {\n Owner = Owner.owner;\n }\n}\nfunction getListener() {\n return Listener;\n}\nfunction getOwner() {\n return Owner;\n}\nfunction runWithOwner(o, fn) {\n const prev = Owner;\n const prevListener = Listener;\n Owner = o;\n Listener = null;\n try {\n return runUpdates(fn, true);\n } catch (err) {\n handleError(err);\n } finally {\n Owner = prev;\n Listener = prevListener;\n }\n}\nfunction enableScheduling(scheduler = requestCallback) {\n Scheduler = scheduler;\n}\nfunction startTransition(fn) {\n if (Transition && Transition.running) {\n fn();\n return Transition.done;\n }\n const l = Listener;\n const o = Owner;\n return Promise.resolve().then(() => {\n Listener = l;\n Owner = o;\n let t;\n if (Scheduler || SuspenseContext) {\n t = Transition || (Transition = {\n sources: new Set(),\n effects: [],\n promises: new Set(),\n disposed: new Set(),\n queue: new Set(),\n running: true\n });\n t.done || (t.done = new Promise(res => t.resolve = res));\n t.running = true;\n }\n runUpdates(fn, false);\n Listener = Owner = null;\n return t ? t.done : undefined;\n });\n}\nconst [transPending, setTransPending] = /*@__PURE__*/createSignal(false);\nfunction useTransition() {\n return [transPending, startTransition];\n}\nfunction resumeEffects(e) {\n Effects.push.apply(Effects, e);\n e.length = 0;\n}\nfunction devComponent(Comp, props) {\n const c = createComputation(() => untrack(() => {\n Object.assign(Comp, {\n [$DEVCOMP]: true\n });\n return Comp(props);\n }), undefined, true, 0);\n c.props = props;\n c.observers = null;\n c.observerSlots = null;\n c.name = Comp.name;\n c.component = Comp;\n updateComputation(c);\n return c.tValue !== undefined ? c.tValue : c.value;\n}\nfunction registerGraph(value) {\n if (Owner) {\n if (Owner.sourceMap) Owner.sourceMap.push(value);else Owner.sourceMap = [value];\n value.graph = Owner;\n }\n if (DevHooks.afterRegisterGraph) DevHooks.afterRegisterGraph(value);\n}\nfunction createContext(defaultValue, options) {\n const id = Symbol(\"context\");\n return {\n id,\n Provider: createProvider(id, options),\n defaultValue\n };\n}\nfunction useContext(context) {\n let value;\n return Owner && Owner.context && (value = Owner.context[context.id]) !== undefined ? value : context.defaultValue;\n}\nfunction children(fn) {\n const children = createMemo(fn);\n const memo = createMemo(() => resolveChildren(children()), undefined, {\n name: \"children\"\n }) ;\n memo.toArray = () => {\n const c = memo();\n return Array.isArray(c) ? c : c != null ? [c] : [];\n };\n return memo;\n}\nlet SuspenseContext;\nfunction getSuspenseContext() {\n return SuspenseContext || (SuspenseContext = createContext());\n}\nfunction enableExternalSource(factory, untrack = fn => fn()) {\n if (ExternalSourceConfig) {\n const {\n factory: oldFactory,\n untrack: oldUntrack\n } = ExternalSourceConfig;\n ExternalSourceConfig = {\n factory: (fn, trigger) => {\n const oldSource = oldFactory(fn, trigger);\n const source = factory(x => oldSource.track(x), trigger);\n return {\n track: x => source.track(x),\n dispose() {\n source.dispose();\n oldSource.dispose();\n }\n };\n },\n untrack: fn => oldUntrack(() => untrack(fn))\n };\n } else {\n ExternalSourceConfig = {\n factory,\n untrack\n };\n }\n}\nfunction readSignal() {\n const runningTransition = Transition && Transition.running;\n if (this.sources && (runningTransition ? this.tState : this.state)) {\n if ((runningTransition ? this.tState : this.state) === STALE) updateComputation(this);else {\n const updates = Updates;\n Updates = null;\n runUpdates(() => lookUpstream(this), false);\n Updates = updates;\n }\n }\n if (Listener) {\n const sSlot = this.observers ? this.observers.length : 0;\n if (!Listener.sources) {\n Listener.sources = [this];\n Listener.sourceSlots = [sSlot];\n } else {\n Listener.sources.push(this);\n Listener.sourceSlots.push(sSlot);\n }\n if (!this.observers) {\n this.observers = [Listener];\n this.observerSlots = [Listener.sources.length - 1];\n } else {\n this.observers.push(Listener);\n this.observerSlots.push(Listener.sources.length - 1);\n }\n }\n if (runningTransition && Transition.sources.has(this)) return this.tValue;\n return this.value;\n}\nfunction writeSignal(node, value, isComp) {\n let current = Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value;\n if (!node.comparator || !node.comparator(current, value)) {\n if (Transition) {\n const TransitionRunning = Transition.running;\n if (TransitionRunning || !isComp && Transition.sources.has(node)) {\n Transition.sources.add(node);\n node.tValue = value;\n }\n if (!TransitionRunning) node.value = value;\n } else node.value = value;\n if (node.observers && node.observers.length) {\n runUpdates(() => {\n for (let i = 0; i < node.observers.length; i += 1) {\n const o = node.observers[i];\n const TransitionRunning = Transition && Transition.running;\n if (TransitionRunning && Transition.disposed.has(o)) continue;\n if (TransitionRunning ? !o.tState : !o.state) {\n if (o.pure) Updates.push(o);else Effects.push(o);\n if (o.observers) markDownstream(o);\n }\n if (!TransitionRunning) o.state = STALE;else o.tState = STALE;\n }\n if (Updates.length > 10e5) {\n Updates = [];\n if (IS_DEV) throw new Error(\"Potential Infinite Loop Detected.\");\n throw new Error();\n }\n }, false);\n }\n }\n return value;\n}\nfunction updateComputation(node) {\n if (!node.fn) return;\n cleanNode(node);\n const time = ExecCount;\n runComputation(node, Transition && Transition.running && Transition.sources.has(node) ? node.tValue : node.value, time);\n if (Transition && !Transition.running && Transition.sources.has(node)) {\n queueMicrotask(() => {\n runUpdates(() => {\n Transition && (Transition.running = true);\n Listener = Owner = node;\n runComputation(node, node.tValue, time);\n Listener = Owner = null;\n }, false);\n });\n }\n}\nfunction runComputation(node, value, time) {\n let nextValue;\n const owner = Owner,\n listener = Listener;\n Listener = Owner = node;\n try {\n nextValue = node.fn(value);\n } catch (err) {\n if (node.pure) {\n if (Transition && Transition.running) {\n node.tState = STALE;\n node.tOwned && node.tOwned.forEach(cleanNode);\n node.tOwned = undefined;\n } else {\n node.state = STALE;\n node.owned && node.owned.forEach(cleanNode);\n node.owned = null;\n }\n }\n node.updatedAt = time + 1;\n return handleError(err);\n } finally {\n Listener = listener;\n Owner = owner;\n }\n if (!node.updatedAt || node.updatedAt <= time) {\n if (node.updatedAt != null && \"observers\" in node) {\n writeSignal(node, nextValue, true);\n } else if (Transition && Transition.running && node.pure) {\n Transition.sources.add(node);\n node.tValue = nextValue;\n } else node.value = nextValue;\n node.updatedAt = time;\n }\n}\nfunction createComputation(fn, init, pure, state = STALE, options) {\n const c = {\n fn,\n state: state,\n updatedAt: null,\n owned: null,\n sources: null,\n sourceSlots: null,\n cleanups: null,\n value: init,\n owner: Owner,\n context: Owner ? Owner.context : null,\n pure\n };\n if (Transition && Transition.running) {\n c.state = 0;\n c.tState = state;\n }\n if (Owner === null) console.warn(\"computations created outside a `createRoot` or `render` will never be disposed\");else if (Owner !== UNOWNED) {\n if (Transition && Transition.running && Owner.pure) {\n if (!Owner.tOwned) Owner.tOwned = [c];else Owner.tOwned.push(c);\n } else {\n if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c);\n }\n }\n if (options && options.name) c.name = options.name;\n if (ExternalSourceConfig && c.fn) {\n const [track, trigger] = createSignal(undefined, {\n equals: false\n });\n const ordinary = ExternalSourceConfig.factory(c.fn, trigger);\n onCleanup(() => ordinary.dispose());\n const triggerInTransition = () => startTransition(trigger).then(() => inTransition.dispose());\n const inTransition = ExternalSourceConfig.factory(c.fn, triggerInTransition);\n c.fn = x => {\n track();\n return Transition && Transition.running ? inTransition.track(x) : ordinary.track(x);\n };\n }\n DevHooks.afterCreateOwner && DevHooks.afterCreateOwner(c);\n return c;\n}\nfunction runTop(node) {\n const runningTransition = Transition && Transition.running;\n if ((runningTransition ? node.tState : node.state) === 0) return;\n if ((runningTransition ? node.tState : node.state) === PENDING) return lookUpstream(node);\n if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node);\n const ancestors = [node];\n while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {\n if (runningTransition && Transition.disposed.has(node)) return;\n if (runningTransition ? node.tState : node.state) ancestors.push(node);\n }\n for (let i = ancestors.length - 1; i >= 0; i--) {\n node = ancestors[i];\n if (runningTransition) {\n let top = node,\n prev = ancestors[i + 1];\n while ((top = top.owner) && top !== prev) {\n if (Transition.disposed.has(top)) return;\n }\n }\n if ((runningTransition ? node.tState : node.state) === STALE) {\n updateComputation(node);\n } else if ((runningTransition ? node.tState : node.state) === PENDING) {\n const updates = Updates;\n Updates = null;\n runUpdates(() => lookUpstream(node, ancestors[0]), false);\n Updates = updates;\n }\n }\n}\nfunction runUpdates(fn, init) {\n if (Updates) return fn();\n let wait = false;\n if (!init) Updates = [];\n if (Effects) wait = true;else Effects = [];\n ExecCount++;\n try {\n const res = fn();\n completeUpdates(wait);\n return res;\n } catch (err) {\n if (!wait) Effects = null;\n Updates = null;\n handleError(err);\n }\n}\nfunction completeUpdates(wait) {\n if (Updates) {\n if (Scheduler && Transition && Transition.running) scheduleQueue(Updates);else runQueue(Updates);\n Updates = null;\n }\n if (wait) return;\n let res;\n if (Transition) {\n if (!Transition.promises.size && !Transition.queue.size) {\n const sources = Transition.sources;\n const disposed = Transition.disposed;\n Effects.push.apply(Effects, Transition.effects);\n res = Transition.resolve;\n for (const e of Effects) {\n \"tState\" in e && (e.state = e.tState);\n delete e.tState;\n }\n Transition = null;\n runUpdates(() => {\n for (const d of disposed) cleanNode(d);\n for (const v of sources) {\n v.value = v.tValue;\n if (v.owned) {\n for (let i = 0, len = v.owned.length; i < len; i++) cleanNode(v.owned[i]);\n }\n if (v.tOwned) v.owned = v.tOwned;\n delete v.tValue;\n delete v.tOwned;\n v.tState = 0;\n }\n setTransPending(false);\n }, false);\n } else if (Transition.running) {\n Transition.running = false;\n Transition.effects.push.apply(Transition.effects, Effects);\n Effects = null;\n setTransPending(true);\n return;\n }\n }\n const e = Effects;\n Effects = null;\n if (e.length) runUpdates(() => runEffects(e), false);else DevHooks.afterUpdate && DevHooks.afterUpdate();\n if (res) res();\n}\nfunction runQueue(queue) {\n for (let i = 0; i < queue.length; i++) runTop(queue[i]);\n}\nfunction scheduleQueue(queue) {\n for (let i = 0; i < queue.length; i++) {\n const item = queue[i];\n const tasks = Transition.queue;\n if (!tasks.has(item)) {\n tasks.add(item);\n Scheduler(() => {\n tasks.delete(item);\n runUpdates(() => {\n Transition.running = true;\n runTop(item);\n }, false);\n Transition && (Transition.running = false);\n });\n }\n }\n}\nfunction runUserEffects(queue) {\n let i,\n userLength = 0;\n for (i = 0; i < queue.length; i++) {\n const e = queue[i];\n if (!e.user) runTop(e);else queue[userLength++] = e;\n }\n if (sharedConfig.context) {\n if (sharedConfig.count) {\n sharedConfig.effects || (sharedConfig.effects = []);\n sharedConfig.effects.push(...queue.slice(0, userLength));\n return;\n }\n setHydrateContext();\n }\n if (sharedConfig.effects && (sharedConfig.done || !sharedConfig.count)) {\n queue = [...sharedConfig.effects, ...queue];\n userLength += sharedConfig.effects.length;\n delete sharedConfig.effects;\n }\n for (i = 0; i < userLength; i++) runTop(queue[i]);\n}\nfunction lookUpstream(node, ignore) {\n const runningTransition = Transition && Transition.running;\n if (runningTransition) node.tState = 0;else node.state = 0;\n for (let i = 0; i < node.sources.length; i += 1) {\n const source = node.sources[i];\n if (source.sources) {\n const state = runningTransition ? source.tState : source.state;\n if (state === STALE) {\n if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source);\n } else if (state === PENDING) lookUpstream(source, ignore);\n }\n }\n}\nfunction markDownstream(node) {\n const runningTransition = Transition && Transition.running;\n for (let i = 0; i < node.observers.length; i += 1) {\n const o = node.observers[i];\n if (runningTransition ? !o.tState : !o.state) {\n if (runningTransition) o.tState = PENDING;else o.state = PENDING;\n if (o.pure) Updates.push(o);else Effects.push(o);\n o.observers && markDownstream(o);\n }\n }\n}\nfunction cleanNode(node) {\n let i;\n if (node.sources) {\n while (node.sources.length) {\n const source = node.sources.pop(),\n index = node.sourceSlots.pop(),\n obs = source.observers;\n if (obs && obs.length) {\n const n = obs.pop(),\n s = source.observerSlots.pop();\n if (index < obs.length) {\n n.sourceSlots[s] = index;\n obs[index] = n;\n source.observerSlots[index] = s;\n }\n }\n }\n }\n if (node.tOwned) {\n for (i = node.tOwned.length - 1; i >= 0; i--) cleanNode(node.tOwned[i]);\n delete node.tOwned;\n }\n if (Transition && Transition.running && node.pure) {\n reset(node, true);\n } else if (node.owned) {\n for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]);\n node.owned = null;\n }\n if (node.cleanups) {\n for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i]();\n node.cleanups = null;\n }\n if (Transition && Transition.running) node.tState = 0;else node.state = 0;\n delete node.sourceMap;\n}\nfunction reset(node, top) {\n if (!top) {\n node.tState = 0;\n Transition.disposed.add(node);\n }\n if (node.owned) {\n for (let i = 0; i < node.owned.length; i++) reset(node.owned[i]);\n }\n}\nfunction castError(err) {\n if (err instanceof Error) return err;\n return new Error(typeof err === \"string\" ? err : \"Unknown error\", {\n cause: err\n });\n}\nfunction runErrors(err, fns, owner) {\n try {\n for (const f of fns) f(err);\n } catch (e) {\n handleError(e, owner && owner.owner || null);\n }\n}\nfunction handleError(err, owner = Owner) {\n const fns = ERROR && owner && owner.context && owner.context[ERROR];\n const error = castError(err);\n if (!fns) throw error;\n if (Effects) Effects.push({\n fn() {\n runErrors(error, fns, owner);\n },\n state: STALE\n });else runErrors(error, fns, owner);\n}\nfunction resolveChildren(children) {\n if (typeof children === \"function\" && !children.length) return resolveChildren(children());\n if (Array.isArray(children)) {\n const results = [];\n for (let i = 0; i < children.length; i++) {\n const result = resolveChildren(children[i]);\n Array.isArray(result) ? results.push.apply(results, result) : results.push(result);\n }\n return results;\n }\n return children;\n}\nfunction createProvider(id, options) {\n return function provider(props) {\n let res;\n createRenderEffect(() => res = untrack(() => {\n Owner.context = {\n ...Owner.context,\n [id]: props.value\n };\n return children(() => props.children);\n }), undefined, options);\n return res;\n };\n}\nfunction onError(fn) {\n ERROR || (ERROR = Symbol(\"error\"));\n if (Owner === null) console.warn(\"error handlers created outside a `createRoot` or `render` will never be run\");else if (Owner.context === null || !Owner.context[ERROR]) {\n Owner.context = {\n ...Owner.context,\n [ERROR]: [fn]\n };\n mutateContext(Owner, ERROR, [fn]);\n } else Owner.context[ERROR].push(fn);\n}\nfunction mutateContext(o, key, value) {\n if (o.owned) {\n for (let i = 0; i < o.owned.length; i++) {\n if (o.owned[i].context === o.context) mutateContext(o.owned[i], key, value);\n if (!o.owned[i].context) {\n o.owned[i].context = o.context;\n mutateContext(o.owned[i], key, value);\n } else if (!o.owned[i].context[key]) {\n o.owned[i].context[key] = value;\n mutateContext(o.owned[i], key, value);\n }\n }\n }\n}\n\nfunction observable(input) {\n return {\n subscribe(observer) {\n if (!(observer instanceof Object) || observer == null) {\n throw new TypeError(\"Expected the observer to be an object.\");\n }\n const handler = typeof observer === \"function\" ? observer : observer.next && observer.next.bind(observer);\n if (!handler) {\n return {\n unsubscribe() {}\n };\n }\n const dispose = createRoot(disposer => {\n createEffect(() => {\n const v = input();\n untrack(() => handler(v));\n });\n return disposer;\n });\n if (getOwner()) onCleanup(dispose);\n return {\n unsubscribe() {\n dispose();\n }\n };\n },\n [Symbol.observable || \"@@observable\"]() {\n return this;\n }\n };\n}\nfunction from(producer, initalValue = undefined) {\n const [s, set] = createSignal(initalValue, {\n equals: false\n });\n if (\"subscribe\" in producer) {\n const unsub = producer.subscribe(v => set(() => v));\n onCleanup(() => \"unsubscribe\" in unsub ? unsub.unsubscribe() : unsub());\n } else {\n const clean = producer(set);\n onCleanup(clean);\n }\n return s;\n}\n\nconst FALLBACK = Symbol(\"fallback\");\nfunction dispose(d) {\n for (let i = 0; i < d.length; i++) d[i]();\n}\nfunction mapArray(list, mapFn, options = {}) {\n let items = [],\n mapped = [],\n disposers = [],\n len = 0,\n indexes = mapFn.length > 1 ? [] : null;\n onCleanup(() => dispose(disposers));\n return () => {\n let newItems = list() || [],\n newLen = newItems.length,\n i,\n j;\n newItems[$TRACK];\n return untrack(() => {\n let newIndices, newIndicesNext, temp, tempdisposers, tempIndexes, start, end, newEnd, item;\n if (newLen === 0) {\n if (len !== 0) {\n dispose(disposers);\n disposers = [];\n items = [];\n mapped = [];\n len = 0;\n indexes && (indexes = []);\n }\n if (options.fallback) {\n items = [FALLBACK];\n mapped[0] = createRoot(disposer => {\n disposers[0] = disposer;\n return options.fallback();\n });\n len = 1;\n }\n }\n else if (len === 0) {\n mapped = new Array(newLen);\n for (j = 0; j < newLen; j++) {\n items[j] = newItems[j];\n mapped[j] = createRoot(mapper);\n }\n len = newLen;\n } else {\n temp = new Array(newLen);\n tempdisposers = new Array(newLen);\n indexes && (tempIndexes = new Array(newLen));\n for (start = 0, end = Math.min(len, newLen); start < end && items[start] === newItems[start]; start++);\n for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && items[end] === newItems[newEnd]; end--, newEnd--) {\n temp[newEnd] = mapped[end];\n tempdisposers[newEnd] = disposers[end];\n indexes && (tempIndexes[newEnd] = indexes[end]);\n }\n newIndices = new Map();\n newIndicesNext = new Array(newEnd + 1);\n for (j = newEnd; j >= start; j--) {\n item = newItems[j];\n i = newIndices.get(item);\n newIndicesNext[j] = i === undefined ? -1 : i;\n newIndices.set(item, j);\n }\n for (i = start; i <= end; i++) {\n item = items[i];\n j = newIndices.get(item);\n if (j !== undefined && j !== -1) {\n temp[j] = mapped[i];\n tempdisposers[j] = disposers[i];\n indexes && (tempIndexes[j] = indexes[i]);\n j = newIndicesNext[j];\n newIndices.set(item, j);\n } else disposers[i]();\n }\n for (j = start; j < newLen; j++) {\n if (j in temp) {\n mapped[j] = temp[j];\n disposers[j] = tempdisposers[j];\n if (indexes) {\n indexes[j] = tempIndexes[j];\n indexes[j](j);\n }\n } else mapped[j] = createRoot(mapper);\n }\n mapped = mapped.slice(0, len = newLen);\n items = newItems.slice(0);\n }\n return mapped;\n });\n function mapper(disposer) {\n disposers[j] = disposer;\n if (indexes) {\n const [s, set] = createSignal(j, {\n name: \"index\"\n }) ;\n indexes[j] = set;\n return mapFn(newItems[j], s);\n }\n return mapFn(newItems[j]);\n }\n };\n}\nfunction indexArray(list, mapFn, options = {}) {\n let items = [],\n mapped = [],\n disposers = [],\n signals = [],\n len = 0,\n i;\n onCleanup(() => dispose(disposers));\n return () => {\n const newItems = list() || [],\n newLen = newItems.length;\n newItems[$TRACK];\n return untrack(() => {\n if (newLen === 0) {\n if (len !== 0) {\n dispose(disposers);\n disposers = [];\n items = [];\n mapped = [];\n len = 0;\n signals = [];\n }\n if (options.fallback) {\n items = [FALLBACK];\n mapped[0] = createRoot(disposer => {\n disposers[0] = disposer;\n return options.fallback();\n });\n len = 1;\n }\n return mapped;\n }\n if (items[0] === FALLBACK) {\n disposers[0]();\n disposers = [];\n items = [];\n mapped = [];\n len = 0;\n }\n for (i = 0; i < newLen; i++) {\n if (i < items.length && items[i] !== newItems[i]) {\n signals[i](() => newItems[i]);\n } else if (i >= items.length) {\n mapped[i] = createRoot(mapper);\n }\n }\n for (; i < items.length; i++) {\n disposers[i]();\n }\n len = signals.length = disposers.length = newLen;\n items = newItems.slice(0);\n return mapped = mapped.slice(0, len);\n });\n function mapper(disposer) {\n disposers[i] = disposer;\n const [s, set] = createSignal(newItems[i], {\n name: \"value\"\n }) ;\n signals[i] = set;\n return mapFn(s, i);\n }\n };\n}\n\nlet hydrationEnabled = false;\nfunction enableHydration() {\n hydrationEnabled = true;\n}\nfunction createComponent(Comp, props) {\n if (hydrationEnabled) {\n if (sharedConfig.context) {\n const c = sharedConfig.context;\n setHydrateContext(nextHydrateContext());\n const r = devComponent(Comp, props || {}) ;\n setHydrateContext(c);\n return r;\n }\n }\n return devComponent(Comp, props || {});\n}\nfunction trueFn() {\n return true;\n}\nconst propTraps = {\n get(_, property, receiver) {\n if (property === $PROXY) return receiver;\n return _.get(property);\n },\n has(_, property) {\n if (property === $PROXY) return true;\n return _.has(property);\n },\n set: trueFn,\n deleteProperty: trueFn,\n getOwnPropertyDescriptor(_, property) {\n return {\n configurable: true,\n enumerable: true,\n get() {\n return _.get(property);\n },\n set: trueFn,\n deleteProperty: trueFn\n };\n },\n ownKeys(_) {\n return _.keys();\n }\n};\nfunction resolveSource(s) {\n return !(s = typeof s === \"function\" ? s() : s) ? {} : s;\n}\nfunction resolveSources() {\n for (let i = 0, length = this.length; i < length; ++i) {\n const v = this[i]();\n if (v !== undefined) return v;\n }\n}\nfunction mergeProps(...sources) {\n let proxy = false;\n for (let i = 0; i < sources.length; i++) {\n const s = sources[i];\n proxy = proxy || !!s && $PROXY in s;\n sources[i] = typeof s === \"function\" ? (proxy = true, createMemo(s)) : s;\n }\n if (SUPPORTS_PROXY && proxy) {\n return new Proxy({\n get(property) {\n for (let i = sources.length - 1; i >= 0; i--) {\n const v = resolveSource(sources[i])[property];\n if (v !== undefined) return v;\n }\n },\n has(property) {\n for (let i = sources.length - 1; i >= 0; i--) {\n if (property in resolveSource(sources[i])) return true;\n }\n return false;\n },\n keys() {\n const keys = [];\n for (let i = 0; i < sources.length; i++) keys.push(...Object.keys(resolveSource(sources[i])));\n return [...new Set(keys)];\n }\n }, propTraps);\n }\n const sourcesMap = {};\n const defined = Object.create(null);\n for (let i = sources.length - 1; i >= 0; i--) {\n const source = sources[i];\n if (!source) continue;\n const sourceKeys = Object.getOwnPropertyNames(source);\n for (let i = sourceKeys.length - 1; i >= 0; i--) {\n const key = sourceKeys[i];\n if (key === \"__proto__\" || key === \"constructor\") continue;\n const desc = Object.getOwnPropertyDescriptor(source, key);\n if (!defined[key]) {\n defined[key] = desc.get ? {\n enumerable: true,\n configurable: true,\n get: resolveSources.bind(sourcesMap[key] = [desc.get.bind(source)])\n } : desc.value !== undefined ? desc : undefined;\n } else {\n const sources = sourcesMap[key];\n if (sources) {\n if (desc.get) sources.push(desc.get.bind(source));else if (desc.value !== undefined) sources.push(() => desc.value);\n }\n }\n }\n }\n const target = {};\n const definedKeys = Object.keys(defined);\n for (let i = definedKeys.length - 1; i >= 0; i--) {\n const key = definedKeys[i],\n desc = defined[key];\n if (desc && desc.get) Object.defineProperty(target, key, desc);else target[key] = desc ? desc.value : undefined;\n }\n return target;\n}\nfunction splitProps(props, ...keys) {\n if (SUPPORTS_PROXY && $PROXY in props) {\n const blocked = new Set(keys.length > 1 ? keys.flat() : keys[0]);\n const res = keys.map(k => {\n return new Proxy({\n get(property) {\n return k.includes(property) ? props[property] : undefined;\n },\n has(property) {\n return k.includes(property) && property in props;\n },\n keys() {\n return k.filter(property => property in props);\n }\n }, propTraps);\n });\n res.push(new Proxy({\n get(property) {\n return blocked.has(property) ? undefined : props[property];\n },\n has(property) {\n return blocked.has(property) ? false : property in props;\n },\n keys() {\n return Object.keys(props).filter(k => !blocked.has(k));\n }\n }, propTraps));\n return res;\n }\n const otherObject = {};\n const objects = keys.map(() => ({}));\n for (const propName of Object.getOwnPropertyNames(props)) {\n const desc = Object.getOwnPropertyDescriptor(props, propName);\n const isDefaultDesc = !desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable;\n let blocked = false;\n let objectIndex = 0;\n for (const k of keys) {\n if (k.includes(propName)) {\n blocked = true;\n isDefaultDesc ? objects[objectIndex][propName] = desc.value : Object.defineProperty(objects[objectIndex], propName, desc);\n }\n ++objectIndex;\n }\n if (!blocked) {\n isDefaultDesc ? otherObject[propName] = desc.value : Object.defineProperty(otherObject, propName, desc);\n }\n }\n return [...objects, otherObject];\n}\nfunction lazy(fn) {\n let comp;\n let p;\n const wrap = props => {\n const ctx = sharedConfig.context;\n if (ctx) {\n const [s, set] = createSignal();\n sharedConfig.count || (sharedConfig.count = 0);\n sharedConfig.count++;\n (p || (p = fn())).then(mod => {\n !sharedConfig.done && setHydrateContext(ctx);\n sharedConfig.count--;\n set(() => mod.default);\n setHydrateContext();\n });\n comp = s;\n } else if (!comp) {\n const [s] = createResource(() => (p || (p = fn())).then(mod => mod.default));\n comp = s;\n }\n let Comp;\n return createMemo(() => (Comp = comp()) ? untrack(() => {\n if (IS_DEV) Object.assign(Comp, {\n [$DEVCOMP]: true\n });\n if (!ctx || sharedConfig.done) return Comp(props);\n const c = sharedConfig.context;\n setHydrateContext(ctx);\n const r = Comp(props);\n setHydrateContext(c);\n return r;\n }) : \"\");\n };\n wrap.preload = () => p || ((p = fn()).then(mod => comp = () => mod.default), p);\n return wrap;\n}\nlet counter = 0;\nfunction createUniqueId() {\n const ctx = sharedConfig.context;\n return ctx ? sharedConfig.getNextContextId() : `cl-${counter++}`;\n}\n\nconst narrowedError = name => `Attempting to access a stale value from <${name}> that could possibly be undefined. This may occur because you are reading the accessor returned from the component at a time where it has already been unmounted. We recommend cleaning up any stale timers or async, or reading from the initial condition.` ;\nfunction For(props) {\n const fallback = \"fallback\" in props && {\n fallback: () => props.fallback\n };\n return createMemo(mapArray(() => props.each, props.children, fallback || undefined), undefined, {\n name: \"value\"\n }) ;\n}\nfunction Index(props) {\n const fallback = \"fallback\" in props && {\n fallback: () => props.fallback\n };\n return createMemo(indexArray(() => props.each, props.children, fallback || undefined), undefined, {\n name: \"value\"\n }) ;\n}\nfunction Show(props) {\n const keyed = props.keyed;\n const conditionValue = createMemo(() => props.when, undefined, {\n name: \"condition value\"\n } );\n const condition = keyed ? conditionValue : createMemo(conditionValue, undefined, {\n equals: (a, b) => !a === !b,\n name: \"condition\"\n } );\n return createMemo(() => {\n const c = condition();\n if (c) {\n const child = props.children;\n const fn = typeof child === \"function\" && child.length > 0;\n return fn ? untrack(() => child(keyed ? c : () => {\n if (!untrack(condition)) throw narrowedError(\"Show\");\n return conditionValue();\n })) : child;\n }\n return props.fallback;\n }, undefined, {\n name: \"value\"\n } );\n}\nfunction Switch(props) {\n const chs = children(() => props.children);\n const switchFunc = createMemo(() => {\n const ch = chs();\n const mps = Array.isArray(ch) ? ch : [ch];\n let func = () => undefined;\n for (let i = 0; i < mps.length; i++) {\n const index = i;\n const mp = mps[i];\n const prevFunc = func;\n const conditionValue = createMemo(() => prevFunc() ? undefined : mp.when, undefined, {\n name: \"condition value\"\n } );\n const condition = mp.keyed ? conditionValue : createMemo(conditionValue, undefined, {\n equals: (a, b) => !a === !b,\n name: \"condition\"\n } );\n func = () => prevFunc() || (condition() ? [index, conditionValue, mp] : undefined);\n }\n return func;\n });\n return createMemo(() => {\n const sel = switchFunc()();\n if (!sel) return props.fallback;\n const [index, conditionValue, mp] = sel;\n const child = mp.children;\n const fn = typeof child === \"function\" && child.length > 0;\n return fn ? untrack(() => child(mp.keyed ? conditionValue() : () => {\n if (untrack(switchFunc)()?.[0] !== index) throw narrowedError(\"Match\");\n return conditionValue();\n })) : child;\n }, undefined, {\n name: \"eval conditions\"\n } );\n}\nfunction Match(props) {\n return props;\n}\nlet Errors;\nfunction resetErrorBoundaries() {\n Errors && [...Errors].forEach(fn => fn());\n}\nfunction ErrorBoundary(props) {\n let err;\n if (sharedConfig.context && sharedConfig.load) err = sharedConfig.load(sharedConfig.getContextId());\n const [errored, setErrored] = createSignal(err, {\n name: \"errored\"\n } );\n Errors || (Errors = new Set());\n Errors.add(setErrored);\n onCleanup(() => Errors.delete(setErrored));\n return createMemo(() => {\n let e;\n if (e = errored()) {\n const f = props.fallback;\n if ((typeof f !== \"function\" || f.length == 0)) console.error(e);\n return typeof f === \"function\" && f.length ? untrack(() => f(e, () => setErrored())) : f;\n }\n return catchError(() => props.children, setErrored);\n }, undefined, {\n name: \"value\"\n } );\n}\n\nconst suspenseListEquals = (a, b) => a.showContent === b.showContent && a.showFallback === b.showFallback;\nconst SuspenseListContext = /* #__PURE__ */createContext();\nfunction SuspenseList(props) {\n let [wrapper, setWrapper] = createSignal(() => ({\n inFallback: false\n })),\n show;\n const listContext = useContext(SuspenseListContext);\n const [registry, setRegistry] = createSignal([]);\n if (listContext) {\n show = listContext.register(createMemo(() => wrapper()().inFallback));\n }\n const resolved = createMemo(prev => {\n const reveal = props.revealOrder,\n tail = props.tail,\n {\n showContent = true,\n showFallback = true\n } = show ? show() : {},\n reg = registry(),\n reverse = reveal === \"backwards\";\n if (reveal === \"together\") {\n const all = reg.every(inFallback => !inFallback());\n const res = reg.map(() => ({\n showContent: all && showContent,\n showFallback\n }));\n res.inFallback = !all;\n return res;\n }\n let stop = false;\n let inFallback = prev.inFallback;\n const res = [];\n for (let i = 0, len = reg.length; i < len; i++) {\n const n = reverse ? len - i - 1 : i,\n s = reg[n]();\n if (!stop && !s) {\n res[n] = {\n showContent,\n showFallback\n };\n } else {\n const next = !stop;\n if (next) inFallback = true;\n res[n] = {\n showContent: next,\n showFallback: !tail || next && tail === \"collapsed\" ? showFallback : false\n };\n stop = true;\n }\n }\n if (!stop) inFallback = false;\n res.inFallback = inFallback;\n return res;\n }, {\n inFallback: false\n });\n setWrapper(() => resolved);\n return createComponent(SuspenseListContext.Provider, {\n value: {\n register: inFallback => {\n let index;\n setRegistry(registry => {\n index = registry.length;\n return [...registry, inFallback];\n });\n return createMemo(() => resolved()[index], undefined, {\n equals: suspenseListEquals\n });\n }\n },\n get children() {\n return props.children;\n }\n });\n}\nfunction Suspense(props) {\n let counter = 0,\n show,\n ctx,\n p,\n flicker,\n error;\n const [inFallback, setFallback] = createSignal(false),\n SuspenseContext = getSuspenseContext(),\n store = {\n increment: () => {\n if (++counter === 1) setFallback(true);\n },\n decrement: () => {\n if (--counter === 0) setFallback(false);\n },\n inFallback,\n effects: [],\n resolved: false\n },\n owner = getOwner();\n if (sharedConfig.context && sharedConfig.load) {\n const key = sharedConfig.getContextId();\n let ref = sharedConfig.load(key);\n if (ref) {\n if (typeof ref !== \"object\" || ref.s !== 1) p = ref;else sharedConfig.gather(key);\n }\n if (p && p !== \"$$f\") {\n const [s, set] = createSignal(undefined, {\n equals: false\n });\n flicker = s;\n p.then(() => {\n if (sharedConfig.done) return set();\n sharedConfig.gather(key);\n setHydrateContext(ctx);\n set();\n setHydrateContext();\n }, err => {\n error = err;\n set();\n });\n }\n }\n const listContext = useContext(SuspenseListContext);\n if (listContext) show = listContext.register(store.inFallback);\n let dispose;\n onCleanup(() => dispose && dispose());\n return createComponent(SuspenseContext.Provider, {\n value: store,\n get children() {\n return createMemo(() => {\n if (error) throw error;\n ctx = sharedConfig.context;\n if (flicker) {\n flicker();\n return flicker = undefined;\n }\n if (ctx && p === \"$$f\") setHydrateContext();\n const rendered = createMemo(() => props.children);\n return createMemo(prev => {\n const inFallback = store.inFallback(),\n {\n showContent = true,\n showFallback = true\n } = show ? show() : {};\n if ((!inFallback || p && p !== \"$$f\") && showContent) {\n store.resolved = true;\n dispose && dispose();\n dispose = ctx = p = undefined;\n resumeEffects(store.effects);\n return rendered();\n }\n if (!showFallback) return;\n if (dispose) return prev;\n return createRoot(disposer => {\n dispose = disposer;\n if (ctx) {\n setHydrateContext({\n id: ctx.id + \"F\",\n count: 0\n });\n ctx = undefined;\n }\n return props.fallback;\n }, owner);\n });\n });\n }\n });\n}\n\nconst DEV = {\n hooks: DevHooks,\n writeSignal,\n registerGraph\n} ;\nif (globalThis) {\n if (!globalThis.Solid$$) globalThis.Solid$$ = true;else console.warn(\"You appear to have multiple instances of Solid. This can lead to unexpected behavior.\");\n}\n\nexport { $DEVCOMP, $PROXY, $TRACK, DEV, ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, batch, cancelCallback, catchError, children, createComponent, createComputed, createContext, createDeferred, createEffect, createMemo, createReaction, createRenderEffect, createResource, createRoot, createSelector, createSignal, createUniqueId, enableExternalSource, enableHydration, enableScheduling, equalFn, from, getListener, getOwner, indexArray, lazy, mapArray, mergeProps, observable, on, onCleanup, onError, onMount, requestCallback, resetErrorBoundaries, runWithOwner, sharedConfig, splitProps, startTransition, untrack, useContext, useTransition };\n"],
- "mappings": "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",
- "names": ["taskQueue", "value", "error", "children", "untrack", "e", "dispose", "i", "sources", "inFallback", "res", "registry", "counter", "SuspenseContext"]
-}
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/package.json b/pulse-test-staging/frontend-modern/.vite/deps/package.json
deleted file mode 100644
index 3dbc1ca59..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/package.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "type": "module"
-}
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/solid-js.js b/pulse-test-staging/frontend-modern/.vite/deps/solid-js.js
deleted file mode 100644
index 707f8d619..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/solid-js.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import {
- $DEVCOMP,
- $PROXY,
- $TRACK,
- DEV,
- ErrorBoundary,
- For,
- Index,
- Match,
- Show,
- Suspense,
- SuspenseList,
- Switch,
- batch,
- cancelCallback,
- catchError,
- children,
- createComponent,
- createComputed,
- createContext,
- createDeferred,
- createEffect,
- createMemo,
- createReaction,
- createRenderEffect,
- createResource,
- createRoot,
- createSelector,
- createSignal,
- createUniqueId,
- enableExternalSource,
- enableHydration,
- enableScheduling,
- equalFn,
- from,
- getListener,
- getOwner,
- indexArray,
- lazy,
- mapArray,
- mergeProps,
- observable,
- on,
- onCleanup,
- onError,
- onMount,
- requestCallback,
- resetErrorBoundaries,
- runWithOwner,
- sharedConfig,
- splitProps,
- startTransition,
- untrack,
- useContext,
- useTransition
-} from "./chunk-IZS3CG5R.js";
-export {
- $DEVCOMP,
- $PROXY,
- $TRACK,
- DEV,
- ErrorBoundary,
- For,
- Index,
- Match,
- Show,
- Suspense,
- SuspenseList,
- Switch,
- batch,
- cancelCallback,
- catchError,
- children,
- createComponent,
- createComputed,
- createContext,
- createDeferred,
- createEffect,
- createMemo,
- createReaction,
- createRenderEffect,
- createResource,
- createRoot,
- createSelector,
- createSignal,
- createUniqueId,
- enableExternalSource,
- enableHydration,
- enableScheduling,
- equalFn,
- from,
- getListener,
- getOwner,
- indexArray,
- lazy,
- mapArray,
- mergeProps,
- observable,
- on,
- onCleanup,
- onError,
- onMount,
- requestCallback,
- resetErrorBoundaries,
- runWithOwner,
- sharedConfig,
- splitProps,
- startTransition,
- untrack,
- useContext,
- useTransition
-};
-//# sourceMappingURL=solid-js.js.map
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/solid-js.js.map b/pulse-test-staging/frontend-modern/.vite/deps/solid-js.js.map
deleted file mode 100644
index 98652118b..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/solid-js.js.map
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": 3,
- "sources": [],
- "sourcesContent": [],
- "mappings": "",
- "names": []
-}
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_store.js b/pulse-test-staging/frontend-modern/.vite/deps/solid-js_store.js
deleted file mode 100644
index b169997a9..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_store.js
+++ /dev/null
@@ -1,451 +0,0 @@
-import {
- $PROXY,
- $TRACK,
- DEV,
- batch,
- createSignal,
- getListener
-} from "./chunk-IZS3CG5R.js";
-
-// node_modules/solid-js/store/dist/dev.js
-var $RAW = Symbol("store-raw");
-var $NODE = Symbol("store-node");
-var $HAS = Symbol("store-has");
-var $SELF = Symbol("store-self");
-var DevHooks = {
- onStoreNodeUpdate: null
-};
-function wrap$1(value) {
- let p = value[$PROXY];
- if (!p) {
- Object.defineProperty(value, $PROXY, {
- value: p = new Proxy(value, proxyTraps$1)
- });
- if (!Array.isArray(value)) {
- const keys = Object.keys(value), desc = Object.getOwnPropertyDescriptors(value);
- for (let i = 0, l = keys.length; i < l; i++) {
- const prop = keys[i];
- if (desc[prop].get) {
- Object.defineProperty(value, prop, {
- enumerable: desc[prop].enumerable,
- get: desc[prop].get.bind(p)
- });
- }
- }
- }
- }
- return p;
-}
-function isWrappable(obj) {
- let proto;
- return obj != null && typeof obj === "object" && (obj[$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj));
-}
-function unwrap(item, set = /* @__PURE__ */ new Set()) {
- let result, unwrapped, v, prop;
- if (result = item != null && item[$RAW]) return result;
- if (!isWrappable(item) || set.has(item)) return item;
- if (Array.isArray(item)) {
- if (Object.isFrozen(item)) item = item.slice(0);
- else set.add(item);
- for (let i = 0, l = item.length; i < l; i++) {
- v = item[i];
- if ((unwrapped = unwrap(v, set)) !== v) item[i] = unwrapped;
- }
- } else {
- if (Object.isFrozen(item)) item = Object.assign({}, item);
- else set.add(item);
- const keys = Object.keys(item), desc = Object.getOwnPropertyDescriptors(item);
- for (let i = 0, l = keys.length; i < l; i++) {
- prop = keys[i];
- if (desc[prop].get) continue;
- v = item[prop];
- if ((unwrapped = unwrap(v, set)) !== v) item[prop] = unwrapped;
- }
- }
- return item;
-}
-function getNodes(target, symbol) {
- let nodes = target[symbol];
- if (!nodes) Object.defineProperty(target, symbol, {
- value: nodes = /* @__PURE__ */ Object.create(null)
- });
- return nodes;
-}
-function getNode(nodes, property, value) {
- if (nodes[property]) return nodes[property];
- const [s, set] = createSignal(value, {
- equals: false,
- internal: true
- });
- s.$ = set;
- return nodes[property] = s;
-}
-function proxyDescriptor$1(target, property) {
- const desc = Reflect.getOwnPropertyDescriptor(target, property);
- if (!desc || desc.get || !desc.configurable || property === $PROXY || property === $NODE) return desc;
- delete desc.value;
- delete desc.writable;
- desc.get = () => target[$PROXY][property];
- return desc;
-}
-function trackSelf(target) {
- getListener() && getNode(getNodes(target, $NODE), $SELF)();
-}
-function ownKeys(target) {
- trackSelf(target);
- return Reflect.ownKeys(target);
-}
-var proxyTraps$1 = {
- get(target, property, receiver) {
- if (property === $RAW) return target;
- if (property === $PROXY) return receiver;
- if (property === $TRACK) {
- trackSelf(target);
- return receiver;
- }
- const nodes = getNodes(target, $NODE);
- const tracked = nodes[property];
- let value = tracked ? tracked() : target[property];
- if (property === $NODE || property === $HAS || property === "__proto__") return value;
- if (!tracked) {
- const desc = Object.getOwnPropertyDescriptor(target, property);
- if (getListener() && (typeof value !== "function" || target.hasOwnProperty(property)) && !(desc && desc.get)) value = getNode(nodes, property, value)();
- }
- return isWrappable(value) ? wrap$1(value) : value;
- },
- has(target, property) {
- if (property === $RAW || property === $PROXY || property === $TRACK || property === $NODE || property === $HAS || property === "__proto__") return true;
- getListener() && getNode(getNodes(target, $HAS), property)();
- return property in target;
- },
- set() {
- console.warn("Cannot mutate a Store directly");
- return true;
- },
- deleteProperty() {
- console.warn("Cannot mutate a Store directly");
- return true;
- },
- ownKeys,
- getOwnPropertyDescriptor: proxyDescriptor$1
-};
-function setProperty(state, property, value, deleting = false) {
- if (!deleting && state[property] === value) return;
- const prev = state[property], len = state.length;
- DevHooks.onStoreNodeUpdate && DevHooks.onStoreNodeUpdate(state, property, value, prev);
- if (value === void 0) {
- delete state[property];
- if (state[$HAS] && state[$HAS][property] && prev !== void 0) state[$HAS][property].$();
- } else {
- state[property] = value;
- if (state[$HAS] && state[$HAS][property] && prev === void 0) state[$HAS][property].$();
- }
- let nodes = getNodes(state, $NODE), node;
- if (node = getNode(nodes, property, prev)) node.$(() => value);
- if (Array.isArray(state) && state.length !== len) {
- for (let i = state.length; i < len; i++) (node = nodes[i]) && node.$();
- (node = getNode(nodes, "length", len)) && node.$(state.length);
- }
- (node = nodes[$SELF]) && node.$();
-}
-function mergeStoreNode(state, value) {
- const keys = Object.keys(value);
- for (let i = 0; i < keys.length; i += 1) {
- const key = keys[i];
- setProperty(state, key, value[key]);
- }
-}
-function updateArray(current, next) {
- if (typeof next === "function") next = next(current);
- next = unwrap(next);
- if (Array.isArray(next)) {
- if (current === next) return;
- let i = 0, len = next.length;
- for (; i < len; i++) {
- const value = next[i];
- if (current[i] !== value) setProperty(current, i, value);
- }
- setProperty(current, "length", len);
- } else mergeStoreNode(current, next);
-}
-function updatePath(current, path, traversed = []) {
- let part, prev = current;
- if (path.length > 1) {
- part = path.shift();
- const partType = typeof part, isArray = Array.isArray(current);
- if (Array.isArray(part)) {
- for (let i = 0; i < part.length; i++) {
- updatePath(current, [part[i]].concat(path), traversed);
- }
- return;
- } else if (isArray && partType === "function") {
- for (let i = 0; i < current.length; i++) {
- if (part(current[i], i)) updatePath(current, [i].concat(path), traversed);
- }
- return;
- } else if (isArray && partType === "object") {
- const {
- from = 0,
- to = current.length - 1,
- by = 1
- } = part;
- for (let i = from; i <= to; i += by) {
- updatePath(current, [i].concat(path), traversed);
- }
- return;
- } else if (path.length > 1) {
- updatePath(current[part], path, [part].concat(traversed));
- return;
- }
- prev = current[part];
- traversed = [part].concat(traversed);
- }
- let value = path[0];
- if (typeof value === "function") {
- value = value(prev, traversed);
- if (value === prev) return;
- }
- if (part === void 0 && value == void 0) return;
- value = unwrap(value);
- if (part === void 0 || isWrappable(prev) && isWrappable(value) && !Array.isArray(value)) {
- mergeStoreNode(prev, value);
- } else setProperty(current, part, value);
-}
-function createStore(...[store, options]) {
- const unwrappedStore = unwrap(store || {});
- const isArray = Array.isArray(unwrappedStore);
- if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`);
- const wrappedStore = wrap$1(unwrappedStore);
- DEV.registerGraph({
- value: unwrappedStore,
- name: options && options.name
- });
- function setStore(...args) {
- batch(() => {
- isArray && args.length === 1 ? updateArray(unwrappedStore, args[0]) : updatePath(unwrappedStore, args);
- });
- }
- return [wrappedStore, setStore];
-}
-function proxyDescriptor(target, property) {
- const desc = Reflect.getOwnPropertyDescriptor(target, property);
- if (!desc || desc.get || desc.set || !desc.configurable || property === $PROXY || property === $NODE) return desc;
- delete desc.value;
- delete desc.writable;
- desc.get = () => target[$PROXY][property];
- desc.set = (v) => target[$PROXY][property] = v;
- return desc;
-}
-var proxyTraps = {
- get(target, property, receiver) {
- if (property === $RAW) return target;
- if (property === $PROXY) return receiver;
- if (property === $TRACK) {
- trackSelf(target);
- return receiver;
- }
- const nodes = getNodes(target, $NODE);
- const tracked = nodes[property];
- let value = tracked ? tracked() : target[property];
- if (property === $NODE || property === $HAS || property === "__proto__") return value;
- if (!tracked) {
- const desc = Object.getOwnPropertyDescriptor(target, property);
- const isFunction = typeof value === "function";
- if (getListener() && (!isFunction || target.hasOwnProperty(property)) && !(desc && desc.get)) value = getNode(nodes, property, value)();
- else if (value != null && isFunction && value === Array.prototype[property]) {
- return (...args) => batch(() => Array.prototype[property].apply(receiver, args));
- }
- }
- return isWrappable(value) ? wrap(value) : value;
- },
- has(target, property) {
- if (property === $RAW || property === $PROXY || property === $TRACK || property === $NODE || property === $HAS || property === "__proto__") return true;
- getListener() && getNode(getNodes(target, $HAS), property)();
- return property in target;
- },
- set(target, property, value) {
- batch(() => setProperty(target, property, unwrap(value)));
- return true;
- },
- deleteProperty(target, property) {
- batch(() => setProperty(target, property, void 0, true));
- return true;
- },
- ownKeys,
- getOwnPropertyDescriptor: proxyDescriptor
-};
-function wrap(value) {
- let p = value[$PROXY];
- if (!p) {
- Object.defineProperty(value, $PROXY, {
- value: p = new Proxy(value, proxyTraps)
- });
- const keys = Object.keys(value), desc = Object.getOwnPropertyDescriptors(value);
- const proto = Object.getPrototypeOf(value);
- const isClass = proto !== null && value !== null && typeof value === "object" && !Array.isArray(value) && proto !== Object.prototype;
- if (isClass) {
- const descriptors = Object.getOwnPropertyDescriptors(proto);
- keys.push(...Object.keys(descriptors));
- Object.assign(desc, descriptors);
- }
- for (let i = 0, l = keys.length; i < l; i++) {
- const prop = keys[i];
- if (isClass && prop === "constructor") continue;
- if (desc[prop].get) {
- const get = desc[prop].get.bind(p);
- Object.defineProperty(value, prop, {
- get,
- configurable: true
- });
- }
- if (desc[prop].set) {
- const og = desc[prop].set, set = (v) => batch(() => og.call(p, v));
- Object.defineProperty(value, prop, {
- set,
- configurable: true
- });
- }
- }
- }
- return p;
-}
-function createMutable(state, options) {
- const unwrappedStore = unwrap(state || {});
- if (typeof unwrappedStore !== "object" && typeof unwrappedStore !== "function") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createMutable'. Expected an object.`);
- const wrappedStore = wrap(unwrappedStore);
- DEV.registerGraph({
- value: unwrappedStore,
- name: options && options.name
- });
- return wrappedStore;
-}
-function modifyMutable(state, modifier) {
- batch(() => modifier(unwrap(state)));
-}
-var $ROOT = Symbol("store-root");
-function applyState(target, parent, property, merge, key) {
- const previous = parent[property];
- if (target === previous) return;
- const isArray = Array.isArray(target);
- if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || isArray !== Array.isArray(previous) || key && target[key] !== previous[key])) {
- setProperty(parent, property, target);
- return;
- }
- if (isArray) {
- if (target.length && previous.length && (!merge || key && target[0] && target[0][key] != null)) {
- let i, j, start, end, newEnd, item, newIndicesNext, keyVal;
- for (start = 0, end = Math.min(previous.length, target.length); start < end && (previous[start] === target[start] || key && previous[start] && target[start] && previous[start][key] === target[start][key]); start++) {
- applyState(target[start], previous, start, merge, key);
- }
- const temp = new Array(target.length), newIndices = /* @__PURE__ */ new Map();
- for (end = previous.length - 1, newEnd = target.length - 1; end >= start && newEnd >= start && (previous[end] === target[newEnd] || key && previous[end] && target[newEnd] && previous[end][key] === target[newEnd][key]); end--, newEnd--) {
- temp[newEnd] = previous[end];
- }
- if (start > newEnd || start > end) {
- for (j = start; j <= newEnd; j++) setProperty(previous, j, target[j]);
- for (; j < target.length; j++) {
- setProperty(previous, j, temp[j]);
- applyState(target[j], previous, j, merge, key);
- }
- if (previous.length > target.length) setProperty(previous, "length", target.length);
- return;
- }
- newIndicesNext = new Array(newEnd + 1);
- for (j = newEnd; j >= start; j--) {
- item = target[j];
- keyVal = key && item ? item[key] : item;
- i = newIndices.get(keyVal);
- newIndicesNext[j] = i === void 0 ? -1 : i;
- newIndices.set(keyVal, j);
- }
- for (i = start; i <= end; i++) {
- item = previous[i];
- keyVal = key && item ? item[key] : item;
- j = newIndices.get(keyVal);
- if (j !== void 0 && j !== -1) {
- temp[j] = previous[i];
- j = newIndicesNext[j];
- newIndices.set(keyVal, j);
- }
- }
- for (j = start; j < target.length; j++) {
- if (j in temp) {
- setProperty(previous, j, temp[j]);
- applyState(target[j], previous, j, merge, key);
- } else setProperty(previous, j, target[j]);
- }
- } else {
- for (let i = 0, len = target.length; i < len; i++) {
- applyState(target[i], previous, i, merge, key);
- }
- }
- if (previous.length > target.length) setProperty(previous, "length", target.length);
- return;
- }
- const targetKeys = Object.keys(target);
- for (let i = 0, len = targetKeys.length; i < len; i++) {
- applyState(target[targetKeys[i]], previous, targetKeys[i], merge, key);
- }
- const previousKeys = Object.keys(previous);
- for (let i = 0, len = previousKeys.length; i < len; i++) {
- if (target[previousKeys[i]] === void 0) setProperty(previous, previousKeys[i], void 0);
- }
-}
-function reconcile(value, options = {}) {
- const {
- merge,
- key = "id"
- } = options, v = unwrap(value);
- return (state) => {
- if (!isWrappable(state) || !isWrappable(v)) return v;
- const res = applyState(v, {
- [$ROOT]: state
- }, $ROOT, merge, key);
- return res === void 0 ? state : res;
- };
-}
-var producers = /* @__PURE__ */ new WeakMap();
-var setterTraps = {
- get(target, property) {
- if (property === $RAW) return target;
- const value = target[property];
- let proxy;
- return isWrappable(value) ? producers.get(value) || (producers.set(value, proxy = new Proxy(value, setterTraps)), proxy) : value;
- },
- set(target, property, value) {
- setProperty(target, property, unwrap(value));
- return true;
- },
- deleteProperty(target, property) {
- setProperty(target, property, void 0, true);
- return true;
- }
-};
-function produce(fn) {
- return (state) => {
- if (isWrappable(state)) {
- let proxy;
- if (!(proxy = producers.get(state))) {
- producers.set(state, proxy = new Proxy(state, setterTraps));
- }
- fn(proxy);
- }
- return state;
- };
-}
-var DEV2 = {
- $NODE,
- isWrappable,
- hooks: DevHooks
-};
-export {
- $RAW,
- DEV2 as DEV,
- createMutable,
- createStore,
- modifyMutable,
- produce,
- reconcile,
- unwrap
-};
-//# sourceMappingURL=solid-js_store.js.map
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_store.js.map b/pulse-test-staging/frontend-modern/.vite/deps/solid-js_store.js.map
deleted file mode 100644
index 8ec3dba15..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_store.js.map
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": 3,
- "sources": ["../../node_modules/solid-js/store/dist/dev.js"],
- "sourcesContent": ["import { DEV as DEV$1, $PROXY, $TRACK, getListener, batch, createSignal } from 'solid-js';\n\nconst $RAW = Symbol(\"store-raw\"),\n $NODE = Symbol(\"store-node\"),\n $HAS = Symbol(\"store-has\"),\n $SELF = Symbol(\"store-self\");\nconst DevHooks = {\n onStoreNodeUpdate: null\n};\nfunction wrap$1(value) {\n let p = value[$PROXY];\n if (!p) {\n Object.defineProperty(value, $PROXY, {\n value: p = new Proxy(value, proxyTraps$1)\n });\n if (!Array.isArray(value)) {\n const keys = Object.keys(value),\n desc = Object.getOwnPropertyDescriptors(value);\n for (let i = 0, l = keys.length; i < l; i++) {\n const prop = keys[i];\n if (desc[prop].get) {\n Object.defineProperty(value, prop, {\n enumerable: desc[prop].enumerable,\n get: desc[prop].get.bind(p)\n });\n }\n }\n }\n }\n return p;\n}\nfunction isWrappable(obj) {\n let proto;\n return obj != null && typeof obj === \"object\" && (obj[$PROXY] || !(proto = Object.getPrototypeOf(obj)) || proto === Object.prototype || Array.isArray(obj));\n}\nfunction unwrap(item, set = new Set()) {\n let result, unwrapped, v, prop;\n if (result = item != null && item[$RAW]) return result;\n if (!isWrappable(item) || set.has(item)) return item;\n if (Array.isArray(item)) {\n if (Object.isFrozen(item)) item = item.slice(0);else set.add(item);\n for (let i = 0, l = item.length; i < l; i++) {\n v = item[i];\n if ((unwrapped = unwrap(v, set)) !== v) item[i] = unwrapped;\n }\n } else {\n if (Object.isFrozen(item)) item = Object.assign({}, item);else set.add(item);\n const keys = Object.keys(item),\n desc = Object.getOwnPropertyDescriptors(item);\n for (let i = 0, l = keys.length; i < l; i++) {\n prop = keys[i];\n if (desc[prop].get) continue;\n v = item[prop];\n if ((unwrapped = unwrap(v, set)) !== v) item[prop] = unwrapped;\n }\n }\n return item;\n}\nfunction getNodes(target, symbol) {\n let nodes = target[symbol];\n if (!nodes) Object.defineProperty(target, symbol, {\n value: nodes = Object.create(null)\n });\n return nodes;\n}\nfunction getNode(nodes, property, value) {\n if (nodes[property]) return nodes[property];\n const [s, set] = createSignal(value, {\n equals: false,\n internal: true\n });\n s.$ = set;\n return nodes[property] = s;\n}\nfunction proxyDescriptor$1(target, property) {\n const desc = Reflect.getOwnPropertyDescriptor(target, property);\n if (!desc || desc.get || !desc.configurable || property === $PROXY || property === $NODE) return desc;\n delete desc.value;\n delete desc.writable;\n desc.get = () => target[$PROXY][property];\n return desc;\n}\nfunction trackSelf(target) {\n getListener() && getNode(getNodes(target, $NODE), $SELF)();\n}\nfunction ownKeys(target) {\n trackSelf(target);\n return Reflect.ownKeys(target);\n}\nconst proxyTraps$1 = {\n get(target, property, receiver) {\n if (property === $RAW) return target;\n if (property === $PROXY) return receiver;\n if (property === $TRACK) {\n trackSelf(target);\n return receiver;\n }\n const nodes = getNodes(target, $NODE);\n const tracked = nodes[property];\n let value = tracked ? tracked() : target[property];\n if (property === $NODE || property === $HAS || property === \"__proto__\") return value;\n if (!tracked) {\n const desc = Object.getOwnPropertyDescriptor(target, property);\n if (getListener() && (typeof value !== \"function\" || target.hasOwnProperty(property)) && !(desc && desc.get)) value = getNode(nodes, property, value)();\n }\n return isWrappable(value) ? wrap$1(value) : value;\n },\n has(target, property) {\n if (property === $RAW || property === $PROXY || property === $TRACK || property === $NODE || property === $HAS || property === \"__proto__\") return true;\n getListener() && getNode(getNodes(target, $HAS), property)();\n return property in target;\n },\n set() {\n console.warn(\"Cannot mutate a Store directly\");\n return true;\n },\n deleteProperty() {\n console.warn(\"Cannot mutate a Store directly\");\n return true;\n },\n ownKeys: ownKeys,\n getOwnPropertyDescriptor: proxyDescriptor$1\n};\nfunction setProperty(state, property, value, deleting = false) {\n if (!deleting && state[property] === value) return;\n const prev = state[property],\n len = state.length;\n DevHooks.onStoreNodeUpdate && DevHooks.onStoreNodeUpdate(state, property, value, prev);\n if (value === undefined) {\n delete state[property];\n if (state[$HAS] && state[$HAS][property] && prev !== undefined) state[$HAS][property].$();\n } else {\n state[property] = value;\n if (state[$HAS] && state[$HAS][property] && prev === undefined) state[$HAS][property].$();\n }\n let nodes = getNodes(state, $NODE),\n node;\n if (node = getNode(nodes, property, prev)) node.$(() => value);\n if (Array.isArray(state) && state.length !== len) {\n for (let i = state.length; i < len; i++) (node = nodes[i]) && node.$();\n (node = getNode(nodes, \"length\", len)) && node.$(state.length);\n }\n (node = nodes[$SELF]) && node.$();\n}\nfunction mergeStoreNode(state, value) {\n const keys = Object.keys(value);\n for (let i = 0; i < keys.length; i += 1) {\n const key = keys[i];\n setProperty(state, key, value[key]);\n }\n}\nfunction updateArray(current, next) {\n if (typeof next === \"function\") next = next(current);\n next = unwrap(next);\n if (Array.isArray(next)) {\n if (current === next) return;\n let i = 0,\n len = next.length;\n for (; i < len; i++) {\n const value = next[i];\n if (current[i] !== value) setProperty(current, i, value);\n }\n setProperty(current, \"length\", len);\n } else mergeStoreNode(current, next);\n}\nfunction updatePath(current, path, traversed = []) {\n let part,\n prev = current;\n if (path.length > 1) {\n part = path.shift();\n const partType = typeof part,\n isArray = Array.isArray(current);\n if (Array.isArray(part)) {\n for (let i = 0; i < part.length; i++) {\n updatePath(current, [part[i]].concat(path), traversed);\n }\n return;\n } else if (isArray && partType === \"function\") {\n for (let i = 0; i < current.length; i++) {\n if (part(current[i], i)) updatePath(current, [i].concat(path), traversed);\n }\n return;\n } else if (isArray && partType === \"object\") {\n const {\n from = 0,\n to = current.length - 1,\n by = 1\n } = part;\n for (let i = from; i <= to; i += by) {\n updatePath(current, [i].concat(path), traversed);\n }\n return;\n } else if (path.length > 1) {\n updatePath(current[part], path, [part].concat(traversed));\n return;\n }\n prev = current[part];\n traversed = [part].concat(traversed);\n }\n let value = path[0];\n if (typeof value === \"function\") {\n value = value(prev, traversed);\n if (value === prev) return;\n }\n if (part === undefined && value == undefined) return;\n value = unwrap(value);\n if (part === undefined || isWrappable(prev) && isWrappable(value) && !Array.isArray(value)) {\n mergeStoreNode(prev, value);\n } else setProperty(current, part, value);\n}\nfunction createStore(...[store, options]) {\n const unwrappedStore = unwrap(store || {});\n const isArray = Array.isArray(unwrappedStore);\n if (typeof unwrappedStore !== \"object\" && typeof unwrappedStore !== \"function\") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createStore'. Expected an object.`);\n const wrappedStore = wrap$1(unwrappedStore);\n DEV$1.registerGraph({\n value: unwrappedStore,\n name: options && options.name\n });\n function setStore(...args) {\n batch(() => {\n isArray && args.length === 1 ? updateArray(unwrappedStore, args[0]) : updatePath(unwrappedStore, args);\n });\n }\n return [wrappedStore, setStore];\n}\n\nfunction proxyDescriptor(target, property) {\n const desc = Reflect.getOwnPropertyDescriptor(target, property);\n if (!desc || desc.get || desc.set || !desc.configurable || property === $PROXY || property === $NODE) return desc;\n delete desc.value;\n delete desc.writable;\n desc.get = () => target[$PROXY][property];\n desc.set = v => target[$PROXY][property] = v;\n return desc;\n}\nconst proxyTraps = {\n get(target, property, receiver) {\n if (property === $RAW) return target;\n if (property === $PROXY) return receiver;\n if (property === $TRACK) {\n trackSelf(target);\n return receiver;\n }\n const nodes = getNodes(target, $NODE);\n const tracked = nodes[property];\n let value = tracked ? tracked() : target[property];\n if (property === $NODE || property === $HAS || property === \"__proto__\") return value;\n if (!tracked) {\n const desc = Object.getOwnPropertyDescriptor(target, property);\n const isFunction = typeof value === \"function\";\n if (getListener() && (!isFunction || target.hasOwnProperty(property)) && !(desc && desc.get)) value = getNode(nodes, property, value)();else if (value != null && isFunction && value === Array.prototype[property]) {\n return (...args) => batch(() => Array.prototype[property].apply(receiver, args));\n }\n }\n return isWrappable(value) ? wrap(value) : value;\n },\n has(target, property) {\n if (property === $RAW || property === $PROXY || property === $TRACK || property === $NODE || property === $HAS || property === \"__proto__\") return true;\n getListener() && getNode(getNodes(target, $HAS), property)();\n return property in target;\n },\n set(target, property, value) {\n batch(() => setProperty(target, property, unwrap(value)));\n return true;\n },\n deleteProperty(target, property) {\n batch(() => setProperty(target, property, undefined, true));\n return true;\n },\n ownKeys: ownKeys,\n getOwnPropertyDescriptor: proxyDescriptor\n};\nfunction wrap(value) {\n let p = value[$PROXY];\n if (!p) {\n Object.defineProperty(value, $PROXY, {\n value: p = new Proxy(value, proxyTraps)\n });\n const keys = Object.keys(value),\n desc = Object.getOwnPropertyDescriptors(value);\n const proto = Object.getPrototypeOf(value);\n const isClass = proto !== null && value !== null && typeof value === \"object\" && !Array.isArray(value) && proto !== Object.prototype;\n if (isClass) {\n const descriptors = Object.getOwnPropertyDescriptors(proto);\n keys.push(...Object.keys(descriptors));\n Object.assign(desc, descriptors);\n }\n for (let i = 0, l = keys.length; i < l; i++) {\n const prop = keys[i];\n if (isClass && prop === \"constructor\") continue;\n if (desc[prop].get) {\n const get = desc[prop].get.bind(p);\n Object.defineProperty(value, prop, {\n get,\n configurable: true\n });\n }\n if (desc[prop].set) {\n const og = desc[prop].set,\n set = v => batch(() => og.call(p, v));\n Object.defineProperty(value, prop, {\n set,\n configurable: true\n });\n }\n }\n }\n return p;\n}\nfunction createMutable(state, options) {\n const unwrappedStore = unwrap(state || {});\n if (typeof unwrappedStore !== \"object\" && typeof unwrappedStore !== \"function\") throw new Error(`Unexpected type ${typeof unwrappedStore} received when initializing 'createMutable'. Expected an object.`);\n const wrappedStore = wrap(unwrappedStore);\n DEV$1.registerGraph({\n value: unwrappedStore,\n name: options && options.name\n });\n return wrappedStore;\n}\nfunction modifyMutable(state, modifier) {\n batch(() => modifier(unwrap(state)));\n}\n\nconst $ROOT = Symbol(\"store-root\");\nfunction applyState(target, parent, property, merge, key) {\n const previous = parent[property];\n if (target === previous) return;\n const isArray = Array.isArray(target);\n if (property !== $ROOT && (!isWrappable(target) || !isWrappable(previous) || isArray !== Array.isArray(previous) || key && target[key] !== previous[key])) {\n setProperty(parent, property, target);\n return;\n }\n if (isArray) {\n if (target.length && previous.length && (!merge || key && target[0] && target[0][key] != null)) {\n let i, j, start, end, newEnd, item, newIndicesNext, keyVal;\n for (start = 0, end = Math.min(previous.length, target.length); start < end && (previous[start] === target[start] || key && previous[start] && target[start] && previous[start][key] === target[start][key]); start++) {\n applyState(target[start], previous, start, merge, key);\n }\n const temp = new Array(target.length),\n newIndices = new Map();\n for (end = previous.length - 1, newEnd = target.length - 1; end >= start && newEnd >= start && (previous[end] === target[newEnd] || key && previous[end] && target[newEnd] && previous[end][key] === target[newEnd][key]); end--, newEnd--) {\n temp[newEnd] = previous[end];\n }\n if (start > newEnd || start > end) {\n for (j = start; j <= newEnd; j++) setProperty(previous, j, target[j]);\n for (; j < target.length; j++) {\n setProperty(previous, j, temp[j]);\n applyState(target[j], previous, j, merge, key);\n }\n if (previous.length > target.length) setProperty(previous, \"length\", target.length);\n return;\n }\n newIndicesNext = new Array(newEnd + 1);\n for (j = newEnd; j >= start; j--) {\n item = target[j];\n keyVal = key && item ? item[key] : item;\n i = newIndices.get(keyVal);\n newIndicesNext[j] = i === undefined ? -1 : i;\n newIndices.set(keyVal, j);\n }\n for (i = start; i <= end; i++) {\n item = previous[i];\n keyVal = key && item ? item[key] : item;\n j = newIndices.get(keyVal);\n if (j !== undefined && j !== -1) {\n temp[j] = previous[i];\n j = newIndicesNext[j];\n newIndices.set(keyVal, j);\n }\n }\n for (j = start; j < target.length; j++) {\n if (j in temp) {\n setProperty(previous, j, temp[j]);\n applyState(target[j], previous, j, merge, key);\n } else setProperty(previous, j, target[j]);\n }\n } else {\n for (let i = 0, len = target.length; i < len; i++) {\n applyState(target[i], previous, i, merge, key);\n }\n }\n if (previous.length > target.length) setProperty(previous, \"length\", target.length);\n return;\n }\n const targetKeys = Object.keys(target);\n for (let i = 0, len = targetKeys.length; i < len; i++) {\n applyState(target[targetKeys[i]], previous, targetKeys[i], merge, key);\n }\n const previousKeys = Object.keys(previous);\n for (let i = 0, len = previousKeys.length; i < len; i++) {\n if (target[previousKeys[i]] === undefined) setProperty(previous, previousKeys[i], undefined);\n }\n}\nfunction reconcile(value, options = {}) {\n const {\n merge,\n key = \"id\"\n } = options,\n v = unwrap(value);\n return state => {\n if (!isWrappable(state) || !isWrappable(v)) return v;\n const res = applyState(v, {\n [$ROOT]: state\n }, $ROOT, merge, key);\n return res === undefined ? state : res;\n };\n}\nconst producers = new WeakMap();\nconst setterTraps = {\n get(target, property) {\n if (property === $RAW) return target;\n const value = target[property];\n let proxy;\n return isWrappable(value) ? producers.get(value) || (producers.set(value, proxy = new Proxy(value, setterTraps)), proxy) : value;\n },\n set(target, property, value) {\n setProperty(target, property, unwrap(value));\n return true;\n },\n deleteProperty(target, property) {\n setProperty(target, property, undefined, true);\n return true;\n }\n};\nfunction produce(fn) {\n return state => {\n if (isWrappable(state)) {\n let proxy;\n if (!(proxy = producers.get(state))) {\n producers.set(state, proxy = new Proxy(state, setterTraps));\n }\n fn(proxy);\n }\n return state;\n };\n}\n\nconst DEV = {\n $NODE,\n isWrappable,\n hooks: DevHooks\n} ;\n\nexport { $RAW, DEV, createMutable, createStore, modifyMutable, produce, reconcile, unwrap };\n"],
- "mappings": "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",
- "names": ["DEV"]
-}
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_web.js b/pulse-test-staging/frontend-modern/.vite/deps/solid-js_web.js
deleted file mode 100644
index da1373e9f..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_web.js
+++ /dev/null
@@ -1,865 +0,0 @@
-import {
- $DEVCOMP,
- ErrorBoundary,
- For,
- Index,
- Match,
- Show,
- Suspense,
- SuspenseList,
- Switch,
- createComponent,
- createEffect,
- createMemo,
- createRenderEffect,
- createRoot,
- createSignal,
- enableHydration,
- getOwner,
- mergeProps,
- onCleanup,
- runWithOwner,
- sharedConfig,
- splitProps,
- untrack
-} from "./chunk-IZS3CG5R.js";
-
-// node_modules/solid-js/web/dist/dev.js
-var booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "inert", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"];
-var Properties = /* @__PURE__ */ new Set(["className", "value", "readOnly", "noValidate", "formNoValidate", "isMap", "noModule", "playsInline", ...booleans]);
-var ChildProperties = /* @__PURE__ */ new Set(["innerHTML", "textContent", "innerText", "children"]);
-var Aliases = Object.assign(/* @__PURE__ */ Object.create(null), {
- className: "class",
- htmlFor: "for"
-});
-var PropAliases = Object.assign(/* @__PURE__ */ Object.create(null), {
- class: "className",
- novalidate: {
- $: "noValidate",
- FORM: 1
- },
- formnovalidate: {
- $: "formNoValidate",
- BUTTON: 1,
- INPUT: 1
- },
- ismap: {
- $: "isMap",
- IMG: 1
- },
- nomodule: {
- $: "noModule",
- SCRIPT: 1
- },
- playsinline: {
- $: "playsInline",
- VIDEO: 1
- },
- readonly: {
- $: "readOnly",
- INPUT: 1,
- TEXTAREA: 1
- }
-});
-function getPropAlias(prop, tagName) {
- const a = PropAliases[prop];
- return typeof a === "object" ? a[tagName] ? a["$"] : void 0 : a;
-}
-var DelegatedEvents = /* @__PURE__ */ new Set(["beforeinput", "click", "dblclick", "contextmenu", "focusin", "focusout", "input", "keydown", "keyup", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "pointerdown", "pointermove", "pointerout", "pointerover", "pointerup", "touchend", "touchmove", "touchstart"]);
-var SVGElements = /* @__PURE__ */ new Set([
- "altGlyph",
- "altGlyphDef",
- "altGlyphItem",
- "animate",
- "animateColor",
- "animateMotion",
- "animateTransform",
- "circle",
- "clipPath",
- "color-profile",
- "cursor",
- "defs",
- "desc",
- "ellipse",
- "feBlend",
- "feColorMatrix",
- "feComponentTransfer",
- "feComposite",
- "feConvolveMatrix",
- "feDiffuseLighting",
- "feDisplacementMap",
- "feDistantLight",
- "feDropShadow",
- "feFlood",
- "feFuncA",
- "feFuncB",
- "feFuncG",
- "feFuncR",
- "feGaussianBlur",
- "feImage",
- "feMerge",
- "feMergeNode",
- "feMorphology",
- "feOffset",
- "fePointLight",
- "feSpecularLighting",
- "feSpotLight",
- "feTile",
- "feTurbulence",
- "filter",
- "font",
- "font-face",
- "font-face-format",
- "font-face-name",
- "font-face-src",
- "font-face-uri",
- "foreignObject",
- "g",
- "glyph",
- "glyphRef",
- "hkern",
- "image",
- "line",
- "linearGradient",
- "marker",
- "mask",
- "metadata",
- "missing-glyph",
- "mpath",
- "path",
- "pattern",
- "polygon",
- "polyline",
- "radialGradient",
- "rect",
- "set",
- "stop",
- "svg",
- "switch",
- "symbol",
- "text",
- "textPath",
- "tref",
- "tspan",
- "use",
- "view",
- "vkern"
-]);
-var SVGNamespace = {
- xlink: "http://www.w3.org/1999/xlink",
- xml: "http://www.w3.org/XML/1998/namespace"
-};
-var DOMElements = /* @__PURE__ */ new Set(["html", "base", "head", "link", "meta", "style", "title", "body", "address", "article", "aside", "footer", "header", "main", "nav", "section", "body", "blockquote", "dd", "div", "dl", "dt", "figcaption", "figure", "hr", "li", "ol", "p", "pre", "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn", "em", "i", "kbd", "mark", "q", "rp", "rt", "ruby", "s", "samp", "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "area", "audio", "img", "map", "track", "video", "embed", "iframe", "object", "param", "picture", "portal", "source", "svg", "math", "canvas", "noscript", "script", "del", "ins", "caption", "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "button", "datalist", "fieldset", "form", "input", "label", "legend", "meter", "optgroup", "option", "output", "progress", "select", "textarea", "details", "dialog", "menu", "summary", "details", "slot", "template", "acronym", "applet", "basefont", "bgsound", "big", "blink", "center", "content", "dir", "font", "frame", "frameset", "hgroup", "image", "keygen", "marquee", "menuitem", "nobr", "noembed", "noframes", "plaintext", "rb", "rtc", "shadow", "spacer", "strike", "tt", "xmp", "a", "abbr", "acronym", "address", "applet", "area", "article", "aside", "audio", "b", "base", "basefont", "bdi", "bdo", "bgsound", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "font", "footer", "form", "frame", "frameset", "head", "header", "hgroup", "hr", "html", "i", "iframe", "image", "img", "input", "ins", "kbd", "keygen", "label", "legend", "li", "link", "main", "map", "mark", "marquee", "menu", "menuitem", "meta", "meter", "nav", "nobr", "noembed", "noframes", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "plaintext", "portal", "pre", "progress", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp", "script", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "tt", "u", "ul", "var", "video", "wbr", "xmp", "input", "h1", "h2", "h3", "h4", "h5", "h6"]);
-var memo = (fn) => createMemo(() => fn());
-function reconcileArrays(parentNode, a, b) {
- let bLength = b.length, aEnd = a.length, bEnd = bLength, aStart = 0, bStart = 0, after = a[aEnd - 1].nextSibling, map = null;
- while (aStart < aEnd || bStart < bEnd) {
- if (a[aStart] === b[bStart]) {
- aStart++;
- bStart++;
- continue;
- }
- while (a[aEnd - 1] === b[bEnd - 1]) {
- aEnd--;
- bEnd--;
- }
- if (aEnd === aStart) {
- const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] : after;
- while (bStart < bEnd) parentNode.insertBefore(b[bStart++], node);
- } else if (bEnd === bStart) {
- while (aStart < aEnd) {
- if (!map || !map.has(a[aStart])) a[aStart].remove();
- aStart++;
- }
- } else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
- const node = a[--aEnd].nextSibling;
- parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling);
- parentNode.insertBefore(b[--bEnd], node);
- a[aEnd] = b[bEnd];
- } else {
- if (!map) {
- map = /* @__PURE__ */ new Map();
- let i = bStart;
- while (i < bEnd) map.set(b[i], i++);
- }
- const index = map.get(a[aStart]);
- if (index != null) {
- if (bStart < index && index < bEnd) {
- let i = aStart, sequence = 1, t;
- while (++i < aEnd && i < bEnd) {
- if ((t = map.get(a[i])) == null || t !== index + sequence) break;
- sequence++;
- }
- if (sequence > index - bStart) {
- const node = a[aStart];
- while (bStart < index) parentNode.insertBefore(b[bStart++], node);
- } else parentNode.replaceChild(b[bStart++], a[aStart++]);
- } else aStart++;
- } else a[aStart++].remove();
- }
- }
-}
-var $$EVENTS = "_$DX_DELEGATE";
-function render(code, element, init, options = {}) {
- if (!element) {
- throw new Error("The `element` passed to `render(..., element)` doesn't exist. Make sure `element` exists in the document.");
- }
- let disposer;
- createRoot((dispose) => {
- disposer = dispose;
- element === document ? code() : insert(element, code(), element.firstChild ? null : void 0, init);
- }, options.owner);
- return () => {
- disposer();
- element.textContent = "";
- };
-}
-function template(html, isImportNode, isSVG, isMathML) {
- let node;
- const create = () => {
- if (isHydrating()) throw new Error("Failed attempt to create new DOM elements during hydration. Check that the libraries you are using support hydration.");
- const t = isMathML ? document.createElementNS("http://www.w3.org/1998/Math/MathML", "template") : document.createElement("template");
- t.innerHTML = html;
- return isSVG ? t.content.firstChild.firstChild : isMathML ? t.firstChild : t.content.firstChild;
- };
- const fn = isImportNode ? () => untrack(() => document.importNode(node || (node = create()), true)) : () => (node || (node = create())).cloneNode(true);
- fn.cloneNode = fn;
- return fn;
-}
-function delegateEvents(eventNames, document2 = window.document) {
- const e = document2[$$EVENTS] || (document2[$$EVENTS] = /* @__PURE__ */ new Set());
- for (let i = 0, l = eventNames.length; i < l; i++) {
- const name = eventNames[i];
- if (!e.has(name)) {
- e.add(name);
- document2.addEventListener(name, eventHandler);
- }
- }
-}
-function clearDelegatedEvents(document2 = window.document) {
- if (document2[$$EVENTS]) {
- for (let name of document2[$$EVENTS].keys()) document2.removeEventListener(name, eventHandler);
- delete document2[$$EVENTS];
- }
-}
-function setProperty(node, name, value) {
- if (isHydrating(node)) return;
- node[name] = value;
-}
-function setAttribute(node, name, value) {
- if (isHydrating(node)) return;
- if (value == null) node.removeAttribute(name);
- else node.setAttribute(name, value);
-}
-function setAttributeNS(node, namespace, name, value) {
- if (isHydrating(node)) return;
- if (value == null) node.removeAttributeNS(namespace, name);
- else node.setAttributeNS(namespace, name, value);
-}
-function setBoolAttribute(node, name, value) {
- if (isHydrating(node)) return;
- value ? node.setAttribute(name, "") : node.removeAttribute(name);
-}
-function className(node, value) {
- if (isHydrating(node)) return;
- if (value == null) node.removeAttribute("class");
- else node.className = value;
-}
-function addEventListener(node, name, handler, delegate) {
- if (delegate) {
- if (Array.isArray(handler)) {
- node[`$$${name}`] = handler[0];
- node[`$$${name}Data`] = handler[1];
- } else node[`$$${name}`] = handler;
- } else if (Array.isArray(handler)) {
- const handlerFn = handler[0];
- node.addEventListener(name, handler[0] = (e) => handlerFn.call(node, handler[1], e));
- } else node.addEventListener(name, handler, typeof handler !== "function" && handler);
-}
-function classList(node, value, prev = {}) {
- const classKeys = Object.keys(value || {}), prevKeys = Object.keys(prev);
- let i, len;
- for (i = 0, len = prevKeys.length; i < len; i++) {
- const key = prevKeys[i];
- if (!key || key === "undefined" || value[key]) continue;
- toggleClassKey(node, key, false);
- delete prev[key];
- }
- for (i = 0, len = classKeys.length; i < len; i++) {
- const key = classKeys[i], classValue = !!value[key];
- if (!key || key === "undefined" || prev[key] === classValue || !classValue) continue;
- toggleClassKey(node, key, true);
- prev[key] = classValue;
- }
- return prev;
-}
-function style(node, value, prev) {
- if (!value) return prev ? setAttribute(node, "style") : value;
- const nodeStyle = node.style;
- if (typeof value === "string") return nodeStyle.cssText = value;
- typeof prev === "string" && (nodeStyle.cssText = prev = void 0);
- prev || (prev = {});
- value || (value = {});
- let v, s;
- for (s in prev) {
- value[s] == null && nodeStyle.removeProperty(s);
- delete prev[s];
- }
- for (s in value) {
- v = value[s];
- if (v !== prev[s]) {
- nodeStyle.setProperty(s, v);
- prev[s] = v;
- }
- }
- return prev;
-}
-function spread(node, props = {}, isSVG, skipChildren) {
- const prevProps = {};
- if (!skipChildren) {
- createRenderEffect(() => prevProps.children = insertExpression(node, props.children, prevProps.children));
- }
- createRenderEffect(() => typeof props.ref === "function" && use(props.ref, node));
- createRenderEffect(() => assign(node, props, isSVG, true, prevProps, true));
- return prevProps;
-}
-function dynamicProperty(props, key) {
- const src = props[key];
- Object.defineProperty(props, key, {
- get() {
- return src();
- },
- enumerable: true
- });
- return props;
-}
-function use(fn, element, arg) {
- return untrack(() => fn(element, arg));
-}
-function insert(parent, accessor, marker, initial) {
- if (marker !== void 0 && !initial) initial = [];
- if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker);
- createRenderEffect((current) => insertExpression(parent, accessor(), current, marker), initial);
-}
-function assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = false) {
- props || (props = {});
- for (const prop in prevProps) {
- if (!(prop in props)) {
- if (prop === "children") continue;
- prevProps[prop] = assignProp(node, prop, null, prevProps[prop], isSVG, skipRef, props);
- }
- }
- for (const prop in props) {
- if (prop === "children") {
- if (!skipChildren) insertExpression(node, props.children);
- continue;
- }
- const value = props[prop];
- prevProps[prop] = assignProp(node, prop, value, prevProps[prop], isSVG, skipRef, props);
- }
-}
-function hydrate$1(code, element, options = {}) {
- if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);
- sharedConfig.completed = globalThis._$HY.completed;
- sharedConfig.events = globalThis._$HY.events;
- sharedConfig.load = (id) => globalThis._$HY.r[id];
- sharedConfig.has = (id) => id in globalThis._$HY.r;
- sharedConfig.gather = (root) => gatherHydratable(element, root);
- sharedConfig.registry = /* @__PURE__ */ new Map();
- sharedConfig.context = {
- id: options.renderId || "",
- count: 0
- };
- try {
- gatherHydratable(element, options.renderId);
- return render(code, element, [...element.childNodes], options);
- } finally {
- sharedConfig.context = null;
- }
-}
-function getNextElement(template2) {
- let node, key, hydrating = isHydrating();
- if (!hydrating || !(node = sharedConfig.registry.get(key = getHydrationKey()))) {
- if (hydrating) {
- sharedConfig.done = true;
- throw new Error(`Hydration Mismatch. Unable to find DOM nodes for hydration key: ${key}
-${template2 ? template2().outerHTML : ""}`);
- }
- return template2();
- }
- if (sharedConfig.completed) sharedConfig.completed.add(node);
- sharedConfig.registry.delete(key);
- return node;
-}
-function getNextMatch(el, nodeName) {
- while (el && el.localName !== nodeName) el = el.nextSibling;
- return el;
-}
-function getNextMarker(start) {
- let end = start, count = 0, current = [];
- if (isHydrating(start)) {
- while (end) {
- if (end.nodeType === 8) {
- const v = end.nodeValue;
- if (v === "$") count++;
- else if (v === "/") {
- if (count === 0) return [end, current];
- count--;
- }
- }
- current.push(end);
- end = end.nextSibling;
- }
- }
- return [end, current];
-}
-function runHydrationEvents() {
- if (sharedConfig.events && !sharedConfig.events.queued) {
- queueMicrotask(() => {
- const {
- completed,
- events
- } = sharedConfig;
- if (!events) return;
- events.queued = false;
- while (events.length) {
- const [el, e] = events[0];
- if (!completed.has(el)) return;
- events.shift();
- eventHandler(e);
- }
- if (sharedConfig.done) {
- sharedConfig.events = _$HY.events = null;
- sharedConfig.completed = _$HY.completed = null;
- }
- });
- sharedConfig.events.queued = true;
- }
-}
-function isHydrating(node) {
- return !!sharedConfig.context && !sharedConfig.done && (!node || node.isConnected);
-}
-function toPropertyName(name) {
- return name.toLowerCase().replace(/-([a-z])/g, (_, w) => w.toUpperCase());
-}
-function toggleClassKey(node, key, value) {
- const classNames = key.trim().split(/\s+/);
- for (let i = 0, nameLen = classNames.length; i < nameLen; i++) node.classList.toggle(classNames[i], value);
-}
-function assignProp(node, prop, value, prev, isSVG, skipRef, props) {
- let isCE, isProp, isChildProp, propAlias, forceProp;
- if (prop === "style") return style(node, value, prev);
- if (prop === "classList") return classList(node, value, prev);
- if (value === prev) return prev;
- if (prop === "ref") {
- if (!skipRef) value(node);
- } else if (prop.slice(0, 3) === "on:") {
- const e = prop.slice(3);
- prev && node.removeEventListener(e, prev, typeof prev !== "function" && prev);
- value && node.addEventListener(e, value, typeof value !== "function" && value);
- } else if (prop.slice(0, 10) === "oncapture:") {
- const e = prop.slice(10);
- prev && node.removeEventListener(e, prev, true);
- value && node.addEventListener(e, value, true);
- } else if (prop.slice(0, 2) === "on") {
- const name = prop.slice(2).toLowerCase();
- const delegate = DelegatedEvents.has(name);
- if (!delegate && prev) {
- const h = Array.isArray(prev) ? prev[0] : prev;
- node.removeEventListener(name, h);
- }
- if (delegate || value) {
- addEventListener(node, name, value, delegate);
- delegate && delegateEvents([name]);
- }
- } else if (prop.slice(0, 5) === "attr:") {
- setAttribute(node, prop.slice(5), value);
- } else if (prop.slice(0, 5) === "bool:") {
- setBoolAttribute(node, prop.slice(5), value);
- } else if ((forceProp = prop.slice(0, 5) === "prop:") || (isChildProp = ChildProperties.has(prop)) || !isSVG && ((propAlias = getPropAlias(prop, node.tagName)) || (isProp = Properties.has(prop))) || (isCE = node.nodeName.includes("-") || "is" in props)) {
- if (forceProp) {
- prop = prop.slice(5);
- isProp = true;
- } else if (isHydrating(node)) return value;
- if (prop === "class" || prop === "className") className(node, value);
- else if (isCE && !isProp && !isChildProp) node[toPropertyName(prop)] = value;
- else node[propAlias || prop] = value;
- } else {
- const ns = isSVG && prop.indexOf(":") > -1 && SVGNamespace[prop.split(":")[0]];
- if (ns) setAttributeNS(node, ns, prop, value);
- else setAttribute(node, Aliases[prop] || prop, value);
- }
- return value;
-}
-function eventHandler(e) {
- if (sharedConfig.registry && sharedConfig.events) {
- if (sharedConfig.events.find(([el, ev]) => ev === e)) return;
- }
- let node = e.target;
- const key = `$$${e.type}`;
- const oriTarget = e.target;
- const oriCurrentTarget = e.currentTarget;
- const retarget = (value) => Object.defineProperty(e, "target", {
- configurable: true,
- value
- });
- const handleNode = () => {
- const handler = node[key];
- if (handler && !node.disabled) {
- const data = node[`${key}Data`];
- data !== void 0 ? handler.call(node, data, e) : handler.call(node, e);
- if (e.cancelBubble) return;
- }
- node.host && typeof node.host !== "string" && !node.host._$host && node.contains(e.target) && retarget(node.host);
- return true;
- };
- const walkUpTree = () => {
- while (handleNode() && (node = node._$host || node.parentNode || node.host)) ;
- };
- Object.defineProperty(e, "currentTarget", {
- configurable: true,
- get() {
- return node || document;
- }
- });
- if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = _$HY.done = true;
- if (e.composedPath) {
- const path = e.composedPath();
- retarget(path[0]);
- for (let i = 0; i < path.length - 2; i++) {
- node = path[i];
- if (!handleNode()) break;
- if (node._$host) {
- node = node._$host;
- walkUpTree();
- break;
- }
- if (node.parentNode === oriCurrentTarget) {
- break;
- }
- }
- } else walkUpTree();
- retarget(oriTarget);
-}
-function insertExpression(parent, value, current, marker, unwrapArray) {
- const hydrating = isHydrating(parent);
- if (hydrating) {
- !current && (current = [...parent.childNodes]);
- let cleaned = [];
- for (let i = 0; i < current.length; i++) {
- const node = current[i];
- if (node.nodeType === 8 && node.data.slice(0, 2) === "!$") node.remove();
- else cleaned.push(node);
- }
- current = cleaned;
- }
- while (typeof current === "function") current = current();
- if (value === current) return current;
- const t = typeof value, multi = marker !== void 0;
- parent = multi && current[0] && current[0].parentNode || parent;
- if (t === "string" || t === "number") {
- if (hydrating) return current;
- if (t === "number") {
- value = value.toString();
- if (value === current) return current;
- }
- if (multi) {
- let node = current[0];
- if (node && node.nodeType === 3) {
- node.data !== value && (node.data = value);
- } else node = document.createTextNode(value);
- current = cleanChildren(parent, current, marker, node);
- } else {
- if (current !== "" && typeof current === "string") {
- current = parent.firstChild.data = value;
- } else current = parent.textContent = value;
- }
- } else if (value == null || t === "boolean") {
- if (hydrating) return current;
- current = cleanChildren(parent, current, marker);
- } else if (t === "function") {
- createRenderEffect(() => {
- let v = value();
- while (typeof v === "function") v = v();
- current = insertExpression(parent, v, current, marker);
- });
- return () => current;
- } else if (Array.isArray(value)) {
- const array = [];
- const currentArray = current && Array.isArray(current);
- if (normalizeIncomingArray(array, value, current, unwrapArray)) {
- createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
- return () => current;
- }
- if (hydrating) {
- if (!array.length) return current;
- if (marker === void 0) return current = [...parent.childNodes];
- let node = array[0];
- if (node.parentNode !== parent) return current;
- const nodes = [node];
- while ((node = node.nextSibling) !== marker) nodes.push(node);
- return current = nodes;
- }
- if (array.length === 0) {
- current = cleanChildren(parent, current, marker);
- if (multi) return current;
- } else if (currentArray) {
- if (current.length === 0) {
- appendNodes(parent, array, marker);
- } else reconcileArrays(parent, current, array);
- } else {
- current && cleanChildren(parent);
- appendNodes(parent, array);
- }
- current = array;
- } else if (value.nodeType) {
- if (hydrating && value.parentNode) return current = multi ? [value] : value;
- if (Array.isArray(current)) {
- if (multi) return current = cleanChildren(parent, current, marker, value);
- cleanChildren(parent, current, null, value);
- } else if (current == null || current === "" || !parent.firstChild) {
- parent.appendChild(value);
- } else parent.replaceChild(value, parent.firstChild);
- current = value;
- } else console.warn(`Unrecognized value. Skipped inserting`, value);
- return current;
-}
-function normalizeIncomingArray(normalized, array, current, unwrap) {
- let dynamic = false;
- for (let i = 0, len = array.length; i < len; i++) {
- let item = array[i], prev = current && current[normalized.length], t;
- if (item == null || item === true || item === false) ;
- else if ((t = typeof item) === "object" && item.nodeType) {
- normalized.push(item);
- } else if (Array.isArray(item)) {
- dynamic = normalizeIncomingArray(normalized, item, prev) || dynamic;
- } else if (t === "function") {
- if (unwrap) {
- while (typeof item === "function") item = item();
- dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item], Array.isArray(prev) ? prev : [prev]) || dynamic;
- } else {
- normalized.push(item);
- dynamic = true;
- }
- } else {
- const value = String(item);
- if (prev && prev.nodeType === 3 && prev.data === value) normalized.push(prev);
- else normalized.push(document.createTextNode(value));
- }
- }
- return dynamic;
-}
-function appendNodes(parent, array, marker = null) {
- for (let i = 0, len = array.length; i < len; i++) parent.insertBefore(array[i], marker);
-}
-function cleanChildren(parent, current, marker, replacement) {
- if (marker === void 0) return parent.textContent = "";
- const node = replacement || document.createTextNode("");
- if (current.length) {
- let inserted = false;
- for (let i = current.length - 1; i >= 0; i--) {
- const el = current[i];
- if (node !== el) {
- const isParent = el.parentNode === parent;
- if (!inserted && !i) isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);
- else isParent && el.remove();
- } else inserted = true;
- }
- } else parent.insertBefore(node, marker);
- return [node];
-}
-function gatherHydratable(element, root) {
- const templates = element.querySelectorAll(`*[data-hk]`);
- for (let i = 0; i < templates.length; i++) {
- const node = templates[i];
- const key = node.getAttribute("data-hk");
- if ((!root || key.startsWith(root)) && !sharedConfig.registry.has(key)) sharedConfig.registry.set(key, node);
- }
-}
-function getHydrationKey() {
- return sharedConfig.getNextContextId();
-}
-function NoHydration(props) {
- return sharedConfig.context ? void 0 : props.children;
-}
-function Hydration(props) {
- return props.children;
-}
-var voidFn = () => void 0;
-var RequestContext = Symbol();
-function innerHTML(parent, content) {
- !sharedConfig.context && (parent.innerHTML = content);
-}
-function throwInBrowser(func) {
- const err = new Error(`${func.name} is not supported in the browser, returning undefined`);
- console.error(err);
-}
-function renderToString(fn, options) {
- throwInBrowser(renderToString);
-}
-function renderToStringAsync(fn, options) {
- throwInBrowser(renderToStringAsync);
-}
-function renderToStream(fn, options) {
- throwInBrowser(renderToStream);
-}
-function ssr(template2, ...nodes) {
-}
-function ssrElement(name, props, children, needsId) {
-}
-function ssrClassList(value) {
-}
-function ssrStyle(value) {
-}
-function ssrAttribute(key, value) {
-}
-function ssrHydrationKey() {
-}
-function resolveSSRNode(node) {
-}
-function escape(html) {
-}
-function ssrSpread(props, isSVG, skipChildren) {
-}
-var isServer = false;
-var isDev = true;
-var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
-function createElement(tagName, isSVG = false) {
- return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);
-}
-var hydrate = (...args) => {
- enableHydration();
- return hydrate$1(...args);
-};
-function Portal(props) {
- const {
- useShadow
- } = props, marker = document.createTextNode(""), mount = () => props.mount || document.body, owner = getOwner();
- let content;
- let hydrating = !!sharedConfig.context;
- createEffect(() => {
- if (hydrating) getOwner().user = hydrating = false;
- content || (content = runWithOwner(owner, () => createMemo(() => props.children)));
- const el = mount();
- if (el instanceof HTMLHeadElement) {
- const [clean, setClean] = createSignal(false);
- const cleanup = () => setClean(true);
- createRoot((dispose) => insert(el, () => !clean() ? content() : dispose(), null));
- onCleanup(cleanup);
- } else {
- const container = createElement(props.isSVG ? "g" : "div", props.isSVG), renderRoot = useShadow && container.attachShadow ? container.attachShadow({
- mode: "open"
- }) : container;
- Object.defineProperty(container, "_$host", {
- get() {
- return marker.parentNode;
- },
- configurable: true
- });
- insert(renderRoot, content);
- el.appendChild(container);
- props.ref && props.ref(container);
- onCleanup(() => el.removeChild(container));
- }
- }, void 0, {
- render: !hydrating
- });
- return marker;
-}
-function createDynamic(component, props) {
- const cached = createMemo(component);
- return createMemo(() => {
- const component2 = cached();
- switch (typeof component2) {
- case "function":
- Object.assign(component2, {
- [$DEVCOMP]: true
- });
- return untrack(() => component2(props));
- case "string":
- const isSvg = SVGElements.has(component2);
- const el = sharedConfig.context ? getNextElement() : createElement(component2, isSvg);
- spread(el, props, isSvg);
- return el;
- }
- });
-}
-function Dynamic(props) {
- const [, others] = splitProps(props, ["component"]);
- return createDynamic(() => props.component, others);
-}
-export {
- Aliases,
- voidFn as Assets,
- ChildProperties,
- DOMElements,
- DelegatedEvents,
- Dynamic,
- ErrorBoundary,
- For,
- Hydration,
- voidFn as HydrationScript,
- Index,
- Match,
- NoHydration,
- Portal,
- Properties,
- RequestContext,
- SVGElements,
- SVGNamespace,
- Show,
- Suspense,
- SuspenseList,
- Switch,
- addEventListener,
- assign,
- classList,
- className,
- clearDelegatedEvents,
- createComponent,
- createDynamic,
- delegateEvents,
- dynamicProperty,
- createRenderEffect as effect,
- escape,
- voidFn as generateHydrationScript,
- voidFn as getAssets,
- getHydrationKey,
- getNextElement,
- getNextMarker,
- getNextMatch,
- getOwner,
- getPropAlias,
- voidFn as getRequestEvent,
- hydrate,
- innerHTML,
- insert,
- isDev,
- isServer,
- memo,
- mergeProps,
- render,
- renderToStream,
- renderToString,
- renderToStringAsync,
- resolveSSRNode,
- runHydrationEvents,
- setAttribute,
- setAttributeNS,
- setBoolAttribute,
- setProperty,
- spread,
- ssr,
- ssrAttribute,
- ssrClassList,
- ssrElement,
- ssrHydrationKey,
- ssrSpread,
- ssrStyle,
- style,
- template,
- untrack,
- use,
- voidFn as useAssets
-};
-//# sourceMappingURL=solid-js_web.js.map
diff --git a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_web.js.map b/pulse-test-staging/frontend-modern/.vite/deps/solid-js_web.js.map
deleted file mode 100644
index 102c4fca2..000000000
--- a/pulse-test-staging/frontend-modern/.vite/deps/solid-js_web.js.map
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "version": 3,
- "sources": ["../../node_modules/solid-js/web/dist/dev.js"],
- "sourcesContent": ["import { createMemo, createRoot, createRenderEffect, untrack, sharedConfig, enableHydration, getOwner, createEffect, runWithOwner, createSignal, onCleanup, $DEVCOMP, splitProps } from 'solid-js';\nexport { ErrorBoundary, For, Index, Match, Show, Suspense, SuspenseList, Switch, createComponent, createRenderEffect as effect, getOwner, mergeProps, untrack } from 'solid-js';\n\nconst booleans = [\"allowfullscreen\", \"async\", \"autofocus\", \"autoplay\", \"checked\", \"controls\", \"default\", \"disabled\", \"formnovalidate\", \"hidden\", \"indeterminate\", \"inert\", \"ismap\", \"loop\", \"multiple\", \"muted\", \"nomodule\", \"novalidate\", \"open\", \"playsinline\", \"readonly\", \"required\", \"reversed\", \"seamless\", \"selected\"];\nconst Properties = /*#__PURE__*/new Set([\"className\", \"value\", \"readOnly\", \"noValidate\", \"formNoValidate\", \"isMap\", \"noModule\", \"playsInline\", ...booleans]);\nconst ChildProperties = /*#__PURE__*/new Set([\"innerHTML\", \"textContent\", \"innerText\", \"children\"]);\nconst Aliases = /*#__PURE__*/Object.assign(Object.create(null), {\n className: \"class\",\n htmlFor: \"for\"\n});\nconst PropAliases = /*#__PURE__*/Object.assign(Object.create(null), {\n class: \"className\",\n novalidate: {\n $: \"noValidate\",\n FORM: 1\n },\n formnovalidate: {\n $: \"formNoValidate\",\n BUTTON: 1,\n INPUT: 1\n },\n ismap: {\n $: \"isMap\",\n IMG: 1\n },\n nomodule: {\n $: \"noModule\",\n SCRIPT: 1\n },\n playsinline: {\n $: \"playsInline\",\n VIDEO: 1\n },\n readonly: {\n $: \"readOnly\",\n INPUT: 1,\n TEXTAREA: 1\n }\n});\nfunction getPropAlias(prop, tagName) {\n const a = PropAliases[prop];\n return typeof a === \"object\" ? a[tagName] ? a[\"$\"] : undefined : a;\n}\nconst DelegatedEvents = /*#__PURE__*/new Set([\"beforeinput\", \"click\", \"dblclick\", \"contextmenu\", \"focusin\", \"focusout\", \"input\", \"keydown\", \"keyup\", \"mousedown\", \"mousemove\", \"mouseout\", \"mouseover\", \"mouseup\", \"pointerdown\", \"pointermove\", \"pointerout\", \"pointerover\", \"pointerup\", \"touchend\", \"touchmove\", \"touchstart\"]);\nconst SVGElements = /*#__PURE__*/new Set([\n\"altGlyph\", \"altGlyphDef\", \"altGlyphItem\", \"animate\", \"animateColor\", \"animateMotion\", \"animateTransform\", \"circle\", \"clipPath\", \"color-profile\", \"cursor\", \"defs\", \"desc\", \"ellipse\", \"feBlend\", \"feColorMatrix\", \"feComponentTransfer\", \"feComposite\", \"feConvolveMatrix\", \"feDiffuseLighting\", \"feDisplacementMap\", \"feDistantLight\", \"feDropShadow\", \"feFlood\", \"feFuncA\", \"feFuncB\", \"feFuncG\", \"feFuncR\", \"feGaussianBlur\", \"feImage\", \"feMerge\", \"feMergeNode\", \"feMorphology\", \"feOffset\", \"fePointLight\", \"feSpecularLighting\", \"feSpotLight\", \"feTile\", \"feTurbulence\", \"filter\", \"font\", \"font-face\", \"font-face-format\", \"font-face-name\", \"font-face-src\", \"font-face-uri\", \"foreignObject\", \"g\", \"glyph\", \"glyphRef\", \"hkern\", \"image\", \"line\", \"linearGradient\", \"marker\", \"mask\", \"metadata\", \"missing-glyph\", \"mpath\", \"path\", \"pattern\", \"polygon\", \"polyline\", \"radialGradient\", \"rect\",\n\"set\", \"stop\",\n\"svg\", \"switch\", \"symbol\", \"text\", \"textPath\",\n\"tref\", \"tspan\", \"use\", \"view\", \"vkern\"]);\nconst SVGNamespace = {\n xlink: \"http://www.w3.org/1999/xlink\",\n xml: \"http://www.w3.org/XML/1998/namespace\"\n};\nconst DOMElements = /*#__PURE__*/new Set([\"html\", \"base\", \"head\", \"link\", \"meta\", \"style\", \"title\", \"body\", \"address\", \"article\", \"aside\", \"footer\", \"header\", \"main\", \"nav\", \"section\", \"body\", \"blockquote\", \"dd\", \"div\", \"dl\", \"dt\", \"figcaption\", \"figure\", \"hr\", \"li\", \"ol\", \"p\", \"pre\", \"ul\", \"a\", \"abbr\", \"b\", \"bdi\", \"bdo\", \"br\", \"cite\", \"code\", \"data\", \"dfn\", \"em\", \"i\", \"kbd\", \"mark\", \"q\", \"rp\", \"rt\", \"ruby\", \"s\", \"samp\", \"small\", \"span\", \"strong\", \"sub\", \"sup\", \"time\", \"u\", \"var\", \"wbr\", \"area\", \"audio\", \"img\", \"map\", \"track\", \"video\", \"embed\", \"iframe\", \"object\", \"param\", \"picture\", \"portal\", \"source\", \"svg\", \"math\", \"canvas\", \"noscript\", \"script\", \"del\", \"ins\", \"caption\", \"col\", \"colgroup\", \"table\", \"tbody\", \"td\", \"tfoot\", \"th\", \"thead\", \"tr\", \"button\", \"datalist\", \"fieldset\", \"form\", \"input\", \"label\", \"legend\", \"meter\", \"optgroup\", \"option\", \"output\", \"progress\", \"select\", \"textarea\", \"details\", \"dialog\", \"menu\", \"summary\", \"details\", \"slot\", \"template\", \"acronym\", \"applet\", \"basefont\", \"bgsound\", \"big\", \"blink\", \"center\", \"content\", \"dir\", \"font\", \"frame\", \"frameset\", \"hgroup\", \"image\", \"keygen\", \"marquee\", \"menuitem\", \"nobr\", \"noembed\", \"noframes\", \"plaintext\", \"rb\", \"rtc\", \"shadow\", \"spacer\", \"strike\", \"tt\", \"xmp\", \"a\", \"abbr\", \"acronym\", \"address\", \"applet\", \"area\", \"article\", \"aside\", \"audio\", \"b\", \"base\", \"basefont\", \"bdi\", \"bdo\", \"bgsound\", \"big\", \"blink\", \"blockquote\", \"body\", \"br\", \"button\", \"canvas\", \"caption\", \"center\", \"cite\", \"code\", \"col\", \"colgroup\", \"content\", \"data\", \"datalist\", \"dd\", \"del\", \"details\", \"dfn\", \"dialog\", \"dir\", \"div\", \"dl\", \"dt\", \"em\", \"embed\", \"fieldset\", \"figcaption\", \"figure\", \"font\", \"footer\", \"form\", \"frame\", \"frameset\", \"head\", \"header\", \"hgroup\", \"hr\", \"html\", \"i\", \"iframe\", \"image\", \"img\", \"input\", \"ins\", \"kbd\", \"keygen\", \"label\", \"legend\", \"li\", \"link\", \"main\", \"map\", \"mark\", \"marquee\", \"menu\", \"menuitem\", \"meta\", \"meter\", \"nav\", \"nobr\", \"noembed\", \"noframes\", \"noscript\", \"object\", \"ol\", \"optgroup\", \"option\", \"output\", \"p\", \"param\", \"picture\", \"plaintext\", \"portal\", \"pre\", \"progress\", \"q\", \"rb\", \"rp\", \"rt\", \"rtc\", \"ruby\", \"s\", \"samp\", \"script\", \"section\", \"select\", \"shadow\", \"slot\", \"small\", \"source\", \"spacer\", \"span\", \"strike\", \"strong\", \"style\", \"sub\", \"summary\", \"sup\", \"table\", \"tbody\", \"td\", \"template\", \"textarea\", \"tfoot\", \"th\", \"thead\", \"time\", \"title\", \"tr\", \"track\", \"tt\", \"u\", \"ul\", \"var\", \"video\", \"wbr\", \"xmp\", \"input\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"]);\n\nconst memo = fn => createMemo(() => fn());\n\nfunction reconcileArrays(parentNode, a, b) {\n let bLength = b.length,\n aEnd = a.length,\n bEnd = bLength,\n aStart = 0,\n bStart = 0,\n after = a[aEnd - 1].nextSibling,\n map = null;\n while (aStart < aEnd || bStart < bEnd) {\n if (a[aStart] === b[bStart]) {\n aStart++;\n bStart++;\n continue;\n }\n while (a[aEnd - 1] === b[bEnd - 1]) {\n aEnd--;\n bEnd--;\n }\n if (aEnd === aStart) {\n const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] : after;\n while (bStart < bEnd) parentNode.insertBefore(b[bStart++], node);\n } else if (bEnd === bStart) {\n while (aStart < aEnd) {\n if (!map || !map.has(a[aStart])) a[aStart].remove();\n aStart++;\n }\n } else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {\n const node = a[--aEnd].nextSibling;\n parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling);\n parentNode.insertBefore(b[--bEnd], node);\n a[aEnd] = b[bEnd];\n } else {\n if (!map) {\n map = new Map();\n let i = bStart;\n while (i < bEnd) map.set(b[i], i++);\n }\n const index = map.get(a[aStart]);\n if (index != null) {\n if (bStart < index && index < bEnd) {\n let i = aStart,\n sequence = 1,\n t;\n while (++i < aEnd && i < bEnd) {\n if ((t = map.get(a[i])) == null || t !== index + sequence) break;\n sequence++;\n }\n if (sequence > index - bStart) {\n const node = a[aStart];\n while (bStart < index) parentNode.insertBefore(b[bStart++], node);\n } else parentNode.replaceChild(b[bStart++], a[aStart++]);\n } else aStart++;\n } else a[aStart++].remove();\n }\n }\n}\n\nconst $$EVENTS = \"_$DX_DELEGATE\";\nfunction render(code, element, init, options = {}) {\n if (!element) {\n throw new Error(\"The `element` passed to `render(..., element)` doesn't exist. Make sure `element` exists in the document.\");\n }\n let disposer;\n createRoot(dispose => {\n disposer = dispose;\n element === document ? code() : insert(element, code(), element.firstChild ? null : undefined, init);\n }, options.owner);\n return () => {\n disposer();\n element.textContent = \"\";\n };\n}\nfunction template(html, isImportNode, isSVG, isMathML) {\n let node;\n const create = () => {\n if (isHydrating()) throw new Error(\"Failed attempt to create new DOM elements during hydration. Check that the libraries you are using support hydration.\");\n const t = isMathML ? document.createElementNS(\"http://www.w3.org/1998/Math/MathML\", \"template\") : document.createElement(\"template\");\n t.innerHTML = html;\n return isSVG ? t.content.firstChild.firstChild : isMathML ? t.firstChild : t.content.firstChild;\n };\n const fn = isImportNode ? () => untrack(() => document.importNode(node || (node = create()), true)) : () => (node || (node = create())).cloneNode(true);\n fn.cloneNode = fn;\n return fn;\n}\nfunction delegateEvents(eventNames, document = window.document) {\n const e = document[$$EVENTS] || (document[$$EVENTS] = new Set());\n for (let i = 0, l = eventNames.length; i < l; i++) {\n const name = eventNames[i];\n if (!e.has(name)) {\n e.add(name);\n document.addEventListener(name, eventHandler);\n }\n }\n}\nfunction clearDelegatedEvents(document = window.document) {\n if (document[$$EVENTS]) {\n for (let name of document[$$EVENTS].keys()) document.removeEventListener(name, eventHandler);\n delete document[$$EVENTS];\n }\n}\nfunction setProperty(node, name, value) {\n if (isHydrating(node)) return;\n node[name] = value;\n}\nfunction setAttribute(node, name, value) {\n if (isHydrating(node)) return;\n if (value == null) node.removeAttribute(name);else node.setAttribute(name, value);\n}\nfunction setAttributeNS(node, namespace, name, value) {\n if (isHydrating(node)) return;\n if (value == null) node.removeAttributeNS(namespace, name);else node.setAttributeNS(namespace, name, value);\n}\nfunction setBoolAttribute(node, name, value) {\n if (isHydrating(node)) return;\n value ? node.setAttribute(name, \"\") : node.removeAttribute(name);\n}\nfunction className(node, value) {\n if (isHydrating(node)) return;\n if (value == null) node.removeAttribute(\"class\");else node.className = value;\n}\nfunction addEventListener(node, name, handler, delegate) {\n if (delegate) {\n if (Array.isArray(handler)) {\n node[`$$${name}`] = handler[0];\n node[`$$${name}Data`] = handler[1];\n } else node[`$$${name}`] = handler;\n } else if (Array.isArray(handler)) {\n const handlerFn = handler[0];\n node.addEventListener(name, handler[0] = e => handlerFn.call(node, handler[1], e));\n } else node.addEventListener(name, handler, typeof handler !== \"function\" && handler);\n}\nfunction classList(node, value, prev = {}) {\n const classKeys = Object.keys(value || {}),\n prevKeys = Object.keys(prev);\n let i, len;\n for (i = 0, len = prevKeys.length; i < len; i++) {\n const key = prevKeys[i];\n if (!key || key === \"undefined\" || value[key]) continue;\n toggleClassKey(node, key, false);\n delete prev[key];\n }\n for (i = 0, len = classKeys.length; i < len; i++) {\n const key = classKeys[i],\n classValue = !!value[key];\n if (!key || key === \"undefined\" || prev[key] === classValue || !classValue) continue;\n toggleClassKey(node, key, true);\n prev[key] = classValue;\n }\n return prev;\n}\nfunction style(node, value, prev) {\n if (!value) return prev ? setAttribute(node, \"style\") : value;\n const nodeStyle = node.style;\n if (typeof value === \"string\") return nodeStyle.cssText = value;\n typeof prev === \"string\" && (nodeStyle.cssText = prev = undefined);\n prev || (prev = {});\n value || (value = {});\n let v, s;\n for (s in prev) {\n value[s] == null && nodeStyle.removeProperty(s);\n delete prev[s];\n }\n for (s in value) {\n v = value[s];\n if (v !== prev[s]) {\n nodeStyle.setProperty(s, v);\n prev[s] = v;\n }\n }\n return prev;\n}\nfunction spread(node, props = {}, isSVG, skipChildren) {\n const prevProps = {};\n if (!skipChildren) {\n createRenderEffect(() => prevProps.children = insertExpression(node, props.children, prevProps.children));\n }\n createRenderEffect(() => typeof props.ref === \"function\" && use(props.ref, node));\n createRenderEffect(() => assign(node, props, isSVG, true, prevProps, true));\n return prevProps;\n}\nfunction dynamicProperty(props, key) {\n const src = props[key];\n Object.defineProperty(props, key, {\n get() {\n return src();\n },\n enumerable: true\n });\n return props;\n}\nfunction use(fn, element, arg) {\n return untrack(() => fn(element, arg));\n}\nfunction insert(parent, accessor, marker, initial) {\n if (marker !== undefined && !initial) initial = [];\n if (typeof accessor !== \"function\") return insertExpression(parent, accessor, initial, marker);\n createRenderEffect(current => insertExpression(parent, accessor(), current, marker), initial);\n}\nfunction assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = false) {\n props || (props = {});\n for (const prop in prevProps) {\n if (!(prop in props)) {\n if (prop === \"children\") continue;\n prevProps[prop] = assignProp(node, prop, null, prevProps[prop], isSVG, skipRef, props);\n }\n }\n for (const prop in props) {\n if (prop === \"children\") {\n if (!skipChildren) insertExpression(node, props.children);\n continue;\n }\n const value = props[prop];\n prevProps[prop] = assignProp(node, prop, value, prevProps[prop], isSVG, skipRef, props);\n }\n}\nfunction hydrate$1(code, element, options = {}) {\n if (globalThis._$HY.done) return render(code, element, [...element.childNodes], options);\n sharedConfig.completed = globalThis._$HY.completed;\n sharedConfig.events = globalThis._$HY.events;\n sharedConfig.load = id => globalThis._$HY.r[id];\n sharedConfig.has = id => id in globalThis._$HY.r;\n sharedConfig.gather = root => gatherHydratable(element, root);\n sharedConfig.registry = new Map();\n sharedConfig.context = {\n id: options.renderId || \"\",\n count: 0\n };\n try {\n gatherHydratable(element, options.renderId);\n return render(code, element, [...element.childNodes], options);\n } finally {\n sharedConfig.context = null;\n }\n}\nfunction getNextElement(template) {\n let node,\n key,\n hydrating = isHydrating();\n if (!hydrating || !(node = sharedConfig.registry.get(key = getHydrationKey()))) {\n if (hydrating) {\n sharedConfig.done = true;\n throw new Error(`Hydration Mismatch. Unable to find DOM nodes for hydration key: ${key}\\n${template ? template().outerHTML : \"\"}`);\n }\n return template();\n }\n if (sharedConfig.completed) sharedConfig.completed.add(node);\n sharedConfig.registry.delete(key);\n return node;\n}\nfunction getNextMatch(el, nodeName) {\n while (el && el.localName !== nodeName) el = el.nextSibling;\n return el;\n}\nfunction getNextMarker(start) {\n let end = start,\n count = 0,\n current = [];\n if (isHydrating(start)) {\n while (end) {\n if (end.nodeType === 8) {\n const v = end.nodeValue;\n if (v === \"$\") count++;else if (v === \"/\") {\n if (count === 0) return [end, current];\n count--;\n }\n }\n current.push(end);\n end = end.nextSibling;\n }\n }\n return [end, current];\n}\nfunction runHydrationEvents() {\n if (sharedConfig.events && !sharedConfig.events.queued) {\n queueMicrotask(() => {\n const {\n completed,\n events\n } = sharedConfig;\n if (!events) return;\n events.queued = false;\n while (events.length) {\n const [el, e] = events[0];\n if (!completed.has(el)) return;\n events.shift();\n eventHandler(e);\n }\n if (sharedConfig.done) {\n sharedConfig.events = _$HY.events = null;\n sharedConfig.completed = _$HY.completed = null;\n }\n });\n sharedConfig.events.queued = true;\n }\n}\nfunction isHydrating(node) {\n return !!sharedConfig.context && !sharedConfig.done && (!node || node.isConnected);\n}\nfunction toPropertyName(name) {\n return name.toLowerCase().replace(/-([a-z])/g, (_, w) => w.toUpperCase());\n}\nfunction toggleClassKey(node, key, value) {\n const classNames = key.trim().split(/\\s+/);\n for (let i = 0, nameLen = classNames.length; i < nameLen; i++) node.classList.toggle(classNames[i], value);\n}\nfunction assignProp(node, prop, value, prev, isSVG, skipRef, props) {\n let isCE, isProp, isChildProp, propAlias, forceProp;\n if (prop === \"style\") return style(node, value, prev);\n if (prop === \"classList\") return classList(node, value, prev);\n if (value === prev) return prev;\n if (prop === \"ref\") {\n if (!skipRef) value(node);\n } else if (prop.slice(0, 3) === \"on:\") {\n const e = prop.slice(3);\n prev && node.removeEventListener(e, prev, typeof prev !== \"function\" && prev);\n value && node.addEventListener(e, value, typeof value !== \"function\" && value);\n } else if (prop.slice(0, 10) === \"oncapture:\") {\n const e = prop.slice(10);\n prev && node.removeEventListener(e, prev, true);\n value && node.addEventListener(e, value, true);\n } else if (prop.slice(0, 2) === \"on\") {\n const name = prop.slice(2).toLowerCase();\n const delegate = DelegatedEvents.has(name);\n if (!delegate && prev) {\n const h = Array.isArray(prev) ? prev[0] : prev;\n node.removeEventListener(name, h);\n }\n if (delegate || value) {\n addEventListener(node, name, value, delegate);\n delegate && delegateEvents([name]);\n }\n } else if (prop.slice(0, 5) === \"attr:\") {\n setAttribute(node, prop.slice(5), value);\n } else if (prop.slice(0, 5) === \"bool:\") {\n setBoolAttribute(node, prop.slice(5), value);\n } else if ((forceProp = prop.slice(0, 5) === \"prop:\") || (isChildProp = ChildProperties.has(prop)) || !isSVG && ((propAlias = getPropAlias(prop, node.tagName)) || (isProp = Properties.has(prop))) || (isCE = node.nodeName.includes(\"-\") || \"is\" in props)) {\n if (forceProp) {\n prop = prop.slice(5);\n isProp = true;\n } else if (isHydrating(node)) return value;\n if (prop === \"class\" || prop === \"className\") className(node, value);else if (isCE && !isProp && !isChildProp) node[toPropertyName(prop)] = value;else node[propAlias || prop] = value;\n } else {\n const ns = isSVG && prop.indexOf(\":\") > -1 && SVGNamespace[prop.split(\":\")[0]];\n if (ns) setAttributeNS(node, ns, prop, value);else setAttribute(node, Aliases[prop] || prop, value);\n }\n return value;\n}\nfunction eventHandler(e) {\n if (sharedConfig.registry && sharedConfig.events) {\n if (sharedConfig.events.find(([el, ev]) => ev === e)) return;\n }\n let node = e.target;\n const key = `$$${e.type}`;\n const oriTarget = e.target;\n const oriCurrentTarget = e.currentTarget;\n const retarget = value => Object.defineProperty(e, \"target\", {\n configurable: true,\n value\n });\n const handleNode = () => {\n const handler = node[key];\n if (handler && !node.disabled) {\n const data = node[`${key}Data`];\n data !== undefined ? handler.call(node, data, e) : handler.call(node, e);\n if (e.cancelBubble) return;\n }\n node.host && typeof node.host !== \"string\" && !node.host._$host && node.contains(e.target) && retarget(node.host);\n return true;\n };\n const walkUpTree = () => {\n while (handleNode() && (node = node._$host || node.parentNode || node.host));\n };\n Object.defineProperty(e, \"currentTarget\", {\n configurable: true,\n get() {\n return node || document;\n }\n });\n if (sharedConfig.registry && !sharedConfig.done) sharedConfig.done = _$HY.done = true;\n if (e.composedPath) {\n const path = e.composedPath();\n retarget(path[0]);\n for (let i = 0; i < path.length - 2; i++) {\n node = path[i];\n if (!handleNode()) break;\n if (node._$host) {\n node = node._$host;\n walkUpTree();\n break;\n }\n if (node.parentNode === oriCurrentTarget) {\n break;\n }\n }\n }\n else walkUpTree();\n retarget(oriTarget);\n}\nfunction insertExpression(parent, value, current, marker, unwrapArray) {\n const hydrating = isHydrating(parent);\n if (hydrating) {\n !current && (current = [...parent.childNodes]);\n let cleaned = [];\n for (let i = 0; i < current.length; i++) {\n const node = current[i];\n if (node.nodeType === 8 && node.data.slice(0, 2) === \"!$\") node.remove();else cleaned.push(node);\n }\n current = cleaned;\n }\n while (typeof current === \"function\") current = current();\n if (value === current) return current;\n const t = typeof value,\n multi = marker !== undefined;\n parent = multi && current[0] && current[0].parentNode || parent;\n if (t === \"string\" || t === \"number\") {\n if (hydrating) return current;\n if (t === \"number\") {\n value = value.toString();\n if (value === current) return current;\n }\n if (multi) {\n let node = current[0];\n if (node && node.nodeType === 3) {\n node.data !== value && (node.data = value);\n } else node = document.createTextNode(value);\n current = cleanChildren(parent, current, marker, node);\n } else {\n if (current !== \"\" && typeof current === \"string\") {\n current = parent.firstChild.data = value;\n } else current = parent.textContent = value;\n }\n } else if (value == null || t === \"boolean\") {\n if (hydrating) return current;\n current = cleanChildren(parent, current, marker);\n } else if (t === \"function\") {\n createRenderEffect(() => {\n let v = value();\n while (typeof v === \"function\") v = v();\n current = insertExpression(parent, v, current, marker);\n });\n return () => current;\n } else if (Array.isArray(value)) {\n const array = [];\n const currentArray = current && Array.isArray(current);\n if (normalizeIncomingArray(array, value, current, unwrapArray)) {\n createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));\n return () => current;\n }\n if (hydrating) {\n if (!array.length) return current;\n if (marker === undefined) return current = [...parent.childNodes];\n let node = array[0];\n if (node.parentNode !== parent) return current;\n const nodes = [node];\n while ((node = node.nextSibling) !== marker) nodes.push(node);\n return current = nodes;\n }\n if (array.length === 0) {\n current = cleanChildren(parent, current, marker);\n if (multi) return current;\n } else if (currentArray) {\n if (current.length === 0) {\n appendNodes(parent, array, marker);\n } else reconcileArrays(parent, current, array);\n } else {\n current && cleanChildren(parent);\n appendNodes(parent, array);\n }\n current = array;\n } else if (value.nodeType) {\n if (hydrating && value.parentNode) return current = multi ? [value] : value;\n if (Array.isArray(current)) {\n if (multi) return current = cleanChildren(parent, current, marker, value);\n cleanChildren(parent, current, null, value);\n } else if (current == null || current === \"\" || !parent.firstChild) {\n parent.appendChild(value);\n } else parent.replaceChild(value, parent.firstChild);\n current = value;\n } else console.warn(`Unrecognized value. Skipped inserting`, value);\n return current;\n}\nfunction normalizeIncomingArray(normalized, array, current, unwrap) {\n let dynamic = false;\n for (let i = 0, len = array.length; i < len; i++) {\n let item = array[i],\n prev = current && current[normalized.length],\n t;\n if (item == null || item === true || item === false) ; else if ((t = typeof item) === \"object\" && item.nodeType) {\n normalized.push(item);\n } else if (Array.isArray(item)) {\n dynamic = normalizeIncomingArray(normalized, item, prev) || dynamic;\n } else if (t === \"function\") {\n if (unwrap) {\n while (typeof item === \"function\") item = item();\n dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item], Array.isArray(prev) ? prev : [prev]) || dynamic;\n } else {\n normalized.push(item);\n dynamic = true;\n }\n } else {\n const value = String(item);\n if (prev && prev.nodeType === 3 && prev.data === value) normalized.push(prev);else normalized.push(document.createTextNode(value));\n }\n }\n return dynamic;\n}\nfunction appendNodes(parent, array, marker = null) {\n for (let i = 0, len = array.length; i < len; i++) parent.insertBefore(array[i], marker);\n}\nfunction cleanChildren(parent, current, marker, replacement) {\n if (marker === undefined) return parent.textContent = \"\";\n const node = replacement || document.createTextNode(\"\");\n if (current.length) {\n let inserted = false;\n for (let i = current.length - 1; i >= 0; i--) {\n const el = current[i];\n if (node !== el) {\n const isParent = el.parentNode === parent;\n if (!inserted && !i) isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);else isParent && el.remove();\n } else inserted = true;\n }\n } else parent.insertBefore(node, marker);\n return [node];\n}\nfunction gatherHydratable(element, root) {\n const templates = element.querySelectorAll(`*[data-hk]`);\n for (let i = 0; i < templates.length; i++) {\n const node = templates[i];\n const key = node.getAttribute(\"data-hk\");\n if ((!root || key.startsWith(root)) && !sharedConfig.registry.has(key)) sharedConfig.registry.set(key, node);\n }\n}\nfunction getHydrationKey() {\n return sharedConfig.getNextContextId();\n}\nfunction NoHydration(props) {\n return sharedConfig.context ? undefined : props.children;\n}\nfunction Hydration(props) {\n return props.children;\n}\nconst voidFn = () => undefined;\nconst RequestContext = Symbol();\nfunction innerHTML(parent, content) {\n !sharedConfig.context && (parent.innerHTML = content);\n}\n\nfunction throwInBrowser(func) {\n const err = new Error(`${func.name} is not supported in the browser, returning undefined`);\n console.error(err);\n}\nfunction renderToString(fn, options) {\n throwInBrowser(renderToString);\n}\nfunction renderToStringAsync(fn, options) {\n throwInBrowser(renderToStringAsync);\n}\nfunction renderToStream(fn, options) {\n throwInBrowser(renderToStream);\n}\nfunction ssr(template, ...nodes) {}\nfunction ssrElement(name, props, children, needsId) {}\nfunction ssrClassList(value) {}\nfunction ssrStyle(value) {}\nfunction ssrAttribute(key, value) {}\nfunction ssrHydrationKey() {}\nfunction resolveSSRNode(node) {}\nfunction escape(html) {}\nfunction ssrSpread(props, isSVG, skipChildren) {}\n\nconst isServer = false;\nconst isDev = true;\nconst SVG_NAMESPACE = \"http://www.w3.org/2000/svg\";\nfunction createElement(tagName, isSVG = false) {\n return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName);\n}\nconst hydrate = (...args) => {\n enableHydration();\n return hydrate$1(...args);\n};\nfunction Portal(props) {\n const {\n useShadow\n } = props,\n marker = document.createTextNode(\"\"),\n mount = () => props.mount || document.body,\n owner = getOwner();\n let content;\n let hydrating = !!sharedConfig.context;\n createEffect(() => {\n if (hydrating) getOwner().user = hydrating = false;\n content || (content = runWithOwner(owner, () => createMemo(() => props.children)));\n const el = mount();\n if (el instanceof HTMLHeadElement) {\n const [clean, setClean] = createSignal(false);\n const cleanup = () => setClean(true);\n createRoot(dispose => insert(el, () => !clean() ? content() : dispose(), null));\n onCleanup(cleanup);\n } else {\n const container = createElement(props.isSVG ? \"g\" : \"div\", props.isSVG),\n renderRoot = useShadow && container.attachShadow ? container.attachShadow({\n mode: \"open\"\n }) : container;\n Object.defineProperty(container, \"_$host\", {\n get() {\n return marker.parentNode;\n },\n configurable: true\n });\n insert(renderRoot, content);\n el.appendChild(container);\n props.ref && props.ref(container);\n onCleanup(() => el.removeChild(container));\n }\n }, undefined, {\n render: !hydrating\n });\n return marker;\n}\nfunction createDynamic(component, props) {\n const cached = createMemo(component);\n return createMemo(() => {\n const component = cached();\n switch (typeof component) {\n case \"function\":\n Object.assign(component, {\n [$DEVCOMP]: true\n });\n return untrack(() => component(props));\n case \"string\":\n const isSvg = SVGElements.has(component);\n const el = sharedConfig.context ? getNextElement() : createElement(component, isSvg);\n spread(el, props, isSvg);\n return el;\n }\n });\n}\nfunction Dynamic(props) {\n const [, others] = splitProps(props, [\"component\"]);\n return createDynamic(() => props.component, others);\n}\n\nexport { Aliases, voidFn as Assets, ChildProperties, DOMElements, DelegatedEvents, Dynamic, Hydration, voidFn as HydrationScript, NoHydration, Portal, Properties, RequestContext, SVGElements, SVGNamespace, addEventListener, assign, classList, className, clearDelegatedEvents, createDynamic, delegateEvents, dynamicProperty, escape, voidFn as generateHydrationScript, voidFn as getAssets, getHydrationKey, getNextElement, getNextMarker, getNextMatch, getPropAlias, voidFn as getRequestEvent, hydrate, innerHTML, insert, isDev, isServer, memo, render, renderToStream, renderToString, renderToStringAsync, resolveSSRNode, runHydrationEvents, setAttribute, setAttributeNS, setBoolAttribute, setProperty, spread, ssr, ssrAttribute, ssrClassList, ssrElement, ssrHydrationKey, ssrSpread, ssrStyle, style, template, use, voidFn as useAssets };\n"],
- "mappings": "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",
- "names": ["document", "template", "component"]
-}
diff --git a/pulse-test-staging/frontend-modern/index.html b/pulse-test-staging/frontend-modern/index.html
deleted file mode 100644
index ee0609cbb..000000000
--- a/pulse-test-staging/frontend-modern/index.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
- Pulse Monitor - Modern
-
-
- You need to enable JavaScript to run this app.
-
-
-
-
-
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/package-lock.json b/pulse-test-staging/frontend-modern/package-lock.json
deleted file mode 100644
index 1818865ab..000000000
--- a/pulse-test-staging/frontend-modern/package-lock.json
+++ /dev/null
@@ -1,2949 +0,0 @@
-{
- "name": "pulse-modern",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "pulse-modern",
- "version": "1.0.0",
- "dependencies": {
- "@solidjs/router": "^0.10.0",
- "chart.js": "^4.4.0",
- "solid-js": "^1.8.0"
- },
- "devDependencies": {
- "@types/node": "^20.10.0",
- "autoprefixer": "^10.4.0",
- "postcss": "^8.4.0",
- "tailwindcss": "^3.4.0",
- "typescript": "^5.3.0",
- "vite": "^5.0.0",
- "vite-plugin-solid": "^2.8.0"
- }
- },
- "node_modules/@alloc/quick-lru": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@ampproject/remapping": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
- "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.24"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/code-frame": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
- "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.27.1",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
- "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
- "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
- "dev": true,
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.28.0",
- "@babel/helper-compilation-targets": "^7.27.2",
- "@babel/helper-module-transforms": "^7.27.3",
- "@babel/helpers": "^7.27.6",
- "@babel/parser": "^7.28.0",
- "@babel/template": "^7.27.2",
- "@babel/traverse": "^7.28.0",
- "@babel/types": "^7.28.0",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
- "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.28.0",
- "@babel/types": "^7.28.0",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
- "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.27.2",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
- "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
- "dev": true,
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.27.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
- "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-imports": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1",
- "@babel/traverse": "^7.27.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
- "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-string-parser": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
- "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-identifier": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
- "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.27.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
- "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.27.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/parser": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
- "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.28.0"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz",
- "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
- "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/parser": "^7.27.2",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
- "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.28.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.28.0",
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.28.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/types": {
- "version": "7.28.1",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.1.tgz",
- "integrity": "sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-string-parser": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@esbuild/aix-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
- "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "aix"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
- "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
- "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/android-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
- "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
- "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/darwin-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
- "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
- "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/freebsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
- "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
- "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
- "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-loong64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
- "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-mips64el": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
- "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
- "cpu": [
- "mips64el"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-ppc64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
- "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-riscv64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
- "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-s390x": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
- "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/netbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
- "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "netbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/openbsd-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
- "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "openbsd"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/sunos-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
- "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "sunos"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
- "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-ia32": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
- "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/win32-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
- "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dev": true,
- "dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.12",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
- "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
- "dev": true,
- "dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0",
- "@jridgewell/trace-mapping": "^0.3.24"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
- "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
- "dev": true
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.29",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
- "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
- "dev": true,
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
- }
- },
- "node_modules/@kurkle/color": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
- "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="
- },
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
- "optional": true,
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/@rollup/rollup-android-arm-eabi": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.45.1.tgz",
- "integrity": "sha512-NEySIFvMY0ZQO+utJkgoMiCAjMrGvnbDLHvcmlA33UXJpYBCvlBEbMMtV837uCkS+plG2umfhn0T5mMAxGrlRA==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-android-arm64": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.45.1.tgz",
- "integrity": "sha512-ujQ+sMXJkg4LRJaYreaVx7Z/VMgBBd89wGS4qMrdtfUFZ+TSY5Rs9asgjitLwzeIbhwdEhyj29zhst3L1lKsRQ==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "android"
- ]
- },
- "node_modules/@rollup/rollup-darwin-arm64": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.45.1.tgz",
- "integrity": "sha512-FSncqHvqTm3lC6Y13xncsdOYfxGSLnP+73k815EfNmpewPs+EyM49haPS105Rh4aF5mJKywk9X0ogzLXZzN9lA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-darwin-x64": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.45.1.tgz",
- "integrity": "sha512-2/vVn/husP5XI7Fsf/RlhDaQJ7x9zjvC81anIVbr4b/f0xtSmXQTFcGIQ/B1cXIYM6h2nAhJkdMHTnD7OtQ9Og==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "darwin"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-arm64": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.45.1.tgz",
- "integrity": "sha512-4g1kaDxQItZsrkVTdYQ0bxu4ZIQ32cotoQbmsAnW1jAE4XCMbcBPDirX5fyUzdhVCKgPcrwWuucI8yrVRBw2+g==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-freebsd-x64": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.45.1.tgz",
- "integrity": "sha512-L/6JsfiL74i3uK1Ti2ZFSNsp5NMiM4/kbbGEcOCps99aZx3g8SJMO1/9Y0n/qKlWZfn6sScf98lEOUe2mBvW9A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "freebsd"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.45.1.tgz",
- "integrity": "sha512-RkdOTu2jK7brlu+ZwjMIZfdV2sSYHK2qR08FUWcIoqJC2eywHbXr0L8T/pONFwkGukQqERDheaGTeedG+rra6Q==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm-musleabihf": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.45.1.tgz",
- "integrity": "sha512-3kJ8pgfBt6CIIr1o+HQA7OZ9mp/zDk3ctekGl9qn/pRBgrRgfwiffaUmqioUGN9hv0OHv2gxmvdKOkARCtRb8Q==",
- "cpu": [
- "arm"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.45.1.tgz",
- "integrity": "sha512-k3dOKCfIVixWjG7OXTCOmDfJj3vbdhN0QYEqB+OuGArOChek22hn7Uy5A/gTDNAcCy5v2YcXRJ/Qcnm4/ma1xw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.45.1.tgz",
- "integrity": "sha512-PmI1vxQetnM58ZmDFl9/Uk2lpBBby6B6rF4muJc65uZbxCs0EA7hhKCk2PKlmZKuyVSHAyIw3+/SiuMLxKxWog==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.45.1.tgz",
- "integrity": "sha512-9UmI0VzGmNJ28ibHW2GpE2nF0PBQqsyiS4kcJ5vK+wuwGnV5RlqdczVocDSUfGX/Na7/XINRVoUgJyFIgipoRg==",
- "cpu": [
- "loong64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.45.1.tgz",
- "integrity": "sha512-7nR2KY8oEOUTD3pBAxIBBbZr0U7U+R9HDTPNy+5nVVHDXI4ikYniH1oxQz9VoB5PbBU1CZuDGHkLJkd3zLMWsg==",
- "cpu": [
- "ppc64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-gnu": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.45.1.tgz",
- "integrity": "sha512-nlcl3jgUultKROfZijKjRQLUu9Ma0PeNv/VFHkZiKbXTBQXhpytS8CIj5/NfBeECZtY2FJQubm6ltIxm/ftxpw==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-riscv64-musl": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.45.1.tgz",
- "integrity": "sha512-HJV65KLS51rW0VY6rvZkiieiBnurSzpzore1bMKAhunQiECPuxsROvyeaot/tcK3A3aGnI+qTHqisrpSgQrpgA==",
- "cpu": [
- "riscv64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-s390x-gnu": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.45.1.tgz",
- "integrity": "sha512-NITBOCv3Qqc6hhwFt7jLV78VEO/il4YcBzoMGGNxznLgRQf43VQDae0aAzKiBeEPIxnDrACiMgbqjuihx08OOw==",
- "cpu": [
- "s390x"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.45.1.tgz",
- "integrity": "sha512-+E/lYl6qu1zqgPEnTrs4WysQtvc/Sh4fC2nByfFExqgYrqkKWp1tWIbe+ELhixnenSpBbLXNi6vbEEJ8M7fiHw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.45.1.tgz",
- "integrity": "sha512-a6WIAp89p3kpNoYStITT9RbTbTnqarU7D8N8F2CV+4Cl9fwCOZraLVuVFvlpsW0SbIiYtEnhCZBPLoNdRkjQFw==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-win32-arm64-msvc": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.45.1.tgz",
- "integrity": "sha512-T5Bi/NS3fQiJeYdGvRpTAP5P02kqSOpqiopwhj0uaXB6nzs5JVi2XMJb18JUSKhCOX8+UE1UKQufyD6Or48dJg==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-ia32-msvc": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.45.1.tgz",
- "integrity": "sha512-lxV2Pako3ujjuUe9jiU3/s7KSrDfH6IgTSQOnDWr9aJ92YsFd7EurmClK0ly/t8dzMkDtd04g60WX6yl0sGfdw==",
- "cpu": [
- "ia32"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@rollup/rollup-win32-x64-msvc": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.45.1.tgz",
- "integrity": "sha512-M/fKi4sasCdM8i0aWJjCSFm2qEnYRR8AMLG2kxp6wD13+tMGA4Z1tVAuHkNRjud5SW2EM3naLuK35w9twvf6aA==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "optional": true,
- "os": [
- "win32"
- ]
- },
- "node_modules/@solidjs/router": {
- "version": "0.10.10",
- "resolved": "https://registry.npmjs.org/@solidjs/router/-/router-0.10.10.tgz",
- "integrity": "sha512-nGl7gMgsojuaupI5MAK2cFtkndmWWSAPhill/8La3IjujY3vMBamcQFymBsA2ejzxEYJjkOlEQHYgp2jNFkwuQ==",
- "peerDependencies": {
- "solid-js": "^1.8.6"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
- "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.20.7"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true
- },
- "node_modules/@types/node": {
- "version": "20.19.9",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz",
- "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==",
- "dev": true,
- "dependencies": {
- "undici-types": "~6.21.0"
- }
- },
- "node_modules/ansi-regex": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
- "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "dev": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/arg": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
- },
- "node_modules/autoprefixer": {
- "version": "10.4.21",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
- "integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "browserslist": "^4.24.4",
- "caniuse-lite": "^1.0.30001702",
- "fraction.js": "^4.3.7",
- "normalize-range": "^0.1.2",
- "picocolors": "^1.1.1",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/babel-plugin-jsx-dom-expressions": {
- "version": "0.39.8",
- "resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.39.8.tgz",
- "integrity": "sha512-/MVOIIjonylDXnrWmG23ZX82m9mtKATsVHB7zYlPfDR9Vdd/NBE48if+wv27bSkBtyO7EPMUlcUc4J63QwuACQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-imports": "7.18.6",
- "@babel/plugin-syntax-jsx": "^7.18.6",
- "@babel/types": "^7.20.7",
- "html-entities": "2.3.3",
- "parse5": "^7.1.2",
- "validate-html-nesting": "^1.2.1"
- },
- "peerDependencies": {
- "@babel/core": "^7.20.12"
- }
- },
- "node_modules/babel-plugin-jsx-dom-expressions/node_modules/@babel/helper-module-imports": {
- "version": "7.18.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
- "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.18.6"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/babel-preset-solid": {
- "version": "1.9.6",
- "resolved": "https://registry.npmjs.org/babel-preset-solid/-/babel-preset-solid-1.9.6.tgz",
- "integrity": "sha512-HXTK9f93QxoH8dYn1M2mJdOlWgMsR88Lg/ul6QCZGkNTktjTE5HAf93YxQumHoCudLEtZrU1cFCMFOVho6GqFg==",
- "dev": true,
- "dependencies": {
- "babel-plugin-jsx-dom-expressions": "^0.39.8"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
- },
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.25.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
- "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "caniuse-lite": "^1.0.30001726",
- "electron-to-chromium": "^1.5.173",
- "node-releases": "^2.0.19",
- "update-browserslist-db": "^1.1.3"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- }
- },
- "node_modules/camelcase-css": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/caniuse-lite": {
- "version": "1.0.30001727",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
- "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ]
- },
- "node_modules/chart.js": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.0.tgz",
- "integrity": "sha512-aYeC/jDgSEx8SHWZvANYMioYMZ2KX02W6f6uVfyteuCGcadDLcYVHdfdygsTQkQ4TKn5lghoojAsPj5pu0SnvQ==",
- "dependencies": {
- "@kurkle/color": "^0.3.0"
- },
- "engines": {
- "pnpm": ">=8"
- }
- },
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/chokidar/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
- },
- "node_modules/commander": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "dev": true,
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/cssesc": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
- "bin": {
- "cssesc": "bin/cssesc"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
- },
- "node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
- "dev": true,
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/didyoumean": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true
- },
- "node_modules/dlv": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true
- },
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
- "dev": true
- },
- "node_modules/electron-to-chromium": {
- "version": "1.5.190",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.190.tgz",
- "integrity": "sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==",
- "dev": true
- },
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
- },
- "node_modules/entities": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
- "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "dev": true,
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/esbuild": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
- "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
- "dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=12"
- },
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.21.5",
- "@esbuild/android-arm": "0.21.5",
- "@esbuild/android-arm64": "0.21.5",
- "@esbuild/android-x64": "0.21.5",
- "@esbuild/darwin-arm64": "0.21.5",
- "@esbuild/darwin-x64": "0.21.5",
- "@esbuild/freebsd-arm64": "0.21.5",
- "@esbuild/freebsd-x64": "0.21.5",
- "@esbuild/linux-arm": "0.21.5",
- "@esbuild/linux-arm64": "0.21.5",
- "@esbuild/linux-ia32": "0.21.5",
- "@esbuild/linux-loong64": "0.21.5",
- "@esbuild/linux-mips64el": "0.21.5",
- "@esbuild/linux-ppc64": "0.21.5",
- "@esbuild/linux-riscv64": "0.21.5",
- "@esbuild/linux-s390x": "0.21.5",
- "@esbuild/linux-x64": "0.21.5",
- "@esbuild/netbsd-x64": "0.21.5",
- "@esbuild/openbsd-x64": "0.21.5",
- "@esbuild/sunos-x64": "0.21.5",
- "@esbuild/win32-arm64": "0.21.5",
- "@esbuild/win32-ia32": "0.21.5",
- "@esbuild/win32-x64": "0.21.5"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/fast-glob": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
- "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
- "dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.8"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/fastq": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
- "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
- "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
- "dev": true,
- "dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/fraction.js": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
- "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
- "dev": true,
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "patreon",
- "url": "https://github.com/sponsors/rawify"
- }
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
- }
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
- "dev": true,
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/html-entities": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.3.3.tgz",
- "integrity": "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==",
- "dev": true
- },
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.16.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
- "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
- "dev": true,
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-what": {
- "version": "4.1.16",
- "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
- "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
- "dev": true,
- "engines": {
- "node": ">=12.13"
- },
- "funding": {
- "url": "https://github.com/sponsors/mesqueeb"
- }
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
- },
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "dev": true,
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
- }
- },
- "node_modules/jiti": {
- "version": "1.21.7",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
- "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
- "dev": true,
- "bin": {
- "jiti": "bin/jiti.js"
- }
- },
- "node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
- },
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
- "dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/json5": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
- "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
- "dev": true,
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/lilconfig": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
- "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
- "dev": true,
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/antonk52"
- }
- },
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
- "node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true
- },
- "node_modules/merge-anything": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.1.7.tgz",
- "integrity": "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==",
- "dev": true,
- "dependencies": {
- "is-what": "^4.1.8"
- },
- "engines": {
- "node": ">=12.13"
- },
- "funding": {
- "url": "https://github.com/sponsors/mesqueeb"
- }
- },
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true,
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "dev": true
- },
- "node_modules/mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
- "dependencies": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
- "node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "bin": {
- "nanoid": "bin/nanoid.cjs"
- },
- "engines": {
- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
- }
- },
- "node_modules/node-releases": {
- "version": "2.0.19",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
- "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
- "dev": true
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/normalize-range": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
- "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-hash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/package-json-from-dist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
- "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
- "dev": true
- },
- "node_modules/parse5": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
- "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
- "dev": true,
- "dependencies": {
- "entities": "^6.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "dev": true
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pirates": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
- "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/postcss": {
- "version": "8.5.6",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
- "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/postcss"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "nanoid": "^3.3.11",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/postcss-import": {
- "version": "15.1.0",
- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
- "dependencies": {
- "postcss-value-parser": "^4.0.0",
- "read-cache": "^1.0.0",
- "resolve": "^1.1.7"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "postcss": "^8.0.0"
- }
- },
- "node_modules/postcss-js": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
- "dev": true,
- "dependencies": {
- "camelcase-css": "^2.0.1"
- },
- "engines": {
- "node": "^12 || ^14 || >= 16"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.4.21"
- }
- },
- "node_modules/postcss-load-config": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
- "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "lilconfig": "^3.0.0",
- "yaml": "^2.3.4"
- },
- "engines": {
- "node": ">= 14"
- },
- "peerDependencies": {
- "postcss": ">=8.0.9",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/postcss-nested": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
- "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "postcss-selector-parser": "^6.1.1"
- },
- "engines": {
- "node": ">=12.0"
- },
- "peerDependencies": {
- "postcss": "^8.2.14"
- }
- },
- "node_modules/postcss-selector-parser": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
- "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
- "dev": true,
- "dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
- },
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ]
- },
- "node_modules/read-cache": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
- "dependencies": {
- "pify": "^2.3.0"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.10",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
- "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
- "dev": true,
- "dependencies": {
- "is-core-module": "^2.16.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/reusify": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
- "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
- "dev": true,
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
- "node_modules/rollup": {
- "version": "4.45.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.45.1.tgz",
- "integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
- "dev": true,
- "dependencies": {
- "@types/estree": "1.0.8"
- },
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=18.0.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "@rollup/rollup-android-arm-eabi": "4.45.1",
- "@rollup/rollup-android-arm64": "4.45.1",
- "@rollup/rollup-darwin-arm64": "4.45.1",
- "@rollup/rollup-darwin-x64": "4.45.1",
- "@rollup/rollup-freebsd-arm64": "4.45.1",
- "@rollup/rollup-freebsd-x64": "4.45.1",
- "@rollup/rollup-linux-arm-gnueabihf": "4.45.1",
- "@rollup/rollup-linux-arm-musleabihf": "4.45.1",
- "@rollup/rollup-linux-arm64-gnu": "4.45.1",
- "@rollup/rollup-linux-arm64-musl": "4.45.1",
- "@rollup/rollup-linux-loongarch64-gnu": "4.45.1",
- "@rollup/rollup-linux-powerpc64le-gnu": "4.45.1",
- "@rollup/rollup-linux-riscv64-gnu": "4.45.1",
- "@rollup/rollup-linux-riscv64-musl": "4.45.1",
- "@rollup/rollup-linux-s390x-gnu": "4.45.1",
- "@rollup/rollup-linux-x64-gnu": "4.45.1",
- "@rollup/rollup-linux-x64-musl": "4.45.1",
- "@rollup/rollup-win32-arm64-msvc": "4.45.1",
- "@rollup/rollup-win32-ia32-msvc": "4.45.1",
- "@rollup/rollup-win32-x64-msvc": "4.45.1",
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
- "node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/seroval": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.3.2.tgz",
- "integrity": "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/seroval-plugins": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.3.2.tgz",
- "integrity": "sha512-0QvCV2lM3aj/U3YozDiVwx9zpH0q8A60CTWIv4Jszj/givcudPb48B+rkU5D51NJ0pTpweGMttHjboPa9/zoIQ==",
- "engines": {
- "node": ">=10"
- },
- "peerDependencies": {
- "seroval": "^1.0"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/signal-exit": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
- "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
- "dev": true,
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/solid-js": {
- "version": "1.9.7",
- "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.7.tgz",
- "integrity": "sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==",
- "dependencies": {
- "csstype": "^3.1.0",
- "seroval": "~1.3.0",
- "seroval-plugins": "~1.3.0"
- }
- },
- "node_modules/solid-refresh": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.6.3.tgz",
- "integrity": "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==",
- "dev": true,
- "dependencies": {
- "@babel/generator": "^7.23.6",
- "@babel/helper-module-imports": "^7.22.15",
- "@babel/types": "^7.23.6"
- },
- "peerDependencies": {
- "solid-js": "^1.3"
- }
- },
- "node_modules/source-map-js": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
- "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/string-width": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
- "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
- "dev": true,
- "dependencies": {
- "eastasianwidth": "^0.2.0",
- "emoji-regex": "^9.2.2",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/string-width-cjs": {
- "name": "string-width",
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/string-width-cjs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/string-width-cjs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
- "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/strip-ansi-cjs": {
- "name": "strip-ansi",
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/sucrase": {
- "version": "3.35.0",
- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
- "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
- "dev": true,
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.2",
- "commander": "^4.0.0",
- "glob": "^10.3.10",
- "lines-and-columns": "^1.1.6",
- "mz": "^2.7.0",
- "pirates": "^4.0.1",
- "ts-interface-checker": "^0.1.9"
- },
- "bin": {
- "sucrase": "bin/sucrase",
- "sucrase-node": "bin/sucrase-node"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/tailwindcss": {
- "version": "3.4.17",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
- "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
- "dev": true,
- "dependencies": {
- "@alloc/quick-lru": "^5.2.0",
- "arg": "^5.0.2",
- "chokidar": "^3.6.0",
- "didyoumean": "^1.2.2",
- "dlv": "^1.1.3",
- "fast-glob": "^3.3.2",
- "glob-parent": "^6.0.2",
- "is-glob": "^4.0.3",
- "jiti": "^1.21.6",
- "lilconfig": "^3.1.3",
- "micromatch": "^4.0.8",
- "normalize-path": "^3.0.0",
- "object-hash": "^3.0.0",
- "picocolors": "^1.1.1",
- "postcss": "^8.4.47",
- "postcss-import": "^15.1.0",
- "postcss-js": "^4.0.1",
- "postcss-load-config": "^4.0.2",
- "postcss-nested": "^6.2.0",
- "postcss-selector-parser": "^6.1.2",
- "resolve": "^1.22.8",
- "sucrase": "^3.35.0"
- },
- "bin": {
- "tailwind": "lib/cli.js",
- "tailwindcss": "lib/cli.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
- "dependencies": {
- "any-promise": "^1.0.0"
- }
- },
- "node_modules/thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
- "dependencies": {
- "thenify": ">= 3.1.0 < 4"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/ts-interface-checker": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true
- },
- "node_modules/typescript": {
- "version": "5.8.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
- "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
- "dev": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/undici-types": {
- "version": "6.21.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
- "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
- "dev": true
- },
- "node_modules/update-browserslist-db": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
- "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
- },
- "bin": {
- "update-browserslist-db": "cli.js"
- },
- "peerDependencies": {
- "browserslist": ">= 4.21.0"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
- },
- "node_modules/validate-html-nesting": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/validate-html-nesting/-/validate-html-nesting-1.2.3.tgz",
- "integrity": "sha512-kdkWdCl6eCeLlRShJKbjVOU2kFKxMF8Ghu50n+crEoyx+VKm3FxAxF9z4DCy6+bbTOqNW0+jcIYRnjoIRzigRw==",
- "dev": true
- },
- "node_modules/vite": {
- "version": "5.4.19",
- "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz",
- "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==",
- "dev": true,
- "dependencies": {
- "esbuild": "^0.21.3",
- "postcss": "^8.4.43",
- "rollup": "^4.20.0"
- },
- "bin": {
- "vite": "bin/vite.js"
- },
- "engines": {
- "node": "^18.0.0 || >=20.0.0"
- },
- "funding": {
- "url": "https://github.com/vitejs/vite?sponsor=1"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.3"
- },
- "peerDependencies": {
- "@types/node": "^18.0.0 || >=20.0.0",
- "less": "*",
- "lightningcss": "^1.21.0",
- "sass": "*",
- "sass-embedded": "*",
- "stylus": "*",
- "sugarss": "*",
- "terser": "^5.4.0"
- },
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "less": {
- "optional": true
- },
- "lightningcss": {
- "optional": true
- },
- "sass": {
- "optional": true
- },
- "sass-embedded": {
- "optional": true
- },
- "stylus": {
- "optional": true
- },
- "sugarss": {
- "optional": true
- },
- "terser": {
- "optional": true
- }
- }
- },
- "node_modules/vite-plugin-solid": {
- "version": "2.11.7",
- "resolved": "https://registry.npmjs.org/vite-plugin-solid/-/vite-plugin-solid-2.11.7.tgz",
- "integrity": "sha512-5TgK1RnE449g0Ryxb9BXqem89RSy7fE8XGVCo+Gw84IHgPuPVP7nYNP6WBVAaY/0xw+OqfdQee+kusL0y3XYNg==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.23.3",
- "@types/babel__core": "^7.20.4",
- "babel-preset-solid": "^1.8.4",
- "merge-anything": "^5.1.7",
- "solid-refresh": "^0.6.3",
- "vitefu": "^1.0.4"
- },
- "peerDependencies": {
- "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*",
- "solid-js": "^1.7.2",
- "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
- },
- "peerDependenciesMeta": {
- "@testing-library/jest-dom": {
- "optional": true
- }
- }
- },
- "node_modules/vitefu": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz",
- "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==",
- "dev": true,
- "peerDependencies": {
- "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
- },
- "peerDependenciesMeta": {
- "vite": {
- "optional": true
- }
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
- "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^6.1.0",
- "string-width": "^5.0.1",
- "strip-ansi": "^7.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs": {
- "name": "wrap-ansi",
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/wrap-ansi-cjs/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
- "node_modules/yaml": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
- "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
- "dev": true,
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- }
- }
- }
-}
diff --git a/pulse-test-staging/frontend-modern/package.json b/pulse-test-staging/frontend-modern/package.json
deleted file mode 100644
index 062e1c261..000000000
--- a/pulse-test-staging/frontend-modern/package.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "name": "pulse-modern",
- "version": "1.0.0",
- "description": "Modern type-safe frontend for Pulse monitoring",
- "type": "module",
- "author": "rcourtman",
- "license": "MIT",
- "repository": {
- "type": "git",
- "url": "https://github.com/rcourtman/Pulse.git"
- },
- "bugs": {
- "url": "https://github.com/rcourtman/Pulse/issues"
- },
- "homepage": "https://github.com/rcourtman/Pulse",
- "scripts": {
- "dev": "vite",
- "build": "tsc && vite build",
- "preview": "vite preview",
- "generate-types": "cd ../scripts && go run generate-types.go",
- "type-check": "tsc --noEmit"
- },
- "dependencies": {
- "@solidjs/router": "^0.10.0",
- "solid-js": "^1.8.0"
- },
- "devDependencies": {
- "@types/node": "^20.10.0",
- "autoprefixer": "^10.4.0",
- "postcss": "^8.4.0",
- "tailwindcss": "^3.4.0",
- "typescript": "^5.3.0",
- "vite": "^5.0.0",
- "vite-plugin-solid": "^2.8.0"
- }
-}
diff --git a/pulse-test-staging/frontend-modern/postcss.config.js b/pulse-test-staging/frontend-modern/postcss.config.js
deleted file mode 100644
index e99ebc2c0..000000000
--- a/pulse-test-staging/frontend-modern/postcss.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export default {
- plugins: {
- tailwindcss: {},
- autoprefixer: {},
- },
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/public/logo.svg b/pulse-test-staging/frontend-modern/public/logo.svg
deleted file mode 100644
index 22b2ec661..000000000
--- a/pulse-test-staging/frontend-modern/public/logo.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-
- Pulse Logo
-
-
-
-
-
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/App.tsx b/pulse-test-staging/frontend-modern/src/App.tsx
deleted file mode 100644
index ed66e4503..000000000
--- a/pulse-test-staging/frontend-modern/src/App.tsx
+++ /dev/null
@@ -1,290 +0,0 @@
-import { Show, createSignal, createContext, useContext, createEffect, onMount } from 'solid-js';
-import { getGlobalWebSocketStore } from './stores/websocket-global';
-import { Dashboard } from './components/Dashboard/Dashboard';
-import StorageComponent from './components/Storage/Storage';
-import Backups from './components/Backups/Backups';
-import Settings from './components/Settings/Settings';
-import { Alerts } from './pages/Alerts';
-import { ToastContainer } from './components/Toast/Toast';
-import { ErrorBoundary } from './components/ErrorBoundary';
-import { logger } from './utils/logger';
-import { POLLING_INTERVALS, STORAGE_KEYS } from './constants';
-import { UpdatesAPI } from './api/updates';
-import type { VersionInfo } from './api/updates';
-
-type TabType = 'main' | 'storage' | 'backups' | 'alerts' | 'settings';
-
-// Enhanced store type with proper typing
-type EnhancedStore = ReturnType;
-
-// Export WebSocket context for other components
-export const WebSocketContext = createContext();
-export const useWebSocket = () => {
- const context = useContext(WebSocketContext);
- if (!context) {
- throw new Error('useWebSocket must be used within WebSocketContext.Provider');
- }
- return context;
-};
-
-function App() {
- // Get singleton WebSocket store
- const wsStore = getGlobalWebSocketStore();
- const { state, connected, reconnecting } = wsStore;
-
- // Data update indicator
- const [dataUpdated, setDataUpdated] = createSignal(false);
- let updateTimeout: number;
-
- // Flash indicator when data updates
- createEffect(() => {
- // Watch for state changes
- const updateTime = state.lastUpdate;
- if (updateTime && updateTime !== '') {
- setDataUpdated(true);
- window.clearTimeout(updateTimeout);
- updateTimeout = window.setTimeout(() => setDataUpdated(false), POLLING_INTERVALS.DATA_FLASH);
- }
- });
-
- // Tab management
- const [activeTab, setActiveTab] = createSignal('main');
-
- // Version info
- const [versionInfo, setVersionInfo] = createSignal(null);
-
- // Dark mode
- const [darkMode, setDarkMode] = createSignal(
- localStorage.getItem(STORAGE_KEYS.DARK_MODE) === 'true' ||
- window.matchMedia('(prefers-color-scheme: dark)').matches
- );
-
- // Toggle dark mode
- const toggleDarkMode = () => {
- const newMode = !darkMode();
- setDarkMode(newMode);
- localStorage.setItem(STORAGE_KEYS.DARK_MODE, String(newMode));
- if (newMode) {
- document.documentElement.classList.add('dark');
- } else {
- document.documentElement.classList.remove('dark');
- }
- logger.info('Theme changed', { mode: newMode ? 'dark' : 'light' });
- };
-
- // Initialize dark mode
- if (darkMode()) {
- document.documentElement.classList.add('dark');
- }
-
- // Load version info on mount
- onMount(async () => {
- try {
- const version = await UpdatesAPI.getVersion();
- setVersionInfo(version);
- } catch (error) {
- console.error('Failed to load version:', error);
- }
- });
-
- // Pass through the store directly
- const enhancedStore: EnhancedStore = wsStore;
-
- return (
-
-
-
-
- {/* Header */}
-
-
- {/* Tabs */}
-
-
- {/* Main Content */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Footer */}
-
- Pulse | Version: {' '}
-
- {versionInfo()?.version || 'loading...'}
-
- {versionInfo()?.isDevelopment && ' (Development)'}
- {versionInfo()?.isDocker && ' - Docker'}
-
-
-
-
-
-
- );
-}
-
-export default App;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/api/alerts.ts b/pulse-test-staging/frontend-modern/src/api/alerts.ts
deleted file mode 100644
index d8ad0421f..000000000
--- a/pulse-test-staging/frontend-modern/src/api/alerts.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-import type { Alert } from '@/types/api';
-import type { AlertConfig } from '@/types/alerts';
-
-export class AlertsAPI {
- private static baseUrl = '/api/alerts';
-
- static async getActive(): Promise {
- const response = await fetch(`${this.baseUrl}/active`);
- if (!response.ok) {
- throw new Error('Failed to fetch active alerts');
- }
- return response.json();
- }
-
- static async getHistory(params?: {
- limit?: number;
- offset?: number;
- startTime?: string;
- endTime?: string;
- severity?: 'warning' | 'critical' | 'all';
- resourceId?: string;
- }): Promise {
- const queryParams = new URLSearchParams();
- if (params) {
- Object.entries(params).forEach(([key, value]) => {
- if (value !== undefined) {
- queryParams.append(key, value.toString());
- }
- });
- }
-
- const response = await fetch(`${this.baseUrl}/history?${queryParams}`);
- if (!response.ok) {
- throw new Error('Failed to fetch alert history');
- }
- return response.json();
- }
-
- // Removed unused config methods - not implemented in backend
-
- static async acknowledge(alertId: string, user?: string): Promise<{ success: boolean }> {
- const response = await fetch(`${this.baseUrl}/${alertId}/acknowledge`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ user }),
- });
-
- if (!response.ok) {
- throw new Error('Failed to acknowledge alert');
- }
-
- return response.json();
- }
-
- // Alert configuration methods
- static async getConfig(): Promise {
- const response = await fetch(`${this.baseUrl}/config`);
- if (!response.ok) {
- throw new Error('Failed to fetch alert configuration');
- }
- return response.json();
- }
-
- static async updateConfig(config: AlertConfig): Promise<{ success: boolean }> {
- const response = await fetch(`${this.baseUrl}/config`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(config),
- });
-
- if (!response.ok) {
- throw new Error('Failed to update alert configuration');
- }
-
- return response.json();
- }
-
- static async clearAlert(alertId: string): Promise<{ success: boolean }> {
- const response = await fetch(`${this.baseUrl}/${alertId}/clear`, {
- method: 'POST',
- });
-
- if (!response.ok) {
- throw new Error('Failed to clear alert');
- }
-
- return response.json();
- }
-
- static async clearHistory(): Promise<{ success: boolean }> {
- const response = await fetch(`${this.baseUrl}/history`, {
- method: 'DELETE',
- });
-
- if (!response.ok) {
- throw new Error('Failed to clear alert history');
- }
-
- return response.json();
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/api/monitoring.ts b/pulse-test-staging/frontend-modern/src/api/monitoring.ts
deleted file mode 100644
index f46c6d8cb..000000000
--- a/pulse-test-staging/frontend-modern/src/api/monitoring.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import type { State, Performance, Stats } from '@/types/api';
-
-export class MonitoringAPI {
- private static baseUrl = '/api';
-
- static async getState(): Promise {
- const response = await fetch(`${this.baseUrl}/state`);
- if (!response.ok) {
- throw new Error('Failed to fetch monitoring state');
- }
- return response.json();
- }
-
- static async getPerformance(): Promise {
- const response = await fetch(`${this.baseUrl}/performance`);
- if (!response.ok) {
- throw new Error('Failed to fetch performance metrics');
- }
- return response.json();
- }
-
- static async getStats(): Promise {
- const response = await fetch(`${this.baseUrl}/stats`);
- if (!response.ok) {
- throw new Error('Failed to fetch system stats');
- }
- return response.json();
- }
-
- static async exportDiagnostics(): Promise {
- const response = await fetch(`${this.baseUrl}/diagnostics/export`);
- if (!response.ok) {
- throw new Error('Failed to export diagnostics');
- }
- return response.blob();
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/api/nodes.ts b/pulse-test-staging/frontend-modern/src/api/nodes.ts
deleted file mode 100644
index 0b679187d..000000000
--- a/pulse-test-staging/frontend-modern/src/api/nodes.ts
+++ /dev/null
@@ -1,103 +0,0 @@
-import { NodeConfig } from '../types/nodes';
-
-export class NodesAPI {
- private static readonly baseUrl = '/api/config/nodes';
-
- static async getNodes(): Promise {
- const response = await fetch(this.baseUrl);
- if (!response.ok) {
- throw new Error('Failed to fetch nodes');
- }
- // The API returns an array of nodes directly
- const nodes: NodeConfig[] = await response.json();
- return nodes;
- }
-
- static async addNode(node: NodeConfig): Promise<{ success: boolean; message?: string }> {
- const response = await fetch(this.baseUrl, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(node),
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(`Failed to add node: ${error}`);
- }
-
- return response.json();
- }
-
- static async updateNode(nodeId: string, node: NodeConfig): Promise<{ success: boolean; message?: string }> {
- const response = await fetch(`${this.baseUrl}/${nodeId}`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(node),
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(`Failed to update node: ${error}`);
- }
-
- return response.json();
- }
-
- static async deleteNode(nodeId: string): Promise<{ success: boolean; message?: string }> {
- const response = await fetch(`${this.baseUrl}/${nodeId}`, {
- method: 'DELETE',
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(`Failed to delete node: ${error}`);
- }
-
- return response.json();
- }
-
- static async testConnection(node: NodeConfig): Promise<{
- status: string;
- message?: string;
- isCluster?: boolean;
- nodeCount?: number;
- clusterNodeCount?: number;
- datastoreCount?: number;
- }> {
- const response = await fetch(`${this.baseUrl}/test-connection`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(node),
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(error);
- }
-
- return response.json();
- }
-
- static async testExistingNode(nodeId: string): Promise<{
- status: string;
- message?: string;
- latency?: number;
- }> {
- const response = await fetch(`${this.baseUrl}/${nodeId}/test`, {
- method: 'POST',
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(error);
- }
-
- return response.json();
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/api/notifications.ts b/pulse-test-staging/frontend-modern/src/api/notifications.ts
deleted file mode 100644
index c30c0a3f3..000000000
--- a/pulse-test-staging/frontend-modern/src/api/notifications.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-
-export interface EmailProvider {
- id?: string;
- name: string;
- smtpHost: string;
- smtpPort: number;
- tls: boolean;
- startTLS: boolean;
- authRequired: boolean;
- instructions: string;
- server?: string;
- port?: number;
- security?: 'none' | 'tls' | 'starttls';
-}
-
-export interface WebhookTemplate {
- id?: string;
- service: string;
- name: string;
- urlPattern: string;
- method: string;
- headers: Record;
- payloadTemplate: string;
- instructions: string;
- description?: string;
- template?: {
- url?: string;
- method?: string;
- headers?: Record;
- body?: string;
- };
-}
-
-export interface EmailConfig {
- enabled: boolean;
- provider: string;
- server: string;
- port: number;
- username: string;
- password?: string;
- from: string;
- to: string[];
- tls: boolean;
- starttls: boolean;
-}
-
-export interface Webhook {
- id: string;
- name: string;
- url: string;
- method: string;
- headers: Record;
- template?: string;
- enabled: boolean;
-}
-
-export interface NotificationTestRequest {
- type: 'email' | 'webhook';
- config?: any; // Backend expects different format than frontend types
- webhookId?: string;
-}
-
-export class NotificationsAPI {
- private static baseUrl = '/api/notifications';
-
- // Email configuration
- static async getEmailConfig(): Promise {
- const response = await fetch(`${this.baseUrl}/email`);
- if (!response.ok) {
- throw new Error('Failed to fetch email configuration');
- }
- const backendConfig = await response.json();
-
- // Convert backend field names to frontend field names
- return {
- enabled: backendConfig.enabled || false,
- provider: backendConfig.provider || '',
- server: backendConfig.smtpHost || '',
- port: backendConfig.smtpPort || 587,
- username: backendConfig.username || '',
- password: backendConfig.password || '',
- from: backendConfig.from || '',
- to: backendConfig.to || [],
- tls: backendConfig.tls || false,
- starttls: backendConfig.tls || false // Backend only has TLS field
- };
- }
-
- static async updateEmailConfig(config: EmailConfig): Promise<{ success: boolean }> {
- // Convert frontend field names to backend field names
- const backendConfig = {
- enabled: config.enabled,
- smtpHost: config.server,
- smtpPort: config.port,
- username: config.username,
- password: config.password,
- from: config.from,
- to: config.to,
- tls: config.tls || config.starttls // Backend only has TLS field
- };
-
- const response = await fetch(`${this.baseUrl}/email`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(backendConfig),
- });
-
- if (!response.ok) {
- throw new Error('Failed to update email configuration');
- }
-
- return response.json();
- }
-
- // Webhook management
- static async getWebhooks(): Promise {
- const response = await fetch(`${this.baseUrl}/webhooks`);
- if (!response.ok) {
- throw new Error('Failed to fetch webhooks');
- }
- return response.json();
- }
-
- static async createWebhook(webhook: Omit): Promise {
- const response = await fetch(`${this.baseUrl}/webhooks`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(webhook),
- });
-
- if (!response.ok) {
- throw new Error('Failed to create webhook');
- }
-
- return response.json();
- }
-
- static async updateWebhook(id: string, webhook: Partial): Promise {
- const response = await fetch(`${this.baseUrl}/webhooks/${id}`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(webhook),
- });
-
- if (!response.ok) {
- throw new Error('Failed to update webhook');
- }
-
- return response.json();
- }
-
- static async deleteWebhook(id: string): Promise<{ success: boolean }> {
- const response = await fetch(`${this.baseUrl}/webhooks/${id}`, {
- method: 'DELETE',
- });
-
- if (!response.ok) {
- throw new Error('Failed to delete webhook');
- }
-
- return response.json();
- }
-
- // Templates and providers
- static async getEmailProviders(): Promise {
- const response = await fetch(`${this.baseUrl}/email-providers`);
- if (!response.ok) {
- throw new Error('Failed to fetch email providers');
- }
- return response.json();
- }
-
- static async getWebhookTemplates(): Promise {
- const response = await fetch(`${this.baseUrl}/webhook-templates`);
- if (!response.ok) {
- throw new Error('Failed to fetch webhook templates');
- }
- return response.json();
- }
-
- // Testing
- static async testNotification(request: NotificationTestRequest): Promise<{ success: boolean; message?: string }> {
- const body: { method: string; config?: any } = { method: request.type };
-
- // Include config if provided for testing without saving
- if (request.config) {
- body.config = request.config;
- }
-
- const response = await fetch(`${this.baseUrl}/test`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(body),
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(error || 'Failed to test notification');
- }
-
- return response.json();
- }
-
- static async testWebhook(webhook: Webhook): Promise<{ success: boolean; message?: string }> {
- const response = await fetch(`${this.baseUrl}/webhooks/test`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(webhook),
- });
-
- if (!response.ok) {
- const error = await response.text();
- throw new Error(error || 'Failed to test webhook');
- }
-
- return response.json();
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/api/settings.ts b/pulse-test-staging/frontend-modern/src/api/settings.ts
deleted file mode 100644
index 77c593818..000000000
--- a/pulse-test-staging/frontend-modern/src/api/settings.ts
+++ /dev/null
@@ -1,91 +0,0 @@
-import type {
- SettingsResponse,
- SettingsUpdateRequest
-} from '@/types/settings';
-
-// System settings type matching Go backend
-export interface SystemSettingsUpdate {
- pollingInterval: number; // in seconds
- backendPort?: number;
- frontendPort?: number;
- allowedOrigins?: string;
- connectionTimeout?: number; // in seconds
- updateChannel?: string;
- autoUpdateEnabled?: boolean;
- autoUpdateCheckInterval?: number; // in hours
- autoUpdateTime?: string; // HH:MM format
-}
-
-// Response types
-export interface ApiResponse {
- success?: boolean;
- status?: string;
- message?: string;
- data?: T;
-}
-
-export class SettingsAPI {
- private static baseUrl = '/api';
-
- static async getSettings(): Promise {
- const response = await fetch(`${this.baseUrl}/settings`);
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(errorText || 'Failed to fetch settings');
- }
-
- return response.json() as Promise;
- }
-
- // Full settings update (legacy - avoid using)
- static async updateSettings(settings: SettingsUpdateRequest): Promise {
- const response = await fetch(`${this.baseUrl}/settings/update`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(settings),
- });
-
- if (!response.ok) {
- throw new Error('Failed to update settings');
- }
-
- return response.json() as Promise;
- }
-
- // System settings update (preferred)
- static async updateSystemSettings(settings: SystemSettingsUpdate): Promise {
- const response = await fetch(`${this.baseUrl}/config/system`, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(settings),
- });
-
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(errorText || 'Failed to update system settings');
- }
-
- return response.json() as Promise;
- }
-
- static async validateSettings(settings: SettingsUpdateRequest): Promise {
- const response = await fetch(`${this.baseUrl}/settings/validate`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(settings),
- });
-
- if (!response.ok) {
- throw new Error('Failed to validate settings');
- }
-
- return response.json() as Promise;
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/api/updates.ts b/pulse-test-staging/frontend-modern/src/api/updates.ts
deleted file mode 100644
index 511a85f68..000000000
--- a/pulse-test-staging/frontend-modern/src/api/updates.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-// Remove apiRequest import - use fetch directly
-
-export interface UpdateInfo {
- available: boolean;
- currentVersion: string;
- latestVersion: string;
- releaseNotes: string;
- releaseDate: string;
- downloadUrl: string;
- isPrerelease: boolean;
-}
-
-export interface UpdateStatus {
- status: string;
- progress: number;
- message: string;
- error?: string;
- updatedAt: string;
-}
-
-export interface VersionInfo {
- version: string;
- build: string;
- runtime: string;
- channel?: string;
- isDocker: boolean;
- isDevelopment: boolean;
-}
-
-export class UpdatesAPI {
- static async checkForUpdates(): Promise {
- const response = await fetch('/api/updates/check');
- if (!response.ok) {
- throw new Error('Failed to check for updates');
- }
- return response.json();
- }
-
- static async applyUpdate(downloadUrl: string): Promise<{ status: string; message: string }> {
- const response = await fetch('/api/updates/apply', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ downloadUrl }),
- });
- if (!response.ok) {
- throw new Error('Failed to apply update');
- }
- return response.json();
- }
-
- static async getUpdateStatus(): Promise {
- const response = await fetch('/api/updates/status');
- if (!response.ok) {
- throw new Error('Failed to get update status');
- }
- return response.json();
- }
-
- static async getVersion(): Promise {
- const response = await fetch('/api/version');
- if (!response.ok) {
- throw new Error('Failed to get version');
- }
- return response.json();
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Alerts/CustomRulesTab.tsx b/pulse-test-staging/frontend-modern/src/components/Alerts/CustomRulesTab.tsx
deleted file mode 100644
index 427ef96ed..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Alerts/CustomRulesTab.tsx
+++ /dev/null
@@ -1,178 +0,0 @@
-import { For, Show } from 'solid-js';
-import type { CustomAlertRule } from '@/types/alerts';
-
-interface CustomRulesTabProps {
- rules: CustomAlertRule[];
- onUpdateRules: (rules: CustomAlertRule[]) => void;
- onHasChanges: (hasChanges: boolean) => void;
-}
-
-export function CustomRulesTab(props: CustomRulesTabProps) {
-
- const deleteRule = (ruleId: string) => {
- const updatedRules = props.rules.filter(r => r.id !== ruleId);
- props.onUpdateRules(updatedRules);
- props.onHasChanges(true);
- };
-
- const toggleRule = (ruleId: string) => {
- const updatedRules = props.rules.map(r =>
- r.id === ruleId ? { ...r, enabled: !r.enabled } : r
- );
- props.onUpdateRules(updatedRules);
- props.onHasChanges(true);
- };
-
- const getFilterDescription = (rule: CustomAlertRule): string => {
- return rule.filterConditions.filters.map(filter => {
- if (filter.type === 'metric' && filter.field && filter.operator && filter.value !== undefined) {
- return `${filter.field} ${filter.operator} ${filter.value}%`;
- } else if (filter.type === 'text' && filter.field && filter.value) {
- return `${filter.field}: ${filter.value}`;
- } else {
- return filter.rawText || '';
- }
- }).join(` ${rule.filterConditions.logicalOperator} `);
- };
-
- const getThresholdsSummary = (rule: CustomAlertRule): string => {
- const parts: string[] = [];
- if (rule.thresholds.cpu !== undefined) parts.push(`CPU: ${rule.thresholds.cpu}%`);
- if (rule.thresholds.memory !== undefined) parts.push(`Memory: ${rule.thresholds.memory}%`);
- if (rule.thresholds.disk !== undefined) parts.push(`Disk: ${rule.thresholds.disk}%`);
- return parts.length > 0 ? parts.join(', ') : 'Using global defaults';
- };
-
- return (
-
- {/* Header */}
-
-
Custom Alert Rules
-
- Custom rules apply specific thresholds to guests matching filter conditions.
- Rules are evaluated in priority order (higher number = higher priority).
-
-
-
- {/* Priority Order Explanation */}
-
-
-
-
-
-
-
Alert Priority Order:
-
- Guest-specific overrides (highest priority)
- Custom rules (evaluated by priority number)
- Global default thresholds (lowest priority)
-
-
-
-
-
- {/* Rules List */}
-
0} fallback={
-
-
-
-
-
- No custom alert rules defined yet. Create rules from the Dashboard by applying filters and clicking "Create Alert".
-
-
- }>
-
-
b.priority - a.priority)}>
- {(rule) => (
-
-
-
-
-
-
{rule.name}
-
- {rule.enabled ? 'Active' : 'Disabled'}
-
-
- Priority: {rule.priority}
-
-
-
- {rule.description}
-
-
-
-
toggleRule(rule.id)}
- class="p-1.5 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 transition-colors"
- title={rule.enabled ? "Disable rule" : "Enable rule"}
- >
-
-
- }>
-
-
-
-
-
deleteRule(rule.id)}
- class="p-1.5 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 transition-colors"
- title="Delete rule"
- >
-
-
-
-
-
-
-
-
-
-
Filters:
-
-
- {getFilterDescription(rule)}
-
-
-
-
-
- Thresholds:
-
- {getThresholdsSummary(rule)}
-
-
-
-
-
-
Notify:
-
-
-
- Email
-
-
-
-
- Webhook
-
-
-
-
-
-
-
-
- )}
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Alerts/EmailProviderSelect.tsx b/pulse-test-staging/frontend-modern/src/components/Alerts/EmailProviderSelect.tsx
deleted file mode 100644
index ae3199a8f..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Alerts/EmailProviderSelect.tsx
+++ /dev/null
@@ -1,324 +0,0 @@
-import { createSignal, createEffect, Show, For } from 'solid-js';
-import { NotificationsAPI } from '@/api/notifications';
-
-interface EmailProvider {
- name: string;
- smtpHost: string;
- smtpPort: number;
- tls: boolean;
- startTLS: boolean;
- authRequired: boolean;
- instructions: string;
-}
-
-interface EmailConfig {
- enabled: boolean;
- provider: string;
- smtpHost: string;
- smtpPort: number;
- from: string;
- username: string;
- password: string;
- to: string[];
- tls: boolean;
- startTLS: boolean;
- replyTo: string;
- maxRetries: number;
- retryDelay: number;
- rateLimit: number;
-}
-
-interface EmailProviderSelectProps {
- config: EmailConfig;
- onChange: (config: EmailConfig) => void;
- onTest: () => void;
- testing?: boolean;
-}
-
-export function EmailProviderSelect(props: EmailProviderSelectProps) {
- const [providers, setProviders] = createSignal([]);
- const [showProviders, setShowProviders] = createSignal(false);
- const [showAdvanced, setShowAdvanced] = createSignal(false);
-
- // Load email providers
- createEffect(async () => {
- try {
- const data = await NotificationsAPI.getEmailProviders();
- setProviders(data);
- } catch (err) {
- console.error('Failed to load email providers:', err);
- }
- });
-
- const selectProvider = (provider: EmailProvider) => {
- props.onChange({
- ...props.config,
- provider: provider.name,
- smtpHost: provider.smtpHost,
- smtpPort: provider.smtpPort,
- tls: provider.tls,
- startTLS: provider.startTLS,
- username: provider.name === 'SendGrid' ? 'apikey' : props.config.username,
- });
- setShowProviders(false);
- };
-
- const currentProvider = () => providers().find(p => p.name === props.config.provider);
-
- return (
-
- {/* Provider Selection */}
-
-
-
- Email Provider
-
- setShowProviders(!showProviders())}
- class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400"
- >
- {props.config.provider || 'Select Provider'} →
-
-
-
-
-
-
- {(provider) => (
- selectProvider(provider)}
- class={`p-3 text-left rounded-lg border transition-all ${
- props.config.provider === provider.name
- ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
- : 'border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700/50'
- }`}
- >
-
- {provider.name}
-
-
- {provider.smtpHost}:{provider.smtpPort}
-
-
- )}
-
-
-
-
-
-
-
- Setup Instructions
-
-
- {currentProvider()!.instructions}
-
-
-
-
-
- {/* Basic Configuration */}
-
-
- {/* Recipients */}
-
-
- Recipients (one per line)
-
- Leave empty to send to the From address
-
-
-
-
- {/* Advanced Settings */}
-
-
setShowAdvanced(!showAdvanced())}
- class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400 flex items-center gap-1"
- >
-
-
-
- Advanced Settings
-
-
-
-
-
-
-
- props.onChange({ ...props.config, tls: e.currentTarget.checked })}
- class="rounded border-gray-300 dark:border-gray-600 text-blue-600"
- />
- Use TLS
-
-
-
-
-
- props.onChange({ ...props.config, startTLS: e.currentTarget.checked })}
- class="rounded border-gray-300 dark:border-gray-600 text-blue-600"
- />
- Use STARTTLS
-
-
-
-
-
- Rate Limit
-
-
- props.onChange({ ...props.config, rateLimit: parseInt(e.currentTarget.value) })}
- class="w-20 px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600"
- />
- /min
-
-
-
-
-
-
-
-
-
- {/* Test Button */}
-
-
- {props.testing ? 'Sending Test Email...' : 'Send Test Email'}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Alerts/OverrideModal.tsx b/pulse-test-staging/frontend-modern/src/components/Alerts/OverrideModal.tsx
deleted file mode 100644
index b05154b3c..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Alerts/OverrideModal.tsx
+++ /dev/null
@@ -1,340 +0,0 @@
-import { createSignal, Show, For, createEffect } from 'solid-js';
-import { Portal } from 'solid-js/web';
-import { ThresholdSlider } from '@/components/Dashboard/ThresholdSlider';
-
-interface Override {
- id?: string; // Full guest ID (e.g. "Main-node1-105")
- guestName: string;
- vmid: number;
- type: string;
- node: string;
- instance?: string;
- thresholds: {
- cpu?: number;
- memory?: number;
- disk?: number;
- diskRead?: number;
- diskWrite?: number;
- networkIn?: number;
- networkOut?: number;
- };
-}
-
-interface OverrideModalProps {
- isOpen: boolean;
- onClose: () => void;
- onSave: (override: Override) => void;
- existingOverride?: Override;
- guests: Array<{ id: string; name: string; vmid: number; type: string; node: string; instance: string }>;
-}
-
-export function OverrideModal(props: OverrideModalProps) {
- // Initialize state only when modal opens, not on every render
- const [selectedGuest, setSelectedGuest] = createSignal('');
-
- // Store the select element ref
- let selectRef: HTMLSelectElement | undefined;
- const [thresholds, setThresholds] = createSignal({
- cpu: 80,
- memory: 80,
- disk: 80,
- diskRead: 0,
- diskWrite: 0,
- networkIn: 0,
- networkOut: 0
- });
-
- const [enabledMetrics, setEnabledMetrics] = createSignal({
- cpu: false,
- memory: false,
- disk: false,
- diskRead: false,
- diskWrite: false,
- networkIn: false,
- networkOut: false
- });
-
- // Maintain select value when guests change
- createEffect(() => {
- if (selectRef && selectedGuest()) {
- const currentValue = selectedGuest();
- // Use requestAnimationFrame to ensure DOM has updated
- requestAnimationFrame(() => {
- if (selectRef) {
- selectRef.value = currentValue;
- }
- });
- }
- });
-
- // Reset state when modal opens
- createEffect(() => {
- if (props.isOpen) {
- if (props.existingOverride) {
- setSelectedGuest(`${props.existingOverride.vmid}`);
- setThresholds({
- cpu: props.existingOverride.thresholds.cpu || 80,
- memory: props.existingOverride.thresholds.memory || 80,
- disk: props.existingOverride.thresholds.disk || 80,
- diskRead: props.existingOverride.thresholds.diskRead || 0,
- diskWrite: props.existingOverride.thresholds.diskWrite || 0,
- networkIn: props.existingOverride.thresholds.networkIn || 0,
- networkOut: props.existingOverride.thresholds.networkOut || 0
- });
- setEnabledMetrics({
- cpu: props.existingOverride.thresholds.cpu !== undefined,
- memory: props.existingOverride.thresholds.memory !== undefined,
- disk: props.existingOverride.thresholds.disk !== undefined,
- diskRead: props.existingOverride.thresholds.diskRead !== undefined,
- diskWrite: props.existingOverride.thresholds.diskWrite !== undefined,
- networkIn: props.existingOverride.thresholds.networkIn !== undefined,
- networkOut: props.existingOverride.thresholds.networkOut !== undefined
- });
- } else {
- // Reset to defaults for new override
- setSelectedGuest('');
- setThresholds({
- cpu: 80,
- memory: 80,
- disk: 80,
- diskRead: 0,
- diskWrite: 0,
- networkIn: 0,
- networkOut: 0
- });
- setEnabledMetrics({
- cpu: false,
- memory: false,
- disk: false,
- diskRead: false,
- diskWrite: false,
- networkIn: false,
- networkOut: false
- });
- }
- }
- });
-
- const handleSave = () => {
- const guest = props.guests.find(g => g.vmid.toString() === selectedGuest());
- if (!guest) return;
-
- const enabledThresholds: Override['thresholds'] = {};
- const enabled = enabledMetrics();
- const thresh = thresholds();
-
- if (enabled.cpu && thresh.cpu !== undefined) enabledThresholds.cpu = thresh.cpu;
- if (enabled.memory && thresh.memory !== undefined) enabledThresholds.memory = thresh.memory;
- if (enabled.disk && thresh.disk !== undefined) enabledThresholds.disk = thresh.disk;
- if (enabled.diskRead && thresh.diskRead) enabledThresholds.diskRead = thresh.diskRead;
- if (enabled.diskWrite && thresh.diskWrite) enabledThresholds.diskWrite = thresh.diskWrite;
- if (enabled.networkIn && thresh.networkIn) enabledThresholds.networkIn = thresh.networkIn;
- if (enabled.networkOut && thresh.networkOut) enabledThresholds.networkOut = thresh.networkOut;
-
- props.onSave({
- id: guest.id, // Pass the full guest ID
- guestName: guest.name,
- vmid: guest.vmid,
- type: guest.type,
- node: guest.node,
- instance: guest.instance,
- thresholds: enabledThresholds
- });
- };
-
- return (
-
-
-
-
- {/* Header */}
-
-
- {props.existingOverride ? 'Edit Guest Override' : 'Add Guest Override'}
-
-
-
- {/* Content */}
-
- {/* Guest Selection */}
-
-
-
- Select Guest
-
- {
- const value = e.currentTarget.value;
- setSelectedGuest(value);
- }}
- ref={(el) => {
- selectRef = el;
- }}
- >
- Choose a guest...
-
- {(guest) => (
-
- {guest.name} ({guest.vmid}) - {guest.type} on {guest.node}
-
- )}
-
-
-
-
-
- {/* Threshold Overrides */}
-
-
- Threshold Overrides
-
-
- {/* CPU */}
-
-
setEnabledMetrics({...enabledMetrics(), cpu: e.currentTarget.checked})}
- class="mt-1 rounded border-gray-300 dark:border-gray-600"
- />
-
-
CPU Usage
-
-
- setThresholds({...thresholds(), cpu: v})}
- type="cpu"
- />
-
-
- {thresholds().cpu || 80}%
-
-
-
-
-
- {/* Memory */}
-
-
setEnabledMetrics({...enabledMetrics(), memory: e.currentTarget.checked})}
- class="mt-1 rounded border-gray-300 dark:border-gray-600"
- />
-
-
Memory Usage
-
-
- setThresholds({...thresholds(), memory: v})}
- type="memory"
- />
-
-
- {thresholds().memory || 85}%
-
-
-
-
-
- {/* Disk */}
-
-
setEnabledMetrics({...enabledMetrics(), disk: e.currentTarget.checked})}
- class="mt-1 rounded border-gray-300 dark:border-gray-600"
- />
-
-
Disk Usage
-
-
- setThresholds({...thresholds(), disk: v})}
- type="disk"
- />
-
-
- {thresholds().disk || 90}%
-
-
-
-
-
- {/* I/O Metrics */}
-
-
-
setEnabledMetrics({...enabledMetrics(), diskRead: e.currentTarget.checked})}
- class="mt-1 rounded border-gray-300 dark:border-gray-600"
- />
-
- Disk Read
- setThresholds({...thresholds(), diskRead: parseInt(e.currentTarget.value)})}
- class="w-full px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600"
- >
- Off
- 10 MB/s
- 50 MB/s
- 100 MB/s
- 500 MB/s
-
-
-
-
-
-
setEnabledMetrics({...enabledMetrics(), diskWrite: e.currentTarget.checked})}
- class="mt-1 rounded border-gray-300 dark:border-gray-600"
- />
-
- Disk Write
- setThresholds({...thresholds(), diskWrite: parseInt(e.currentTarget.value)})}
- class="w-full px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600"
- >
- Off
- 10 MB/s
- 50 MB/s
- 100 MB/s
- 500 MB/s
-
-
-
-
-
-
-
- {/* Footer */}
-
-
- Cancel
-
-
- Save Override
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Alerts/WebhookConfig.tsx b/pulse-test-staging/frontend-modern/src/components/Alerts/WebhookConfig.tsx
deleted file mode 100644
index e8f8f2011..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Alerts/WebhookConfig.tsx
+++ /dev/null
@@ -1,326 +0,0 @@
-import { createSignal, createEffect, Show, For } from 'solid-js';
-import { NotificationsAPI } from '@/api/notifications';
-
-interface Webhook {
- id?: string;
- name: string;
- url: string;
- method: string;
- service: string;
- headers: Record;
- enabled: boolean;
-}
-
-interface WebhookTemplate {
- service: string;
- name: string;
- urlPattern: string;
- method: string;
- headers: Record;
- payloadTemplate: string;
- instructions: string;
-}
-
-interface WebhookConfigProps {
- webhooks: Webhook[];
- onAdd: (webhook: Webhook) => void;
- onUpdate: (webhook: Webhook) => void;
- onDelete: (id: string) => void;
- onTest: (id: string) => void;
- testing?: string | null;
-}
-
-export function WebhookConfig(props: WebhookConfigProps) {
- const [adding, setAdding] = createSignal(false);
- const [editingId, setEditingId] = createSignal(null);
- const [formData, setFormData] = createSignal({
- name: '',
- url: '',
- method: 'POST',
- service: 'generic',
- headers: { 'Content-Type': 'application/json' },
- enabled: true
- });
- const [templates, setTemplates] = createSignal([]);
- const [showServiceDropdown, setShowServiceDropdown] = createSignal(false);
-
- // Load webhook templates
- createEffect(async () => {
- try {
- const data = await NotificationsAPI.getWebhookTemplates();
- setTemplates(data);
- } catch (err) {
- console.error('Failed to load webhook templates:', err);
- }
- });
-
- const saveWebhook = () => {
- const data = formData();
- if (!data.name || !data.url) return;
-
- if (editingId()) {
- props.onUpdate({ ...data, id: editingId()! });
- setEditingId(null);
- setAdding(false);
- } else {
- props.onAdd(data);
- // Reset form but keep adding state true
- setFormData({
- name: '',
- url: '',
- method: 'POST',
- service: 'generic',
- headers: { 'Content-Type': 'application/json' },
- enabled: true
- });
- }
- };
-
- const cancelForm = () => {
- setAdding(false);
- setEditingId(null);
- setFormData({
- name: '',
- url: '',
- method: 'POST',
- service: 'generic',
- headers: { 'Content-Type': 'application/json' },
- enabled: true
- });
- };
-
- const editWebhook = (webhook: Webhook) => {
- setEditingId(webhook.id!);
- setFormData(webhook);
- setAdding(true);
- };
-
- const selectService = (service: string) => {
- const template = templates().find(t => t.service === service);
- if (template) {
- setFormData({
- ...formData(),
- service: template.service,
- method: template.method,
- headers: { ...template.headers },
- name: formData().name || template.name
- });
- }
- setShowServiceDropdown(false);
- };
-
- const currentTemplate = () => templates().find(t => t.service === formData().service);
- const serviceName = (service: string) => {
- const names: Record = {
- generic: 'Generic',
- discord: 'Discord',
- slack: 'Slack',
- teams: 'Microsoft Teams',
- 'teams-adaptive': 'Teams (Adaptive)',
- pagerduty: 'PagerDuty'
- };
- return names[service] || service;
- };
-
- return (
-
- {/* Existing Webhooks List */}
-
0}>
-
-
- {(webhook) => (
-
-
-
-
-
- {webhook.name}
-
-
- {serviceName(webhook.service)}
-
-
- {webhook.method}
-
- {!webhook.enabled && (
-
- Disabled
-
- )}
-
-
- {webhook.url}
-
-
-
- props.onTest(webhook.id!)}
- disabled={props.testing === webhook.id}
- class="px-3 py-1 text-xs text-gray-600 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300 disabled:opacity-50"
- >
- {props.testing === webhook.id ? 'Testing...' : 'Test'}
-
- editWebhook(webhook)}
- class="px-3 py-1 text-xs text-blue-600 hover:text-blue-700 dark:text-blue-400"
- >
- Edit
-
- props.onDelete(webhook.id!)}
- class="px-3 py-1 text-xs text-red-600 hover:text-red-700 dark:text-red-400"
- >
- Delete
-
-
-
-
- )}
-
-
-
-
- {/* Add/Edit Form */}
-
-
- {/* Service Selection */}
-
-
-
- Service Type
-
- setShowServiceDropdown(!showServiceDropdown())}
- class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400"
- >
- {serviceName(formData().service)} →
-
-
-
-
-
-
- {(service) => (
- selectService(service)}
- class={`p-3 text-left rounded-lg border transition-all ${
- formData().service === service
- ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20'
- : 'border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700/50'
- }`}
- >
-
- {serviceName(service)}
-
-
- {service === 'generic' ? 'Custom webhook endpoint' :
- service === 'discord' ? 'Discord server webhook' :
- service === 'slack' ? 'Slack incoming webhook' :
- service === 'teams' ? 'Microsoft Teams webhook' :
- service === 'teams-adaptive' ? 'Teams with Adaptive Cards' :
- 'PagerDuty Events API v2'}
-
-
- )}
-
-
-
-
-
-
-
- Setup Instructions
-
-
- {currentTemplate()!.instructions}
-
-
-
-
-
- {/* Basic Configuration */}
-
-
-
- Name
-
- setFormData({ ...formData(), name: e.currentTarget.value })}
- placeholder={currentTemplate()?.name || 'My Webhook'}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600"
- />
-
-
-
-
- HTTP Method
-
- setFormData({ ...formData(), method: e.currentTarget.value })}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600"
- >
- POST
- PUT
- PATCH
-
-
-
-
-
-
- Webhook URL
-
- setFormData({ ...formData(), url: e.currentTarget.value })}
- placeholder={currentTemplate()?.urlPattern || 'https://example.com/webhook'}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600 font-mono"
- />
-
-
-
-
- setFormData({ ...formData(), enabled: e.currentTarget.checked })}
- class="rounded border-gray-300 dark:border-gray-600 text-blue-600"
- />
- Enable this webhook
-
-
-
-
-
- Cancel
-
-
- {editingId() ? 'Update' : 'Add'} Webhook
-
-
-
-
-
- {/* Add Webhook Button */}
-
- setAdding(true)}
- class="w-full py-2 text-sm border border-dashed border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors text-gray-600 dark:text-gray-400"
- >
- + Add Webhook
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Backups/Backups.tsx b/pulse-test-staging/frontend-modern/src/components/Backups/Backups.tsx
deleted file mode 100644
index 4ebdde6d5..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Backups/Backups.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Component, Show } from 'solid-js';
-import { useWebSocket } from '@/App';
-import UnifiedBackups from './UnifiedBackups';
-
-const Backups: Component = () => {
- const { state, connected } = useWebSocket();
-
- return (
-
- {/* Loading State */}
-
-
-
-
-
Loading backup information...
-
-
-
-
- {/* Disconnected State */}
-
-
-
-
-
-
-
Connection Lost
-
Unable to connect to the backend server. Attempting to reconnect...
-
-
-
-
- {/* Main Content - Unified Backups View */}
-
-
-
-
- );
-};
-
-export default Backups;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Backups/UnifiedBackups.tsx b/pulse-test-staging/frontend-modern/src/components/Backups/UnifiedBackups.tsx
deleted file mode 100644
index 84c23f088..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Backups/UnifiedBackups.tsx
+++ /dev/null
@@ -1,1536 +0,0 @@
-import { Component, createSignal, Show, For, createMemo, createEffect } from 'solid-js';
-import { useWebSocket } from '@/App';
-import { formatBytes, formatAbsoluteTime, formatRelativeTime } from '@/utils/format';
-
-type BackupType = 'snapshot' | 'local' | 'remote';
-type GuestType = 'VM' | 'LXC';
-
-interface UnifiedBackup {
- backupType: BackupType;
- vmid: number;
- name: string;
- type: GuestType;
- node: string;
- backupTime: number;
- backupName: string;
- description: string;
- status: string;
- size: number | null;
- storage: string | null;
- datastore: string | null;
- namespace: string | null;
- verified: boolean | null;
- protected: boolean;
-}
-
-interface DateGroup {
- label: string;
- items: UnifiedBackup[];
-}
-
-const UnifiedBackups: Component = () => {
- const { state } = useWebSocket();
- const [searchTerm, setSearchTerm] = createSignal('');
- const [typeFilter, setTypeFilter] = createSignal<'all' | GuestType>('all');
- const [backupTypeFilter, setBackupTypeFilter] = createSignal<'all' | BackupType>('all');
- const [sortKey, setSortKey] = createSignal('backupTime');
- const [sortDirection, setSortDirection] = createSignal<'asc' | 'desc'>('desc');
- const [selectedDateRange, setSelectedDateRange] = createSignal<{ start: number; end: number } | null>(null);
- const [chartTimeRange, setChartTimeRange] = createSignal(30);
- const [tooltip, setTooltip] = createSignal<{ text: string; x: number; y: number } | null>(null);
- const [showFilters, setShowFilters] = createSignal(
- localStorage.getItem('backupsShowFilters') !== null
- ? localStorage.getItem('backupsShowFilters') === 'true'
- : false // Default to collapsed
- );
- const [useRelativeTime, setUseRelativeTime] = createSignal(
- localStorage.getItem('backupsUseRelativeTime') !== null
- ? localStorage.getItem('backupsUseRelativeTime') === 'true'
- : false // Default to absolute time
- );
-
- // Helper functions
- const getDaySuffix = (day: number) => {
- if (day >= 11 && day <= 13) return 'th';
- switch (day % 10) {
- case 1: return 'st';
- case 2: return 'nd';
- case 3: return 'rd';
- default: return 'th';
- }
- };
-
- const truncateMiddle = (str: string, maxLength: number) => {
- if (!str || str.length <= maxLength) return str;
- const start = Math.ceil(maxLength / 2) - 2;
- const end = Math.floor(maxLength / 2) - 2;
- return str.substring(0, start) + '...' + str.substring(str.length - end);
- };
-
- const formatTime = (timestamp: number) => {
- return useRelativeTime() ? formatRelativeTime(timestamp) : formatAbsoluteTime(timestamp);
- };
-
- // Check if we have any backup data yet
- const isLoading = createMemo(() => {
- return !state.pveBackups?.guestSnapshots &&
- !state.pveBackups?.storageBackups &&
- !state.pbsBackups?.length &&
- !state.pbs?.length;
- });
-
- // Normalize all backup data into unified format
- const normalizedData = createMemo(() => {
- const unified: UnifiedBackup[] = [];
- const seenBackups = new Set(); // Track backups to avoid duplicates
-
- // Debug mode - remove in production
- const debugMode = false;
-
- // Normalize snapshots
- state.pveBackups?.guestSnapshots?.forEach((snapshot) => {
- unified.push({
- backupType: 'snapshot',
- vmid: snapshot.vmid,
- name: snapshot.name || '',
- type: snapshot.type === 'qemu' ? 'VM' : 'LXC',
- node: snapshot.node,
- backupTime: snapshot.time ? new Date(snapshot.time).getTime() / 1000 : 0,
- backupName: snapshot.name,
- description: snapshot.description || '',
- status: 'ok',
- size: null,
- storage: null,
- datastore: null,
- namespace: null,
- verified: null,
- protected: false
- });
- });
-
- // Process PBS backups FIRST from the new Go backend (state.pbsBackups)
- // This ensures we have the complete PBS data with namespaces
- state.pbsBackups?.forEach((backup) => {
- const backupDate = new Date(backup.backupTime);
- const dateStr = backupDate.toISOString().split('T')[0];
- const timeStr = backupDate.toISOString().split('T')[1].split('.')[0].replace(/:/g, '');
- const backupName = `${backup.backupType}/${backup.vmid}/${dateStr}_${timeStr}`;
-
- // Create a key that matches the format used by PVE storage backups
- // Use just the timestamp in seconds (Unix time) to match ctime format
- const backupTimeSeconds = Math.floor(backupDate.getTime() / 1000);
- const backupKey = `${backup.vmid}-${backupTimeSeconds}`;
- seenBackups.add(backupKey);
-
- if (debugMode) {
- console.log(`PBS backup: vmid=${backup.vmid}, time=${backupTimeSeconds}, key=${backupKey}, verified=${backup.verified}`);
- }
-
- unified.push({
- backupType: 'remote',
- vmid: parseInt(backup.vmid) || 0,
- name: backup.comment || '',
- type: backup.backupType === 'vm' ? 'VM' : 'LXC',
- node: backup.instance || 'PBS',
- backupTime: backupTimeSeconds,
- backupName: backupName,
- description: backup.comment || '',
- status: backup.verified ? 'verified' : 'unverified',
- size: backup.size || null,
- storage: null,
- datastore: backup.datastore || null,
- namespace: backup.namespace || 'root',
- verified: backup.verified || false,
- protected: backup.protected || false
- });
- });
-
- // Normalize local backups (including PBS through PVE storage)
- state.pveBackups?.storageBackups?.forEach((backup) => {
- // Determine if this is actually a PBS backup based on storage
- const backupType = backup.isPBS ? 'remote' : 'local';
-
- // Skip PBS backups that we already have from direct PBS API
- if (backup.isPBS && backup.volid) {
- // Check if we already have this from PBS API using the same key format
- const backupKey = `${backup.vmid}-${backup.ctime}`;
-
- if (debugMode) {
- console.log(`PVE storage backup: vmid=${backup.vmid}, ctime=${backup.ctime}, key=${backupKey}, isPBS=${backup.isPBS}, skip=${seenBackups.has(backupKey)}`);
- }
-
- if (seenBackups.has(backupKey)) {
- return; // Skip duplicate
- }
- }
-
- unified.push({
- backupType: backupType,
- vmid: backup.vmid || 0,
- name: backup.notes || '',
- type: backup.type === 'qemu' ? 'VM' : 'LXC',
- node: backup.node || '',
- backupTime: backup.ctime || 0,
- backupName: backup.volid?.split('/').pop() || '',
- description: backup.notes || '', // Use notes field for PBS backup descriptions
- status: 'ok', // PVE storage doesn't provide verification status
- size: backup.size || null,
- storage: backup.storage || null,
- datastore: backup.isPBS ? backup.storage : null,
- namespace: backup.isPBS ? 'root' : null,
- verified: null, // PVE storage doesn't provide verification status
- protected: backup.protected || false
- });
- });
-
-
- // Normalize PBS backups
- // NOTE: Legacy code - PBS backups are now handled differently in the Go backend
- // The 'backups' field doesn't exist on PBSInstance anymore, and 'snapshots' field
- // doesn't exist on PBSDatastore. This code is kept for reference but commented out.
-
- /*
- state.pbs?.forEach((pbsInstance) => {
- // Check if backups are at the instance level
- if (pbsInstance.backups && Array.isArray(pbsInstance.backups)) {
- pbsInstance.backups.forEach((backup: any) => {
- unified.push({
- backupType: 'remote',
- vmid: backup.vmid || 0,
- name: backup.guestName || '',
- type: backup.type === 'vm' || backup.type === 'qemu' ? 'VM' : 'LXC',
- node: pbsInstance.name || 'PBS',
- backupTime: backup.ctime || backup.backupTime || 0,
- backupName: `${backup.vmid}/${new Date((backup.ctime || backup.backupTime || 0) * 1000).toISOString().split('T')[0]}`,
- description: backup.notes || backup.comment || '',
- status: backup.verified ? 'verified' : 'unverified',
- size: backup.size || null,
- storage: null,
- datastore: backup.datastore || null,
- namespace: backup.namespace || 'root',
- verified: backup.verified || false,
- protected: backup.protected || false
- });
- });
- }
-
- // Also check datastores for snapshots (original JS structure)
- if (pbsInstance.datastores && Array.isArray(pbsInstance.datastores)) {
- pbsInstance.datastores?.forEach((datastore) => {
- if (datastore.snapshots && Array.isArray(datastore.snapshots)) {
- datastore.snapshots.forEach((backup: any) => {
- let totalSize = 0;
- if (backup.files && Array.isArray(backup.files)) {
- totalSize = backup.files.reduce((sum: any, file: any) => sum + (file.size || 0), 0);
- }
-
- unified.push({
- backupType: 'remote',
- vmid: backup['backup-id'] || 0,
- name: backup.comment || '',
- type: backup['backup-type'] === 'vm' || backup['backup-type'] === 'qemu' ? 'VM' : 'LXC',
- node: pbsInstance.name || 'PBS',
- backupTime: backup['backup-time'] || 0,
- backupName: `${backup['backup-id']}/${new Date((backup['backup-time'] || 0) * 1000).toISOString().split('T')[0]}`,
- description: backup.comment || '',
- status: backup.verified ? 'verified' : 'unverified',
- size: totalSize || null,
- storage: null,
- datastore: datastore.name || null,
- namespace: backup.namespace || 'root',
- verified: backup.verified || false,
- protected: backup.protected || false
- });
- });
- }
- });
- }
- });
- */
-
- return unified;
- });
-
- // Apply filters
- const filteredData = createMemo(() => {
- let data = normalizedData();
- const search = searchTerm().toLowerCase();
- const type = typeFilter();
- const backupType = backupTypeFilter();
- const dateRange = selectedDateRange();
-
- // Date range filter
- if (dateRange) {
- data = data.filter(item =>
- item.backupTime >= dateRange.start && item.backupTime <= dateRange.end
- );
- }
-
- // Search filter
- if (search) {
- const searchTerms = search.split(',').map(term => term.trim()).filter(term => term.length > 0);
- data = data.filter(item =>
- searchTerms.some(term => {
- const searchFields = [
- item.vmid?.toString(),
- item.name,
- item.node,
- item.backupName,
- item.description,
- item.storage,
- item.datastore,
- item.namespace
- ].filter(Boolean).map(field => field!.toString().toLowerCase());
-
- return searchFields.some(field => field.includes(term));
- })
- );
- }
-
- // Type filter
- if (type !== 'all') {
- data = data.filter(item => item.type === type);
- }
-
- // Backup type filter
- if (backupType !== 'all') {
- data = data.filter(item => item.backupType === backupType);
- }
-
- // Sort
- const key = sortKey();
- const dir = sortDirection();
- data = [...data].sort((a, b) => {
- let aVal = a[key];
- let bVal = b[key];
-
- // Handle null/undefined/empty values - put at end for both asc and desc
- const aIsEmpty = aVal === null || aVal === undefined || aVal === '';
- const bIsEmpty = bVal === null || bVal === undefined || bVal === '';
-
- if (aIsEmpty && bIsEmpty) return 0;
- if (aIsEmpty) return 1;
- if (bIsEmpty) return -1;
-
- // Type-specific value preparation
- if (key === 'size' || key === 'vmid' || key === 'backupTime') {
- // Ensure numeric comparison
- aVal = typeof aVal === 'number' ? aVal : Number(aVal) || 0;
- bVal = typeof bVal === 'number' ? bVal : Number(bVal) || 0;
- }
-
- // Type-safe comparison
- if (typeof aVal === 'number' && typeof bVal === 'number') {
- if (aVal === bVal) return 0;
- const comparison = aVal < bVal ? -1 : 1;
- return dir === 'asc' ? comparison : -comparison;
- } else {
- // String comparison (case-insensitive)
- const aStr = String(aVal).toLowerCase();
- const bStr = String(bVal).toLowerCase();
-
- if (aStr === bStr) return 0;
- const comparison = aStr < bStr ? -1 : 1;
- return dir === 'asc' ? comparison : -comparison;
- }
- });
-
- return data;
- });
-
- // Group by date
- const groupedData = createMemo(() => {
- // If sorting by time, show date groups
- // Otherwise, show all items in a single group to preserve sort order
- if (sortKey() !== 'backupTime') {
- return [{
- label: 'All Backups',
- items: filteredData()
- }];
- }
-
- const groups: DateGroup[] = [];
- const groupMap = new Map();
- const now = new Date();
- const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
- const yesterday = new Date(today);
- yesterday.setDate(yesterday.getDate() - 1);
-
- const months = ['January', 'February', 'March', 'April', 'May', 'June',
- 'July', 'August', 'September', 'October', 'November', 'December'];
-
- filteredData().forEach(item => {
- const date = new Date(item.backupTime * 1000);
- const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());
-
- let label: string;
- const month = months[date.getMonth()];
- const day = date.getDate();
- const suffix = getDaySuffix(day);
- const absoluteDate = `${month} ${day}${suffix}`;
-
- if (dateOnly.getTime() === today.getTime()) {
- label = `Today (${absoluteDate})`;
- } else if (dateOnly.getTime() === yesterday.getTime()) {
- label = `Yesterday (${absoluteDate})`;
- } else {
- label = absoluteDate;
- }
-
- if (!groupMap.has(label)) {
- groupMap.set(label, []);
- }
- groupMap.get(label)!.push(item);
- });
-
- // Convert to array
- groupMap.forEach((items, label) => {
- groups.push({ label, items });
- });
-
- // Sort groups based on sort direction
- if (sortDirection() === 'desc') {
- // Most recent first
- groups.sort((a, b) => {
- if (a.label.includes('Today')) return -1;
- if (b.label.includes('Today')) return 1;
- if (a.label.includes('Yesterday')) return b.label.includes('Today') ? 1 : -1;
- if (b.label.includes('Yesterday')) return a.label.includes('Today') ? -1 : 1;
-
- // For other dates, use the first item's date
- const dateA = a.items[0]?.backupTime || 0;
- const dateB = b.items[0]?.backupTime || 0;
- return dateB - dateA;
- });
- } else {
- // Oldest first
- groups.sort((a, b) => {
- if (a.label.includes('Today')) return 1;
- if (b.label.includes('Today')) return -1;
- if (a.label.includes('Yesterday')) return a.label.includes('Today') ? -1 : 1;
- if (b.label.includes('Yesterday')) return b.label.includes('Today') ? 1 : -1;
-
- // For other dates, use the first item's date
- const dateA = a.items[0]?.backupTime || 0;
- const dateB = b.items[0]?.backupTime || 0;
- return dateA - dateB;
- });
- }
-
- // Sort items within each group by time (already sorted by filteredData, but we need to maintain it)
- // The items come pre-sorted from filteredData(), so we don't need to re-sort them
-
- return groups;
- });
-
- // Sort handler
- const handleSort = (key: keyof UnifiedBackup) => {
- if (sortKey() === key) {
- // Toggle direction for the same column
- const newDir = sortDirection() === 'asc' ? 'desc' : 'asc';
- setSortDirection(newDir);
- } else {
- // New column - set key and default direction
- setSortKey(key);
- // Set default sort direction based on column type
- // For time and size, default to descending (newest/largest first)
- // For others, default to ascending
- if (key === 'backupTime' || key === 'size') {
- setSortDirection('desc');
- } else {
- setSortDirection('asc');
- }
- }
- };
-
- // Reset filters
- const resetFilters = () => {
- setSearchTerm('');
- setTypeFilter('all');
- setBackupTypeFilter('all');
- setSortKey('backupTime');
- setSortDirection('desc');
- setSelectedDateRange(null);
- setChartTimeRange(30);
- };
-
- // Persist showFilters state
- createEffect(() => {
- localStorage.setItem('backupsShowFilters', showFilters().toString());
- });
-
- // Persist useRelativeTime state
- createEffect(() => {
- localStorage.setItem('backupsUseRelativeTime', useRelativeTime().toString());
- });
-
- // Handle keyboard shortcuts
- let searchInputRef: HTMLInputElement | undefined;
-
- createEffect(() => {
- const handleKeyDown = (e: KeyboardEvent) => {
- // Ignore if user is typing in an input, textarea, or contenteditable
- const target = e.target as HTMLElement;
- const isInputField = target.tagName === 'INPUT' ||
- target.tagName === 'TEXTAREA' ||
- target.tagName === 'SELECT' ||
- target.contentEditable === 'true';
-
- // Escape key behavior
- if (e.key === 'Escape') {
- // First check if we have search/filters to clear
- if (searchTerm().trim() || typeFilter() !== 'all' || backupTypeFilter() !== 'all' ||
- selectedDateRange() !== null || sortKey() !== 'backupTime' || sortDirection() !== 'desc') {
- // Clear search and reset filters
- resetFilters();
-
- // Blur the search input if it's focused
- if (searchInputRef && document.activeElement === searchInputRef) {
- searchInputRef.blur();
- }
- } else if (showFilters()) {
- // No search/filters active, so collapse the filters section
- setShowFilters(false);
- }
- // If filters are already collapsed, do nothing
- } else if (!isInputField && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
- // If it's a printable character and user is not in an input field
- // Expand filters section if collapsed
- if (!showFilters()) {
- setShowFilters(true);
- }
- // Focus the search input and let the character be typed
- if (searchInputRef) {
- searchInputRef.focus();
- // Don't prevent default - let the character be typed
- }
- }
- };
-
- document.addEventListener('keydown', handleKeyDown);
- return () => document.removeEventListener('keydown', handleKeyDown);
- });
-
- // Get age color class
- const getAgeColorClass = (timestamp: number) => {
- if (!timestamp) return 'text-gray-500 dark:text-gray-400';
-
- const now = Date.now() / 1000;
- const diff = now - timestamp;
- const days = diff / 86400;
-
- if (days < 3) return 'text-green-600 dark:text-green-400';
- if (days < 7) return 'text-yellow-600 dark:text-yellow-400';
- if (days < 30) return 'text-orange-500 dark:text-orange-400';
- return 'text-red-600 dark:text-red-400';
- };
-
- // Get size color class
- const getSizeColor = (size: number | null) => {
- if (!size) return '';
- const gb = size / (1024 * 1024 * 1024);
- if (gb < 5) return 'text-green-600 dark:text-green-400';
- if (gb < 20) return 'text-yellow-600 dark:text-yellow-400';
- if (gb < 50) return 'text-orange-600 dark:text-orange-400';
- return 'text-red-600 dark:text-red-400';
- };
-
-
- // Calculate backup frequency data for chart
- const chartData = createMemo(() => {
- const days = chartTimeRange();
- const now = Date.now();
- const startTime = now - (days * 24 * 60 * 60 * 1000);
-
- // Initialize data structure for each day
- const dailyData: { [key: string]: { snapshots: number; pve: number; pbs: number; total: number } } = {};
-
- // Create entries for each day in the range
- for (let i = 0; i < days; i++) {
- const date = new Date(startTime + (i * 24 * 60 * 60 * 1000));
- const dateKey = date.toISOString().split('T')[0];
- dailyData[dateKey] = { snapshots: 0, pve: 0, pbs: 0, total: 0 };
- }
-
- // Use filtered data but WITHOUT date range filter for the chart
- // The chart should show the time range, and filters should affect what's counted
- let dataForChart = normalizedData();
- const search = searchTerm().toLowerCase();
- const type = typeFilter();
- const backupType = backupTypeFilter();
-
- // Apply search filter
- if (search) {
- const searchTerms = search.split(',').map(term => term.trim()).filter(term => term.length > 0);
- dataForChart = dataForChart.filter(item =>
- searchTerms.some(term => {
- const searchFields = [
- item.vmid?.toString(),
- item.name,
- item.node,
- item.backupName,
- item.description,
- item.storage,
- item.datastore,
- item.namespace
- ].filter(Boolean).map(field => field!.toString().toLowerCase());
-
- return searchFields.some(field => field.includes(term));
- })
- );
- }
-
- // Apply type filter
- if (type !== 'all') {
- dataForChart = dataForChart.filter(item => item.type === type);
- }
-
- // Apply backup type filter
- if (backupType !== 'all') {
- dataForChart = dataForChart.filter(item => item.backupType === backupType);
- }
-
- // Count backups per day within the chart time range
- dataForChart.forEach(backup => {
- const backupTime = backup.backupTime * 1000;
- if (backupTime >= startTime && backupTime <= now) {
- const date = new Date(backupTime);
- const dateKey = date.toISOString().split('T')[0];
-
- if (dailyData[dateKey]) {
- dailyData[dateKey].total++;
- if (backup.backupType === 'snapshot') {
- dailyData[dateKey].snapshots++;
- } else if (backup.backupType === 'local') {
- dailyData[dateKey].pve++;
- } else if (backup.backupType === 'remote') {
- dailyData[dateKey].pbs++;
- }
- }
- }
- });
-
- // Convert to array and calculate max value for scaling
- const dataArray = Object.entries(dailyData).map(([date, counts]) => ({
- date,
- ...counts
- }));
-
- const maxValue = Math.max(...dataArray.map(d => d.total), 1);
-
- return { data: dataArray, maxValue };
- });
-
-
- return (
-
- {/* Backup Frequency Chart */}
-
-
-
Backup Frequency
-
-
- setChartTimeRange(7)}
- class={`px-2 py-0.5 text-xs border rounded transition-colors ${
- chartTimeRange() === 7
- ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 border-blue-300 dark:border-blue-700'
- : 'border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700'
- }`}
- >
- 7d
-
- setChartTimeRange(30)}
- class={`px-2 py-0.5 text-xs border rounded transition-colors ${
- chartTimeRange() === 30
- ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 border-blue-300 dark:border-blue-700'
- : 'border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700'
- }`}
- >
- 30d
-
- setChartTimeRange(90)}
- class={`px-2 py-0.5 text-xs border rounded transition-colors ${
- chartTimeRange() === 90
- ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 border-blue-300 dark:border-blue-700'
- : 'border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700'
- }`}
- >
- 90d
-
- setChartTimeRange(365)}
- class={`px-2 py-0.5 text-xs border rounded transition-colors ${
- chartTimeRange() === 365
- ? 'bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 border-blue-300 dark:border-blue-700'
- : 'border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-700'
- }`}
- >
- 1y
-
-
-
-
- Last {chartTimeRange()} days
-
-
- setSelectedDateRange(null)}
- class="px-2 py-0.5 text-xs bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 rounded hover:bg-blue-200 dark:hover:bg-blue-800/50 transition-colors"
- >
- Clear filter
-
-
-
-
-
-
0}
- fallback={
-
-
No backup data for selected time range
-
- }
- >
- {
- // Use createEffect to reactively update the chart
- createEffect(() => {
- if (!el) return;
-
- const data = chartData().data;
- if (data.length === 0) return;
-
- // Wait for next frame to ensure dimensions are available
- requestAnimationFrame(() => {
- const rect = el.getBoundingClientRect();
- if (rect.width === 0 || rect.height === 0) return;
-
- const margin = { top: 10, right: 10, bottom: 30, left: 30 };
- const width = rect.width - margin.left - margin.right;
- const height = 128 - margin.top - margin.bottom;
-
- el.setAttribute('viewBox', `0 0 ${rect.width} 128`);
- el.innerHTML = '';
-
- // Create main group
- const g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
- g.setAttribute('transform', `translate(${margin.left},${margin.top})`);
- el.appendChild(g);
-
- const data = chartData().data;
- const maxValue = chartData().maxValue;
- const xScale = width / Math.max(data.length, 1);
- const barWidth = Math.max(1, Math.min(xScale - 2, 50));
- const yScale = height / maxValue;
-
- // Add grid lines
- const gridGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
- gridGroup.setAttribute('class', 'grid-lines');
- g.appendChild(gridGroup);
-
- // Y-axis grid lines
- const gridCount = 5;
- for (let i = 0; i <= gridCount; i++) {
- const y = height - (i * height / gridCount);
- const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
- line.setAttribute('x1', '0');
- line.setAttribute('y1', y.toString());
- line.setAttribute('x2', width.toString());
- line.setAttribute('y2', y.toString());
- line.setAttribute('stroke', 'currentColor');
- line.setAttribute('stroke-opacity', '0.1');
- line.setAttribute('class', 'text-gray-300 dark:text-gray-600');
- gridGroup.appendChild(line);
- }
-
- // Add Y-axis labels
- if (maxValue <= 5) {
- for (let i = 0; i <= maxValue; i++) {
- const y = height - (i * height / maxValue);
- const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
- text.setAttribute('x', '-5');
- text.setAttribute('y', (y + 3).toString());
- text.setAttribute('text-anchor', 'end');
- text.setAttribute('class', 'text-[10px] fill-gray-500 dark:fill-gray-400');
- text.textContent = i.toString();
- g.appendChild(text);
- }
- } else {
- for (let i = 0; i <= gridCount; i++) {
- const value = Math.round(i * maxValue / gridCount);
- const y = height - (i * height / gridCount);
-
- if (i === 0 || value !== Math.round((i - 1) * maxValue / gridCount)) {
- const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
- text.setAttribute('x', '-5');
- text.setAttribute('y', (y + 3).toString());
- text.setAttribute('text-anchor', 'end');
- text.setAttribute('class', 'text-[10px] fill-gray-500 dark:fill-gray-400');
- text.textContent = value.toString();
- g.appendChild(text);
- }
- }
- }
-
- // Add bars
- const barsGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
- barsGroup.setAttribute('class', 'bars');
- g.appendChild(barsGroup);
-
- data.forEach((d, i) => {
- const barHeight = d.total * yScale;
- const x = Math.max(0, i * xScale + (xScale - barWidth) / 2);
- const y = height - barHeight;
-
- const barGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
- barGroup.setAttribute('class', 'bar-group');
- barGroup.setAttribute('data-date', d.date);
- barGroup.style.cursor = 'pointer';
-
- // Background track for all slots
- const track = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
- track.setAttribute('x', x.toString());
- track.setAttribute('y', (height - 2).toString());
- track.setAttribute('width', barWidth.toString());
- track.setAttribute('height', '2');
- track.setAttribute('rx', '1');
- track.setAttribute('fill', '#d1d5db');
- track.setAttribute('fill-opacity', '0.3');
- barGroup.appendChild(track);
-
- // Click area
- const clickRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
- clickRect.setAttribute('x', (i * xScale).toString());
- clickRect.setAttribute('y', '0');
- clickRect.setAttribute('width', Math.max(1, xScale).toString());
- clickRect.setAttribute('height', height.toString());
- clickRect.setAttribute('fill', 'transparent');
- clickRect.style.cursor = 'pointer';
- barGroup.appendChild(clickRect);
-
- // Main bar
- const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
- rect.setAttribute('x', x.toString());
- rect.setAttribute('y', y.toString());
- rect.setAttribute('width', barWidth.toString());
- rect.setAttribute('height', barHeight.toString());
- rect.setAttribute('rx', '2');
- rect.setAttribute('class', 'backup-bar');
- rect.setAttribute('data-date', d.date);
-
- // Color based on count
- let barColor = '#e5e7eb';
- if (d.total > 0 && d.total <= 5) barColor = '#60a5fa';
- else if (d.total <= 10) barColor = '#34d399';
- else if (d.total > 10) barColor = '#a78bfa';
-
- rect.setAttribute('fill', barColor);
- rect.setAttribute('fill-opacity', '0.8');
- rect.style.transition = 'fill-opacity 0.2s ease';
-
- // Highlight selected date
- if (selectedDateRange() &&
- new Date(d.date).getTime() >= selectedDateRange()!.start * 1000 &&
- new Date(d.date).getTime() <= selectedDateRange()!.end * 1000) {
- rect.classList.add('ring-2', 'ring-blue-500');
- }
-
- barGroup.appendChild(rect);
-
- // Stacked segments
- if (d.total > 0) {
- // PBS (bottom)
- if (d.pbs > 0) {
- const pbsHeight = (d.pbs / d.total) * barHeight;
- const pbsRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
- pbsRect.setAttribute('x', x.toString());
- pbsRect.setAttribute('y', (y + barHeight - pbsHeight).toString());
- pbsRect.setAttribute('width', barWidth.toString());
- pbsRect.setAttribute('height', pbsHeight.toString());
- pbsRect.setAttribute('rx', '2');
- pbsRect.setAttribute('fill', '#8b5cf6');
- pbsRect.setAttribute('fill-opacity', '0.9');
- barGroup.appendChild(pbsRect);
- }
-
- // PVE (middle)
- if (d.pve > 0) {
- const pveHeight = (d.pve / d.total) * barHeight;
- const pveY = y + (d.snapshots / d.total) * barHeight;
- const pveRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
- pveRect.setAttribute('x', x.toString());
- pveRect.setAttribute('y', pveY.toString());
- pveRect.setAttribute('width', barWidth.toString());
- pveRect.setAttribute('height', pveHeight.toString());
- pveRect.setAttribute('fill', '#f97316');
- pveRect.setAttribute('fill-opacity', '0.9');
- barGroup.appendChild(pveRect);
- }
-
- // Snapshots (top)
- if (d.snapshots > 0) {
- const snapshotHeight = (d.snapshots / d.total) * barHeight;
- const snapshotRect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
- snapshotRect.setAttribute('x', x.toString());
- snapshotRect.setAttribute('y', y.toString());
- snapshotRect.setAttribute('width', barWidth.toString());
- snapshotRect.setAttribute('height', snapshotHeight.toString());
- snapshotRect.setAttribute('rx', '2');
- snapshotRect.setAttribute('fill', '#eab308');
- snapshotRect.setAttribute('fill-opacity', '0.9');
- barGroup.appendChild(snapshotRect);
- }
- }
-
- // Hover effects with tooltips
- barGroup.addEventListener('mouseenter', (e) => {
- rect.setAttribute('fill-opacity', '1');
- rect.setAttribute('filter', 'brightness(1.2)');
-
- // Show tooltip
- const date = new Date(d.date);
- const formattedDate = date.toLocaleDateString('en-US', {
- weekday: 'short',
- month: 'short',
- day: 'numeric'
- });
-
- let tooltipText = `${formattedDate}`;
-
- if (d.total > 0) {
- tooltipText += `\nTotal: ${d.total} backup${d.total > 1 ? 's' : ''}`;
-
- const breakdown = [];
- if (d.snapshots > 0) breakdown.push(`${d.snapshots} Snapshot${d.snapshots > 1 ? 's' : ''}`);
- if (d.pve > 0) breakdown.push(`${d.pve} PVE`);
- if (d.pbs > 0) breakdown.push(`${d.pbs} PBS`);
-
- if (breakdown.length > 0) {
- tooltipText += `\n${breakdown.join(', ')}`;
- }
- } else {
- tooltipText += '\nNo backups';
- }
-
- // Get mouse position relative to the page
- const mouseX = e.pageX || e.clientX + window.scrollX;
- const mouseY = e.pageY || e.clientY + window.scrollY;
-
- setTooltip({
- text: tooltipText,
- x: mouseX,
- y: mouseY - 60
- });
- });
-
- barGroup.addEventListener('mouseleave', () => {
- rect.setAttribute('fill-opacity', '0.8');
- rect.removeAttribute('filter');
- setTooltip(null);
- });
-
- // Click to filter
- barGroup.addEventListener('click', () => {
- const clickedDate = new Date(d.date);
- const startOfDay = new Date(clickedDate.setHours(0, 0, 0, 0)).getTime() / 1000;
- const endOfDay = new Date(clickedDate.setHours(23, 59, 59, 999)).getTime() / 1000;
- setSelectedDateRange({ start: startOfDay, end: endOfDay });
- });
-
- barsGroup.appendChild(barGroup);
-
- // Date labels
- let showLabel = false;
- if (chartTimeRange() <= 7) {
- showLabel = true;
- } else if (chartTimeRange() <= 30) {
- showLabel = i % Math.ceil(data.length / 10) === 0 || i === data.length - 1;
- } else if (chartTimeRange() <= 90) {
- const dayOfWeek = new Date(d.date).getDay();
- showLabel = dayOfWeek === 0 || i === 0 || i === data.length - 1;
- } else {
- const date = new Date(d.date);
- showLabel = date.getDate() === 1 || i === 0 || i === data.length - 1;
- }
-
- if (showLabel) {
- const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
- text.setAttribute('x', (x + barWidth / 2).toString());
- text.setAttribute('y', (height + 20).toString());
- text.setAttribute('text-anchor', 'middle');
- text.setAttribute('class', 'text-[8px] fill-gray-500 dark:fill-gray-400');
-
- // Use shorter format for horizontal labels
- const date = new Date(d.date);
- let labelText;
- if (chartTimeRange() <= 7) {
- // For 7 days, show month/day
- labelText = `${date.getMonth() + 1}/${date.getDate()}`;
- } else if (chartTimeRange() <= 30) {
- // For 30 days, show day only (or month/day for first of month)
- labelText = date.getDate() === 1 ? `${date.getMonth() + 1}/1` : date.getDate().toString();
- } else {
- // For longer ranges, show month/day
- labelText = `${date.getMonth() + 1}/${date.getDate()}`;
- }
- text.textContent = labelText;
- g.appendChild(text);
- }
- });
- });
- });
- }}
- />
-
-
-
-
-
- Snapshots
-
-
-
- PVE
-
-
-
- PBS
-
-
-
-
- {/* Filter Controls */}
-
- {/* Filter toggle - visible on all screen sizes */}
-
setShowFilters(!showFilters())}
- class="w-full flex items-center justify-between px-4 py-3 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700/50 rounded-lg transition-colors"
- >
-
-
-
-
-
-
-
-
-
-
-
-
- Filters & Search
-
-
- Active
-
-
-
-
-
-
-
-
-
-
- {/* Search Row */}
-
-
-
setSearchTerm(e.currentTarget.value)}
- class="w-full pl-9 pr-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg
- bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500
- focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all"
- />
-
-
-
-
-
-
-
-
-
-
-
-
- Reset
-
-
-
- {/* Filters Row */}
-
- {/* Time Format Toggle */}
-
- setUseRelativeTime(false)}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- !useRelativeTime()
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Absolute
-
- setUseRelativeTime(true)}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- useRelativeTime()
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Relative
-
-
-
-
-
- {/* Backup Type Filter */}
-
- setBackupTypeFilter('all')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- backupTypeFilter() === 'all'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- All Backups
-
- setBackupTypeFilter('snapshot')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- backupTypeFilter() === 'snapshot'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Snapshots
-
- setBackupTypeFilter('local')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- backupTypeFilter() === 'local'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- PVE
-
- setBackupTypeFilter('remote')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- backupTypeFilter() === 'remote'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- PBS
-
-
-
-
-
- {/* Type Filter */}
-
- setTypeFilter('all')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- typeFilter() === 'all'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- All Types
-
- setTypeFilter('VM')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- typeFilter() === 'VM'
- ? 'bg-white dark:bg-gray-800 text-blue-600 dark:text-blue-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- VMs
-
- setTypeFilter('LXC')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- typeFilter() === 'LXC'
- ? 'bg-white dark:bg-gray-800 text-green-600 dark:text-green-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- LXCs
-
-
-
-
-
-
-
- {/* Table */}
-
-
-
-
-
-
Loading backup data...
-
This may take up to 20 seconds on first load
-
-
- }
- >
-
0}
- fallback={
-
-
No backups found
-
No backups, snapshots, or remote backups match your filters
-
- }
- >
- {/* Mobile Card View - Compact */}
-
-
- {(group) => (
-
-
- {group.label} ({group.items.length})
-
-
- {(item) => (
-
- {/* Compact header row */}
-
-
-
- {item.type}
-
- {item.vmid}
- {item.name || 'Unnamed'}
-
-
-
- {item.backupType === 'snapshot' ? 'SNAP' :
- item.backupType === 'local' ? 'PVE' : 'PBS'}
-
-
-
-
- {/* Compact info row */}
-
-
- {item.node}
-
- {formatTime(item.backupTime * 1000)}
-
-
-
- {formatBytes(item.size!)}
-
-
-
- ✓
-
-
-
-
- {item.storage || (item.datastore && (
- item.namespace && item.namespace !== 'root'
- ? `${item.datastore}/${item.namespace}`
- : item.datastore
- )) || '-'}
-
-
-
-
- )}
-
-
- )}
-
-
-
- {/* Desktop Table View */}
-
-
-
-
- Name
-
- handleSort('type')}
- style="width: 60px;"
- >
- Type {sortKey() === 'type' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('vmid')}
- style="width: 60px;"
- >
- VMID {sortKey() === 'vmid' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('node')}
- style="width: 100px;"
- >
- Node {sortKey() === 'node' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('backupTime')}
- style="width: 140px;"
- >
- Time {sortKey() === 'backupTime' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
-
- handleSort('size')}
- style="width: 80px;"
- >
- Size {sortKey() === 'size' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
-
- handleSort('backupType')}
- style="width: 80px;"
- >
- Backup {sortKey() === 'backupType' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
-
-
- Verified
-
-
-
-
- Location
-
-
-
- Details
-
-
-
-
-
- {(group) => (
- <>
-
-
- {group.label} ({group.items.length})
-
- {
- let cols = 6; // Base columns: Type, VMID, Node, Time, Backup, Details
- if (backupTypeFilter() !== 'snapshot') cols++; // Add Size column
- if (backupTypeFilter() === 'all' || backupTypeFilter() === 'remote') cols++; // Add Verified column
- if (backupTypeFilter() !== 'snapshot') cols++; // Add Location column
- return cols;
- })()} class="px-2 py-1 text-xs font-medium text-gray-500 dark:text-gray-400">
-
-
- {(item) => (
-
-
- {item.name || '-'}
-
-
-
- {item.type}
-
-
- {item.vmid}
-
- {item.node}
-
-
- {formatTime(item.backupTime * 1000)}
-
-
-
- {item.size ? formatBytes(item.size) : '-'}
-
-
-
-
- {item.backupType === 'snapshot' ? 'Snapshot' : item.backupType === 'local' ? 'PVE' : 'PBS'}
-
-
-
-
- {item.backupType === 'remote' ? (
- item.verified ? (
- ✓
- ) : (
- ⏱
- )
- ) : (
- -
- )}
-
-
-
-
- {item.storage || (item.datastore && (
- item.namespace && item.namespace !== 'root'
- ? `${item.datastore}/${item.namespace}`
- : item.datastore
- )) || '-'}
-
-
- {
- const details = [];
-
- if (item.backupType === 'snapshot') {
- details.push(item.backupName);
- if (item.description) {
- details.push(item.description);
- }
- } else if (item.backupType === 'local') {
- details.push(item.backupName);
- } else if (item.backupType === 'remote') {
- if (item.protected) details.push('Protected');
- // For PBS backups, show the notes field which contains the backup description
- const pbsDescription = item.description || (item.name && item.name !== '-' ? item.name : '');
- if (pbsDescription && pbsDescription.trim()) {
- details.push(pbsDescription);
- }
- }
-
- const fullText = details.join(' • ') || '-';
- if (fullText.length > 35) {
- const rect = e.currentTarget.getBoundingClientRect();
- setTooltip({
- text: fullText,
- x: rect.left,
- y: rect.top - 5
- });
- }
- }}
- onMouseLeave={() => {
- setTooltip(null);
- }}
- >
- {(() => {
- const details = [];
-
- if (item.backupType === 'snapshot') {
- details.push(item.backupName);
- if (item.description) {
- details.push(item.description);
- }
- } else if (item.backupType === 'local') {
- details.push(truncateMiddle(item.backupName, 30));
- } else if (item.backupType === 'remote') {
- if (item.protected) details.push('Protected');
- // For PBS backups, show the notes field which contains the backup description
- const pbsDescription = item.description || (item.name && item.name !== '-' ? item.name : '');
- if (pbsDescription && pbsDescription.trim()) {
- details.push(pbsDescription);
- }
- }
-
- const fullText = details.join(' • ') || '-';
- const displayText = fullText.length > 35 ? fullText.substring(0, 32) + '...' : fullText;
-
- return displayText;
- })()}
-
-
- )}
-
- >
- )}
-
-
-
-
-
-
-
- {/* Tooltip */}
-
-
- {tooltip()!.text}
-
-
-
- );
-};
-
-export default UnifiedBackups;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Dashboard/Dashboard.tsx b/pulse-test-staging/frontend-modern/src/components/Dashboard/Dashboard.tsx
deleted file mode 100644
index 9fa4436fa..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Dashboard/Dashboard.tsx
+++ /dev/null
@@ -1,719 +0,0 @@
-import { createSignal, createMemo, createEffect, For, Show } from 'solid-js';
-import type { VM, Container, Node } from '@/types/api';
-import { GuestRow } from './GuestRow';
-import NodeCard from './NodeCard';
-import { useWebSocket } from '@/App';
-import { getAlertStyles } from '@/utils/alerts';
-import { createTooltipSystem, showTooltip, hideTooltip } from '@/components/shared/Tooltip';
-import { ComponentErrorBoundary } from '@/components/ErrorBoundary';
-import { ScrollableTable } from '@/components/shared/ScrollableTable';
-import { parseFilterStack, evaluateFilterStack } from '@/utils/searchQuery';
-
-interface DashboardProps {
- vms: VM[];
- containers: Container[];
- nodes: Node[];
-}
-
-type ViewMode = 'all' | 'vm' | 'lxc';
-type StatusMode = 'all' | 'running' | 'stopped';
-
-
-export function Dashboard(props: DashboardProps) {
- const { connected, activeAlerts, initialDataReceived } = useWebSocket();
- const [search, setSearch] = createSignal('');
-
- // Initialize from localStorage with proper type checking
- const storedViewMode = localStorage.getItem('dashboardViewMode');
- const [viewMode, setViewMode] = createSignal(
- (storedViewMode === 'all' || storedViewMode === 'vm' || storedViewMode === 'lxc') ? storedViewMode : 'all'
- );
-
- const storedStatusMode = localStorage.getItem('dashboardStatusMode');
- const [statusMode, setStatusMode] = createSignal(
- (storedStatusMode === 'all' || storedStatusMode === 'running' || storedStatusMode === 'stopped') ? storedStatusMode : 'all'
- );
-
- const [showFilters, setShowFilters] = createSignal(
- localStorage.getItem('dashboardShowFilters') !== null
- ? localStorage.getItem('dashboardShowFilters') === 'true'
- : false // Default to collapsed
- );
-
- // Sorting state - default to VMID ascending (matches Proxmox order)
- const [sortKey, setSortKey] = createSignal('vmid');
- const [sortDirection, setSortDirection] = createSignal<'asc' | 'desc'>('asc');
-
- // Create tooltip system
- const TooltipComponent = createTooltipSystem();
-
- // Persist filter states to localStorage
- createEffect(() => {
- localStorage.setItem('dashboardViewMode', viewMode());
- });
-
- createEffect(() => {
- localStorage.setItem('dashboardStatusMode', statusMode());
- });
-
-
-
- createEffect(() => {
- localStorage.setItem('dashboardShowFilters', showFilters().toString());
- });
-
-
- // Sort handler
- const handleSort = (key: keyof (VM | Container)) => {
- if (sortKey() === key) {
- // Toggle direction for the same column
- setSortDirection(sortDirection() === 'asc' ? 'desc' : 'asc');
- } else {
- // New column - set key and default direction
- setSortKey(key);
- // Set default sort direction based on column type
- if (key === 'cpu' || key === 'memory' || key === 'disk' || key === 'diskRead' ||
- key === 'diskWrite' || key === 'networkIn' || key === 'networkOut' || key === 'uptime') {
- setSortDirection('desc');
- } else {
- setSortDirection('asc');
- }
- }
- };
-
- // Handle keyboard shortcuts
- let searchInputRef: HTMLInputElement | undefined;
-
-
- createEffect(() => {
- const handleKeyDown = (e: KeyboardEvent) => {
- // Ignore if user is typing in an input, textarea, or contenteditable
- const target = e.target as HTMLElement;
- const isInputField = target.tagName === 'INPUT' ||
- target.tagName === 'TEXTAREA' ||
- target.tagName === 'SELECT' ||
- target.contentEditable === 'true';
-
- // Escape key behavior
- if (e.key === 'Escape') {
- // First check if we have search/filters to clear
- if (search().trim() || sortKey() !== 'vmid' || sortDirection() !== 'asc') {
- // Clear search and reset filters
- setSearch('');
- setSortKey('vmid');
- setSortDirection('asc');
-
- // Blur the search input if it's focused
- if (searchInputRef && document.activeElement === searchInputRef) {
- searchInputRef.blur();
- }
- } else if (showFilters()) {
- // No search/filters active, so collapse the filters section
- setShowFilters(false);
- }
- // If filters are already collapsed, do nothing
- } else if (!isInputField && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
- // If it's a printable character and user is not in an input field
- // Expand filters section if collapsed
- if (!showFilters()) {
- setShowFilters(true);
- }
- // Focus the search input and let the character be typed
- if (searchInputRef) {
- searchInputRef.focus();
- // Don't prevent default - let the character be typed
- }
- }
- };
-
- document.addEventListener('keydown', handleKeyDown);
- return () => document.removeEventListener('keydown', handleKeyDown);
- });
-
-
- // Combine VMs and containers into a single list
- const allGuests = createMemo(() => {
- const vms = props.vms || [];
- const containers = props.containers || [];
- const guests: (VM | Container)[] = [...vms, ...containers];
- return guests;
- });
-
-
- // Filter guests based on current settings
- const filteredGuests = createMemo(() => {
- let guests = allGuests();
-
- // Filter by type
- if (viewMode() === 'vm') {
- guests = guests.filter(g => g.type === 'qemu');
- } else if (viewMode() === 'lxc') {
- guests = guests.filter(g => g.type === 'lxc');
- }
-
- // Filter by status
- if (statusMode() === 'running') {
- guests = guests.filter(g => g.status === 'running');
- } else if (statusMode() === 'stopped') {
- guests = guests.filter(g => g.status !== 'running');
- }
-
- // Apply search/filter
- const searchTerm = search().trim();
- if (searchTerm) {
- // Split by commas first
- const searchParts = searchTerm.split(',').map(t => t.trim()).filter(t => t);
-
- // Separate filters from text searches
- const filters: string[] = [];
- const textSearches: string[] = [];
-
- searchParts.forEach(part => {
- if (part.includes('>') || part.includes('<') || part.includes(':')) {
- filters.push(part);
- } else {
- textSearches.push(part.toLowerCase());
- }
- });
-
- // Apply filters if any
- if (filters.length > 0) {
- // Join filters with AND operator
- const filterString = filters.join(' AND ');
- const stack = parseFilterStack(filterString);
- if (stack.filters.length > 0) {
- guests = guests.filter(g => evaluateFilterStack(g, stack));
- }
- }
-
- // Apply text search if any
- if (textSearches.length > 0) {
- guests = guests.filter(g =>
- textSearches.some(term =>
- g.name.toLowerCase().includes(term) ||
- g.vmid.toString().includes(term) ||
- g.node.toLowerCase().includes(term) ||
- g.status.toLowerCase().includes(term)
- )
- );
- }
- }
-
-
- // Don't filter by thresholds anymore - dimming is handled in GuestRow component
-
- return guests;
- });
-
- // Group by node
- const groupedGuests = createMemo(() => {
- const guests = filteredGuests();
-
- const groups: Record = {};
- guests.forEach(guest => {
- if (!groups[guest.node]) {
- groups[guest.node] = [];
- }
- groups[guest.node].push(guest);
- });
-
- // Sort within each node group
- const key = sortKey();
- const dir = sortDirection();
- if (key) {
- Object.keys(groups).forEach(node => {
- groups[node] = groups[node].sort((a, b) => {
- let aVal: string | number | boolean | null | undefined = a[key] as string | number | boolean | null | undefined;
- let bVal: string | number | boolean | null | undefined = b[key] as string | number | boolean | null | undefined;
-
- // Special handling for percentage-based columns
- if (key === 'cpu') {
- // CPU is displayed as percentage
- aVal = a.cpu * 100;
- bVal = b.cpu * 100;
- } else if (key === 'memory') {
- // Memory is displayed as percentage (use pre-calculated usage)
- aVal = a.memory ? (a.memory.usage || 0) : 0;
- bVal = b.memory ? (b.memory.usage || 0) : 0;
- } else if (key === 'disk') {
- // Disk is displayed as percentage
- aVal = a.disk.total > 0 ? (a.disk.used / a.disk.total) * 100 : 0;
- bVal = b.disk.total > 0 ? (b.disk.used / b.disk.total) * 100 : 0;
- }
-
- // Handle null/undefined/empty values - put at end for both asc and desc
- const aIsEmpty = aVal === null || aVal === undefined || aVal === '';
- const bIsEmpty = bVal === null || bVal === undefined || bVal === '';
-
- if (aIsEmpty && bIsEmpty) return 0;
- if (aIsEmpty) return 1;
- if (bIsEmpty) return -1;
-
- // Type-specific value preparation
- if (typeof aVal === 'number' && typeof bVal === 'number') {
- // Numeric comparison
- const comparison = aVal < bVal ? -1 : 1;
- return dir === 'asc' ? comparison : -comparison;
- } else {
- // String comparison (case-insensitive)
- const aStr = String(aVal).toLowerCase();
- const bStr = String(bVal).toLowerCase();
-
- if (aStr === bStr) return 0;
- const comparison = aStr < bStr ? -1 : 1;
- return dir === 'asc' ? comparison : -comparison;
- }
- });
- });
- }
-
- return groups;
- });
-
- const totalStats = createMemo(() => {
- const guests = filteredGuests();
- const running = guests.filter(g => g.status === 'running').length;
- const vms = guests.filter(g => g.type === 'qemu').length;
- const containers = guests.filter(g => g.type === 'lxc').length;
- return {
- total: guests.length,
- running,
- stopped: guests.length - running,
- vms,
- containers
- };
- });
-
-
- return (
-
- {/* Node Summary Cards */}
-
-
0} fallback={
- Loading node summary...
- }>
-
-
- {(node) => (
-
-
-
-
-
- )}
-
-
-
-
-
- {/* Dashboard Filter */}
-
- {/* Filter toggle - now visible on all screen sizes */}
-
setShowFilters(!showFilters())}
- class="w-full flex items-center justify-between px-4 py-3 text-sm font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700/50 rounded-lg transition-colors"
- >
-
-
-
-
-
-
-
-
-
-
-
-
- Filters & Search
-
-
- Active
-
-
-
-
-
-
-
-
-
-
- {/* Search Bar Row */}
-
-
-
setSearch(e.currentTarget.value)}
- class="w-full pl-9 pr-9 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg
- bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500
- focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all"
- title="Search guests or use filters like cpu>80"
- />
-
-
-
-
{
- const rect = e.currentTarget.getBoundingClientRect();
- const tooltipContent = `
-
-
Search Examples:
-
-
jellyfin - Find guests with "jellyfin" in name
-
plex,media - Find guests with "plex" OR "media"
-
cpu>80 - Guests using >80% CPU
-
memory<20 - Guests using <20% memory
-
disk>90 - Guests using >90% disk
-
node:pve1 - Guests on specific node
-
vmid:104 - Find specific VM/container
-
-
-
Combine searches:
-
media,cpu>50 - "media" in name AND >50% CPU
-
plex,jellyfin,disk>80 - Multiple names AND disk filter
-
-
- `;
- showTooltip(tooltipContent, rect.left, rect.top);
- }}
- onMouseLeave={() => hideTooltip()}
- onClick={(e) => e.preventDefault()}
- type="button"
- aria-label="Search help"
- >
-
-
-
-
-
-
- {/* Reset Button */}
-
{
- setSearch('');
- setSortKey('vmid');
- setSortDirection('asc');
- setViewMode('all');
- setStatusMode('all');
- }}
- title="Reset all filters (Esc)"
- class="flex items-center justify-center px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-400
- bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600
- rounded-lg transition-colors"
- >
-
-
-
-
-
-
- Reset
-
-
-
-
- {/* Filters Row */}
-
-
- {/* Type Filter */}
-
- setViewMode('all')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- viewMode() === 'all'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- All
-
- setViewMode('vm')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- viewMode() === 'vm'
- ? 'bg-white dark:bg-gray-800 text-blue-600 dark:text-blue-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- VMs
-
- setViewMode('lxc')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- viewMode() === 'lxc'
- ? 'bg-white dark:bg-gray-800 text-green-600 dark:text-green-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- LXCs
-
-
-
-
-
- {/* Status Filter */}
-
- setStatusMode('all')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- statusMode() === 'all'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- All
-
- setStatusMode('running')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- statusMode() === 'running'
- ? 'bg-white dark:bg-gray-800 text-green-600 dark:text-green-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Running
-
- setStatusMode('stopped')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- statusMode() === 'stopped'
- ? 'bg-white dark:bg-gray-800 text-red-600 dark:text-red-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Stopped
-
-
-
-
-
-
-
-
-
- {/* Loading State */}
-
-
-
-
-
-
-
-
Loading dashboard data...
-
Connecting to monitoring service
-
-
-
-
- {/* Empty State - No PVE Nodes Configured */}
-
n.type === 'pve').length === 0 && props.vms.length === 0 && props.containers.length === 0}>
-
-
-
-
-
-
No Proxmox VE nodes configured
-
Add a Proxmox VE node in the Settings tab to start monitoring your infrastructure.
-
{
- const settingsTab = document.querySelector('[role="tab"]:last-child') as HTMLElement;
- settingsTab?.click();
- }}
- class="inline-flex items-center px-3 py-1.5 border border-transparent text-xs font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
- >
- Go to Settings
-
-
-
-
-
- {/* Disconnected State */}
-
-
-
-
-
-
-
Connection Lost
-
Unable to connect to the backend server. Attempting to reconnect...
-
-
-
-
- {/* Table View */}
-
0 || props.vms.length > 0 || props.containers.length > 0)}>
-
-
-
-
-
- handleSort('name')}
- onKeyDown={(e) => e.key === 'Enter' && handleSort('name')}
- tabindex="0"
- role="button"
- aria-label={`Sort by name ${sortKey() === 'name' ? (sortDirection() === 'asc' ? 'ascending' : 'descending') : ''}`}
- >
- Name {sortKey() === 'name' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('type')}
- >
- Type {sortKey() === 'type' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('vmid')}
- >
- VMID {sortKey() === 'vmid' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('uptime')}
- >
- Uptime {sortKey() === 'uptime' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('cpu')}
- >
- CPU {sortKey() === 'cpu' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('memory')}
- >
- Memory {sortKey() === 'memory' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('disk')}
- >
- Disk {sortKey() === 'disk' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('diskRead')}
- >
- Disk Read {sortKey() === 'diskRead' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('diskWrite')}
- >
- Disk Write {sortKey() === 'diskWrite' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('networkIn')}
- >
- Net In {sortKey() === 'networkIn' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
- handleSort('networkOut')}
- >
- Net Out {sortKey() === 'networkOut' && (sortDirection() === 'asc' ? '▲' : '▼')}
-
-
-
-
- a.localeCompare(b))} fallback={<>>}>
- {([node, guests]) => (
- <>
-
-
-
- >}>
- {(guest) => (
-
-
-
- )}
-
- >
- )}
-
-
-
-
-
-
-
-
n.type === 'pve').length > 0}>
-
-
-
-
-
No guests found matching your filters
-
-
-
- {/* Stats */}
-
-
-
-
-
- {totalStats().running} running
-
- |
-
-
- {totalStats().stopped} stopped
-
-
-
-
-
-
- {/* Tooltip System */}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Dashboard/GuestRow.tsx b/pulse-test-staging/frontend-modern/src/components/Dashboard/GuestRow.tsx
deleted file mode 100644
index 205148286..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Dashboard/GuestRow.tsx
+++ /dev/null
@@ -1,174 +0,0 @@
-import { Show, createMemo } from 'solid-js';
-import type { VM, Container } from '@/types/api';
-import { AlertIndicator, AlertCountBadge } from '@/components/shared/AlertIndicators';
-import { formatBytes, formatUptime } from '@/utils/format';
-import { MetricBar } from './MetricBar';
-import { IOMetric } from './IOMetric';
-import { getResourceAlerts } from '@/utils/alerts';
-import { useWebSocket } from '@/App';
-
-type Guest = VM | Container;
-
-// Type guard for VM vs Container
-const isVM = (guest: Guest): guest is VM => {
- return guest.type === 'qemu';
-};
-
-
-interface GuestRowProps {
- guest: Guest;
- showNode?: boolean;
- alertStyles?: {
- rowClass: string;
- indicatorClass: string;
- badgeClass: string;
- hasAlert: boolean;
- alertCount: number;
- severity: 'critical' | 'warning' | null;
- };
-}
-
-export function GuestRow(props: GuestRowProps) {
- const { activeAlerts } = useWebSocket();
-
- const cpuPercent = createMemo(() => (props.guest.cpu || 0) * 100);
- const memPercent = createMemo(() => {
- if (!props.guest.memory) return 0;
- // Use the pre-calculated usage percentage from the backend
- return props.guest.memory.usage || 0;
- });
- const diskPercent = createMemo(() => {
- if (!props.guest.disk || props.guest.disk.total === 0) return 0;
- return (props.guest.disk.used / props.guest.disk.total) * 100;
- });
-
- const isRunning = createMemo(() => props.guest.status === 'running');
-
- // Get alerts for this guest
- const guestAlerts = createMemo(() => {
- const guestId = props.guest.id || `${props.guest.instance}-${props.guest.name}-${props.guest.vmid}`;
- return getResourceAlerts(guestId, activeAlerts);
- });
-
-
- // Get row styling - include alert styles if present
- const rowClass = createMemo(() => {
- const base = 'transition-all duration-200';
- const hover = 'hover:shadow-sm';
- const alertClass = props.alertStyles?.rowClass || '';
- const defaultHover = alertClass ? '' : 'hover:bg-gray-50 dark:hover:bg-gray-700';
- return `${base} ${hover} ${defaultHover} ${alertClass}`;
- });
-
- return (
-
- {/* Name - Sticky column */}
-
-
- {/* Status indicator */}
-
-
- {/* Name */}
-
- {props.guest.name}
-
-
- {/* Alert indicators */}
-
-
-
-
-
-
- {/* Type */}
-
-
- {isVM(props.guest) ? 'VM' : 'LXC'}
-
-
-
- {/* VMID */}
-
- {props.guest.vmid}
-
-
-
- {/* Node (optional) */}
-
-
- {props.guest.node}
-
-
-
- {/* Uptime */}
-
-
- {formatUptime(props.guest.uptime)}
-
-
-
- {/* CPU */}
-
-
-
-
- {/* Memory */}
-
-
-
-
- {/* Disk */}
-
- 0}
- fallback={- }
- >
-
-
-
-
- {/* Disk I/O */}
-
-
-
-
-
-
-
- {/* Network I/O */}
-
-
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Dashboard/IOMetric.tsx b/pulse-test-staging/frontend-modern/src/components/Dashboard/IOMetric.tsx
deleted file mode 100644
index 7feae5001..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Dashboard/IOMetric.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { createMemo, Show } from 'solid-js';
-import { formatSpeed } from '@/utils/format';
-
-interface IOMetricProps {
- value: number;
- disabled?: boolean;
-}
-
-export function IOMetric(props: IOMetricProps) {
- const formatted = createMemo(() => formatSpeed(props.value, 0));
-
- // Color based on speed (MB/s) - matching current dashboard
- const colorClass = createMemo(() => {
- if (props.disabled) return 'text-gray-400 dark:text-gray-500';
-
- const mbps = props.value / (1024 * 1024);
- if (mbps < 1) return 'text-gray-300 dark:text-gray-400';
- if (mbps < 10) return 'text-green-600 dark:text-green-400';
- if (mbps < 50) return 'text-yellow-600 dark:text-yellow-400';
- return 'text-red-600 dark:text-red-400';
- });
-
- return (
- -}>
-
- {formatted()}
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Dashboard/MetricBar.tsx b/pulse-test-staging/frontend-modern/src/components/Dashboard/MetricBar.tsx
deleted file mode 100644
index 6d76f487a..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Dashboard/MetricBar.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { createMemo } from 'solid-js';
-
-interface MetricBarProps {
- value: number;
- label: string;
- sublabel?: string;
- type?: 'cpu' | 'memory' | 'disk' | 'generic';
-}
-
-export function MetricBar(props: MetricBarProps) {
- const width = createMemo(() => Math.min(props.value, 100));
-
- // Get color based on percentage and metric type (matching original)
- const getColor = createMemo(() => {
- const percentage = props.value;
- const metric = props.type || 'generic';
-
- if (metric === 'cpu') {
- if (percentage >= 90) return 'red';
- if (percentage >= 80) return 'yellow';
- return 'green';
- } else if (metric === 'memory') {
- if (percentage >= 85) return 'red';
- if (percentage >= 75) return 'yellow';
- return 'green';
- } else if (metric === 'disk') {
- if (percentage >= 90) return 'red';
- if (percentage >= 80) return 'yellow';
- return 'green';
- } else {
- if (percentage >= 90) return 'red';
- if (percentage >= 75) return 'yellow';
- return 'green';
- }
- });
-
- // Map color to CSS classes
- const progressColorClass = createMemo(() => {
- const colorMap = {
- 'red': 'bg-red-500/60 dark:bg-red-500/50',
- 'yellow': 'bg-yellow-500/60 dark:bg-yellow-500/50',
- 'green': 'bg-green-500/60 dark:bg-green-500/50'
- };
- return colorMap[getColor()] || 'bg-gray-500/60 dark:bg-gray-500/50';
- });
-
- // Combine label and sublabel for display text
- const displayText = createMemo(() => {
- if (props.sublabel) {
- return `${props.label} (${props.sublabel})`;
- }
- return props.label;
- });
-
- return (
-
-
-
-
- {displayText()}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Dashboard/NodeCard.tsx b/pulse-test-staging/frontend-modern/src/components/Dashboard/NodeCard.tsx
deleted file mode 100644
index 3c5fb3a2b..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Dashboard/NodeCard.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import { Component, Show, createMemo } from 'solid-js';
-import type { Node } from '@/types/api';
-import { formatUptime, formatBytes } from '@/utils/format';
-import { getAlertStyles, getResourceAlerts } from '@/utils/alerts';
-import { AlertIndicator, AlertCountBadge } from '@/components/shared/AlertIndicators';
-import { useWebSocket } from '@/App';
-
-interface NodeCardProps {
- node: Node;
-}
-
-const NodeCard: Component = (props) => {
- const { activeAlerts } = useWebSocket();
- // Early return if node data is incomplete
- if (!props.node || !props.node.memory || !props.node.disk) {
- return (
-
- );
- }
-
- const isOnline = () => props.node.status === 'online' && props.node.uptime > 0 && props.node.connectionHealth !== 'error';
- const cpuPercent = () => Math.round(props.node.cpu * 100);
- const memPercent = () => {
- if (!props.node.memory) return 0;
- // Use the pre-calculated usage percentage from the backend
- return Math.round(props.node.memory.usage || 0);
- };
- const diskPercent = () => {
- if (!props.node.disk || props.node.disk.total === 0) return 0;
- return Math.round((props.node.disk.used / props.node.disk.total) * 100);
- };
-
- // Calculate normalized load (load average / cpu count)
- const normalizedLoad = () => {
- if (props.node.loadAverage && props.node.loadAverage.length > 0) {
- const load1m = props.node.loadAverage[0];
- if (typeof load1m === 'number' && !isNaN(load1m)) {
- // Use CPU cores from cpuInfo if available, otherwise assume 4
- const cpuCount = props.node.cpuInfo?.cores || 4;
- return (load1m / cpuCount).toFixed(2);
- }
- }
- return 'N/A';
- };
-
- // Helper function to create progress bar with text overlay (matching original)
- const createProgressBar = (percentage: number, text: string, colorClass: string) => {
- const bgColorClass = 'bg-gray-200 dark:bg-gray-600';
- const progressColorClass = {
- 'red': 'bg-red-500/60 dark:bg-red-500/50',
- 'yellow': 'bg-yellow-500/60 dark:bg-yellow-500/50',
- 'green': 'bg-green-500/60 dark:bg-green-500/50'
- }[colorClass] || 'bg-gray-500/60 dark:bg-gray-500/50';
-
- return (
-
- );
- };
-
- // Get color based on percentage and metric type
- const getColor = (percentage: number, metric: 'cpu' | 'memory' | 'disk') => {
- if (metric === 'cpu') {
- if (percentage >= 90) return 'red';
- if (percentage >= 80) return 'yellow';
- return 'green';
- } else if (metric === 'memory') {
- if (percentage >= 85) return 'red';
- if (percentage >= 75) return 'yellow';
- return 'green';
- } else if (metric === 'disk') {
- if (percentage >= 90) return 'red';
- if (percentage >= 80) return 'yellow';
- return 'green';
- }
- return 'green';
- };
-
- // Format CPU text with cores info
- const cpuText = () => {
- const cores = props.node.cpuInfo?.cores;
- const cpuUsed = cores ? (props.node.cpu * cores).toFixed(1) : '0';
- return cores && cores > 0
- ? `${cpuPercent()}% (${cpuUsed}/${cores} cores)`
- : `${cpuPercent()}%`;
- };
-
- // Format memory text with size info
- const memoryText = () => {
- if (!props.node.memory) return '0%';
- return `${memPercent()}% (${formatBytes(props.node.memory.used)}/${formatBytes(props.node.memory.total)})`;
- };
-
- // Format disk text with size info
- const diskText = () => {
- if (!props.node.disk) return '0%';
- return `${diskPercent()}% (${formatBytes(props.node.disk.used)}/${formatBytes(props.node.disk.total)})`;
- };
-
- const alertStyles = getAlertStyles(props.node.id || props.node.name, activeAlerts);
- const nodeAlerts = createMemo(() => getResourceAlerts(props.node.id || props.node.name, activeAlerts));
- const borderClass = alertStyles.hasAlert
- ? (alertStyles.severity === 'critical' ? 'border-red-500 border-2' : 'border-orange-500 border-2')
- : 'border-gray-200 dark:border-gray-700';
-
- return (
-
- {/* Header */}
-
-
- {props.node.name}
-
-
-
-
-
-
-
- {isOnline() ? 'online' : props.node.status || 'unknown'}
-
-
-
-
- {/* CPU */}
-
- CPU:
- {createProgressBar(cpuPercent(), cpuText(), getColor(cpuPercent(), 'cpu'))}
-
-
- {/* Memory */}
-
- Mem:
- {createProgressBar(memPercent(), memoryText(), getColor(memPercent(), 'memory'))}
-
-
- {/* Disk */}
-
- Disk:
- {createProgressBar(diskPercent(), diskText(), getColor(diskPercent(), 'disk'))}
-
-
- {/* Footer Info */}
-
- Uptime: {formatUptime(props.node.uptime)}
- Load: {normalizedLoad()}
-
-
- );
-};
-
-export default NodeCard;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Dashboard/ThresholdSlider.tsx b/pulse-test-staging/frontend-modern/src/components/Dashboard/ThresholdSlider.tsx
deleted file mode 100644
index 3484f97e3..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Dashboard/ThresholdSlider.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import { createSignal, createEffect, onMount } from 'solid-js';
-
-interface ThresholdSliderProps {
- value: number;
- onChange: (value: number) => void;
- type: 'cpu' | 'memory' | 'disk';
- min?: number;
- max?: number;
-}
-
-export function ThresholdSlider(props: ThresholdSliderProps) {
- let sliderRef: HTMLInputElement | undefined;
- let thumbRef: HTMLDivElement | undefined;
- const [thumbPosition, setThumbPosition] = createSignal(0);
- const [isDragging, setIsDragging] = createSignal(false);
-
- // Color mapping
- const colorMap = {
- cpu: 'text-blue-500',
- memory: 'text-green-500',
- disk: 'text-amber-500'
- };
-
- // Calculate visual position (8-92% range) while keeping actual value (0-100%)
- const calculateVisualPosition = (value: number) => {
- const min = props.min || 0;
- const max = props.max || 100;
- const percent = ((value - min) / (max - min)) * 100;
- // Map 0-100% to 8-92% to prevent edge clipping
- return 8 + (percent * 0.84);
- };
-
- // Update thumb position when value changes
- createEffect(() => {
- if (sliderRef) {
- setThumbPosition(calculateVisualPosition(props.value));
- }
- });
-
- onMount(() => {
- // Initialize thumb position
- setThumbPosition(calculateVisualPosition(props.value));
- });
-
- // Prevent scrolling while dragging
- const handleMouseDown = () => {
- setIsDragging(true);
-
- // Store the current scroll position
- const scrollY = window.scrollY;
- const scrollX = window.scrollX;
-
- const handleScroll = () => {
- window.scrollTo(scrollX, scrollY);
- };
-
- const handleMouseUp = () => {
- setIsDragging(false);
- window.removeEventListener('scroll', handleScroll, { capture: true });
- document.removeEventListener('mouseup', handleMouseUp);
- };
-
- // Lock scroll position while dragging
- window.addEventListener('scroll', handleScroll, { capture: true });
- document.addEventListener('mouseup', handleMouseUp);
- };
-
- return (
- isDragging() && e.preventDefault()}
- style={{ "touch-action": isDragging() ? "none" : "auto" }}
- >
- {/* Track background */}
-
-
- {/* Colored fill */}
-
-
- {/* Native range input (invisible but functional) */}
-
props.onChange(parseInt(e.currentTarget.value))}
- onMouseDown={handleMouseDown}
- onWheel={(e) => e.preventDefault()}
- class="absolute inset-0 w-full h-3.5 opacity-0 cursor-pointer z-20"
- style={{ "touch-action": "none" }}
- title={`${props.type.toUpperCase()}: ${props.value}%`}
- />
-
- {/* Custom thumb with value */}
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/ErrorBoundary.tsx b/pulse-test-staging/frontend-modern/src/components/ErrorBoundary.tsx
deleted file mode 100644
index de0689670..000000000
--- a/pulse-test-staging/frontend-modern/src/components/ErrorBoundary.tsx
+++ /dev/null
@@ -1,132 +0,0 @@
-import { Component, JSX, createSignal, ErrorBoundary as SolidErrorBoundary } from 'solid-js';
-import { logError } from '@/utils/logger';
-
-interface ErrorBoundaryProps {
- children: JSX.Element;
- fallback?: (error: Error, reset: () => void) => JSX.Element;
- onError?: (error: Error) => void;
-}
-
-const DefaultErrorFallback: Component<{ error: Error; reset: () => void }> = (props) => {
- const [details, setDetails] = createSignal(false);
-
- return (
-
-
-
-
-
-
-
-
- Something went wrong
-
-
- An unexpected error occurred
-
-
-
-
-
-
- {props.error.message}
-
-
-
-
-
- Try Again
-
- window.location.reload()}
- class="flex-1 px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
- >
- Reload Page
-
-
-
-
setDetails(!details())}
- class="mt-4 text-sm text-gray-500 dark:text-gray-400 underline hover:text-gray-700 dark:hover:text-gray-300"
- >
- {details() ? 'Hide' : 'Show'} error details
-
-
- {details() && (
-
-
- {props.error.stack}
-
-
- )}
-
-
- );
-};
-
-export const ErrorBoundary: Component = (props) => {
- return (
- {
- // Log the error
- logError('Error boundary caught error', error);
-
- // Call custom error handler if provided
- if (props.onError) {
- props.onError(error);
- }
-
- // Render custom or default fallback
- if (props.fallback) {
- return props.fallback(error, reset);
- }
-
- return ;
- }}
- >
- {props.children}
-
- );
-};
-
-// Component-specific error boundary with more context
-export const ComponentErrorBoundary: Component<{
- name: string;
- children: JSX.Element;
-}> = (props) => {
- return (
- (
-
-
-
-
-
-
- Error in {props.name}
-
-
-
- {error.message}
-
-
- Retry
-
-
- )}
- onError={(error) => {
- logError(`Error in component ${props.name}`, error);
- }}
- >
- {props.children}
-
- );
-};
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Settings/NodeModal.tsx b/pulse-test-staging/frontend-modern/src/components/Settings/NodeModal.tsx
deleted file mode 100644
index 5de4cac68..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Settings/NodeModal.tsx
+++ /dev/null
@@ -1,675 +0,0 @@
-import { Component, Show, createSignal, createEffect } from 'solid-js';
-import { Portal } from 'solid-js/web';
-import type { NodeConfig } from '@/types/nodes';
-import { copyToClipboard } from '@/utils/clipboard';
-import { showSuccess } from '@/utils/toast';
-import { NodesAPI } from '@/api/nodes';
-
-interface NodeModalProps {
- isOpen: boolean;
- onClose: () => void;
- nodeType: 'pve' | 'pbs';
- editingNode?: NodeConfig;
- onSave: (nodeData: Partial) => void;
-}
-
-export const NodeModal: Component = (props) => {
- const [testResult, setTestResult] = createSignal<{ status: string; message: string; isCluster?: boolean } | null>(null);
- const [isTesting, setIsTesting] = createSignal(false);
-
- const [formData, setFormData] = createSignal({
- name: '',
- host: '',
- authType: 'token' as 'password' | 'token',
- user: '',
- password: '',
- tokenName: '',
- tokenValue: '',
- fingerprint: '',
- verifySSL: true,
- // PVE specific
- monitorVMs: true,
- monitorContainers: true,
- monitorStorage: true,
- monitorBackups: true,
- // PBS specific
- monitorDatastores: true,
- monitorSyncJobs: true,
- monitorVerifyJobs: true,
- monitorPruneJobs: true,
- monitorGarbageJobs: false
- });
-
- // Update form when editing node changes
- createEffect(() => {
- if (props.editingNode) {
- const node = props.editingNode;
- setFormData({
- name: node.name || '',
- host: node.host || '',
- authType: node.user ? 'password' : 'token',
- user: node.user || '',
- password: '', // Don't show existing password
- tokenName: node.tokenName || '',
- tokenValue: '', // Don't show existing token
- fingerprint: ('fingerprint' in node ? node.fingerprint : '') || '',
- verifySSL: node.verifySSL ?? true,
- monitorVMs: (node.type === 'pve' && 'monitorVMs' in node ? node.monitorVMs : true) ?? true,
- monitorContainers: (node.type === 'pve' && 'monitorContainers' in node ? node.monitorContainers : true) ?? true,
- monitorStorage: (node.type === 'pve' && 'monitorStorage' in node ? node.monitorStorage : true) ?? true,
- monitorBackups: (node.type === 'pve' && 'monitorBackups' in node ? node.monitorBackups : true) ?? true,
- monitorDatastores: (node.type === 'pbs' && 'monitorDatastores' in node ? node.monitorDatastores : true) ?? true,
- monitorSyncJobs: (node.type === 'pbs' && 'monitorSyncJobs' in node ? node.monitorSyncJobs : true) ?? true,
- monitorVerifyJobs: (node.type === 'pbs' && 'monitorVerifyJobs' in node ? node.monitorVerifyJobs : true) ?? true,
- monitorPruneJobs: (node.type === 'pbs' && 'monitorPruneJobs' in node ? node.monitorPruneJobs : true) ?? true,
- monitorGarbageJobs: (node.type === 'pbs' && 'monitorGarbageJobs' in node ? node.monitorGarbageJobs : false) ?? false
- });
- } else {
- // Reset form for new node
- setFormData({
- name: '',
- host: '',
- authType: 'password',
- user: '',
- password: '',
- tokenName: '',
- tokenValue: '',
- fingerprint: '',
- verifySSL: true,
- monitorVMs: true,
- monitorContainers: true,
- monitorStorage: true,
- monitorBackups: true,
- monitorDatastores: true,
- monitorSyncJobs: true,
- monitorVerifyJobs: true,
- monitorPruneJobs: true,
- monitorGarbageJobs: false
- });
- }
- });
-
- const handleSubmit = (e: Event) => {
- e.preventDefault();
- const data = formData();
-
- // Prepare data based on auth type
- const nodeData: Partial = {
- type: props.nodeType,
- name: data.name || '', // Will be auto-generated by backend if empty
- host: data.host,
- fingerprint: data.fingerprint,
- verifySSL: data.verifySSL
- };
-
- if (data.authType === 'password') {
- nodeData.user = data.user;
- if (data.password) {
- nodeData.password = data.password;
- }
- } else {
- // For token auth, tokenName contains the full token ID (user@realm!tokenname)
- nodeData.tokenName = data.tokenName;
- if (data.tokenValue) {
- nodeData.tokenValue = data.tokenValue;
- }
- }
-
- // Add monitor settings based on type
- if (props.nodeType === 'pve') {
- Object.assign(nodeData, {
- monitorVMs: data.monitorVMs,
- monitorContainers: data.monitorContainers,
- monitorStorage: data.monitorStorage,
- monitorBackups: data.monitorBackups
- });
- } else {
- Object.assign(nodeData, {
- monitorDatastores: data.monitorDatastores,
- monitorSyncJobs: data.monitorSyncJobs,
- monitorVerifyJobs: data.monitorVerifyJobs,
- monitorPruneJobs: data.monitorPruneJobs,
- monitorGarbageJobs: data.monitorGarbageJobs
- });
- }
-
- props.onSave(nodeData);
- };
-
- const updateField = (field: string, value: string | boolean) => {
- setFormData(prev => ({ ...prev, [field]: value }));
- };
-
- const handleTestConnection = async () => {
- const data = formData();
-
- // Validate required fields
- if (!data.host) {
- setTestResult({ status: 'error', message: 'Host is required' });
- return;
- }
-
- if (data.authType === 'password' && (!data.user || !data.password)) {
- setTestResult({ status: 'error', message: 'Username and password are required' });
- return;
- }
-
- if (data.authType === 'token' && (!data.tokenName || !data.tokenValue)) {
- setTestResult({ status: 'error', message: 'Token ID and token value are required' });
- return;
- }
-
- // Prepare test data
- const testData: Partial = {
- type: props.nodeType,
- name: data.name || '', // Will be auto-generated by backend if empty
- host: data.host,
- fingerprint: data.fingerprint,
- verifySSL: data.verifySSL
- };
-
- if (data.authType === 'password') {
- testData.user = data.user;
- testData.password = data.password;
- } else {
- // For token auth, tokenName contains the full token ID
- testData.tokenName = data.tokenName;
- testData.tokenValue = data.tokenValue;
- }
-
- setIsTesting(true);
- setTestResult(null);
-
- try {
- const result = await NodesAPI.testConnection(testData as NodeConfig);
- setTestResult({
- status: 'success',
- message: result.message || 'Connection successful',
- isCluster: result.isCluster
- });
- } catch (error) {
- setTestResult({
- status: 'error',
- message: error instanceof Error ? error.message : 'Connection failed'
- });
- } finally {
- setIsTesting(false);
- }
- };
-
- return (
-
-
-
-
- {/* Backdrop */}
-
-
- {/* Modal */}
-
-
-
-
-
- );
-};
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Settings/Settings.tsx b/pulse-test-staging/frontend-modern/src/components/Settings/Settings.tsx
deleted file mode 100644
index 7b52edb9f..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Settings/Settings.tsx
+++ /dev/null
@@ -1,1034 +0,0 @@
-import { Component, createSignal, onMount, For, Show, createEffect } from 'solid-js';
-import { useWebSocket } from '@/App';
-import { showSuccess, showError } from '@/utils/toast';
-import { NodeModal } from './NodeModal';
-import { SettingsAPI } from '@/api/settings';
-import { NodesAPI } from '@/api/nodes';
-import { UpdatesAPI } from '@/api/updates';
-import type { NodeConfig } from '@/types/nodes';
-import type { UpdateInfo, UpdateStatus, VersionInfo } from '@/api/updates';
-
-type SettingsTab = 'pve' | 'pbs' | 'system' | 'diagnostics';
-
-// Node with UI-specific fields
-type NodeConfigWithStatus = NodeConfig & {
- hasPassword?: boolean;
- hasToken?: boolean;
- status: 'connected' | 'disconnected' | 'error';
-};
-
-const Settings: Component = () => {
- const { state, connected, updateProgress } = useWebSocket();
- const [activeTab, setActiveTab] = createSignal('pve');
- const [hasUnsavedChanges, setHasUnsavedChanges] = createSignal(false);
- const [nodes, setNodes] = createSignal([]);
- const [showNodeModal, setShowNodeModal] = createSignal(false);
- const [editingNode, setEditingNode] = createSignal(null);
-
- // System settings
- const [pollingInterval, setPollingInterval] = createSignal(5);
- const [backendPort, setBackendPort] = createSignal(3000);
- const [frontendPort, setFrontendPort] = createSignal(7655);
- const [allowedOrigins, setAllowedOrigins] = createSignal('*');
- const [connectionTimeout, setConnectionTimeout] = createSignal(10);
-
- // Update settings
- const [versionInfo, setVersionInfo] = createSignal(null);
- const [updateInfo, setUpdateInfo] = createSignal(null);
- const [updateStatus, setUpdateStatus] = createSignal(null);
- const [checkingForUpdates, setCheckingForUpdates] = createSignal(false);
- const [updateChannel, setUpdateChannel] = createSignal<'stable' | 'rc'>('stable');
- const [autoUpdateEnabled, setAutoUpdateEnabled] = createSignal(false);
- const [autoUpdateCheckInterval, setAutoUpdateCheckInterval] = createSignal(24);
- const [autoUpdateTime, setAutoUpdateTime] = createSignal('03:00');
-
- const tabs: { id: SettingsTab; label: string; icon: string }[] = [
- {
- id: 'pve',
- label: 'PVE Nodes',
- icon: 'M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01'
- },
- {
- id: 'pbs',
- label: 'PBS Nodes',
- icon: 'M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4'
- },
- {
- id: 'system',
- label: 'System',
- icon: 'M12 4v16m4-11h4m-4 6h4M8 9H4m4 6H4'
- },
- {
- id: 'diagnostics',
- label: 'Diagnostics',
- icon: 'M3 3v18h18m-10-8l3-3 3 3 4-4'
- }
- ];
-
- // Update status from WebSocket events
- createEffect(() => {
- const progress = updateProgress();
- if (progress) {
- setUpdateStatus(progress);
- }
- });
-
- // Load nodes and system settings on mount
- onMount(async () => {
- try {
- // Load nodes
- const nodesList = await NodesAPI.getNodes();
- // Add status and other UI fields
- const nodesWithStatus = nodesList.map(node => ({
- ...node,
- // Use the hasPassword/hasToken from the API if available, otherwise check local fields
- hasPassword: node.hasPassword ?? !!node.password,
- hasToken: node.hasToken ?? !!node.tokenValue,
- status: node.status || 'disconnected' as const
- }));
- setNodes(nodesWithStatus);
-
- // Load system settings
- try {
- const systemResponse = await fetch('/api/config/system');
- if (systemResponse.ok) {
- const systemSettings = await systemResponse.json();
- setPollingInterval(systemSettings.pollingInterval || 5);
- setBackendPort(systemSettings.backendPort || 3000);
- setFrontendPort(systemSettings.frontendPort || 7655);
- setAllowedOrigins(systemSettings.allowedOrigins || '*');
- setConnectionTimeout(systemSettings.connectionTimeout || 10);
- } else {
- // Fallback to old endpoint
- const response = await SettingsAPI.getSettings();
- const settings = response.current;
- setPollingInterval((settings.monitoring.pollingInterval || 5000) / 1000);
- }
- } catch (error) {
- console.error('Failed to load settings:', error);
- }
-
- // Load version information
- try {
- const version = await UpdatesAPI.getVersion();
- setVersionInfo(version);
- if (version.channel) {
- setUpdateChannel(version.channel as 'stable' | 'rc');
- }
- } catch (error) {
- console.error('Failed to load version:', error);
- }
- } catch (error) {
- console.error('Failed to load configuration:', error);
- }
- });
-
- const saveSettings = async () => {
- try {
- if (activeTab() === 'system') {
- // Save system settings using typed API
- await SettingsAPI.updateSystemSettings({
- pollingInterval: pollingInterval(),
- backendPort: backendPort(),
- frontendPort: frontendPort(),
- allowedOrigins: allowedOrigins(),
- connectionTimeout: connectionTimeout(),
- updateChannel: updateChannel(),
- autoUpdateEnabled: autoUpdateEnabled(),
- autoUpdateCheckInterval: autoUpdateCheckInterval(),
- autoUpdateTime: autoUpdateTime()
- });
- }
-
- showSuccess('Settings saved successfully. Service restart may be required for port changes.');
- setHasUnsavedChanges(false);
-
- // Reload the page after a short delay to ensure the new settings are applied
- setTimeout(() => {
- window.location.reload();
- }, 3000);
- } catch (error) {
- showError(error instanceof Error ? error.message : 'Failed to save settings');
- }
- };
-
- const deleteNode = async (nodeId: string) => {
- if (!confirm('Are you sure you want to delete this node?')) return;
-
- try {
- await NodesAPI.deleteNode(nodeId);
- setNodes(nodes().filter(n => n.id !== nodeId));
- showSuccess('Node deleted successfully');
- } catch (error) {
- showError(error instanceof Error ? error.message : 'Failed to delete node');
- }
- };
-
- const testNodeConnection = async (nodeId: string) => {
- try {
- const node = nodes().find(n => n.id === nodeId);
- if (!node) {
- throw new Error('Node not found');
- }
-
- // Use the existing node test endpoint which uses stored credentials
- const result = await NodesAPI.testExistingNode(nodeId);
- if (result.status === 'success') {
- showSuccess(result.message || 'Connection successful');
- } else {
- throw new Error(result.message || 'Connection failed');
- }
- } catch (error) {
- showError(error instanceof Error ? error.message : 'Connection test failed');
- }
- };
-
- const checkForUpdates = async () => {
- setCheckingForUpdates(true);
- try {
- const info = await UpdatesAPI.checkForUpdates();
- setUpdateInfo(info);
- if (!info.available) {
- showSuccess('You are running the latest version');
- }
- } catch (error) {
- showError('Failed to check for updates');
- console.error('Update check error:', error);
- } finally {
- setCheckingForUpdates(false);
- }
- };
-
- const applyUpdate = async () => {
- const info = updateInfo();
- if (!info || !info.downloadUrl) {
- showError('No update available');
- return;
- }
-
- try {
- await UpdatesAPI.applyUpdate(info.downloadUrl);
- showSuccess('Update started. Pulse will restart automatically.');
-
- // Start polling for update status
- const pollStatus = setInterval(async () => {
- try {
- const status = await UpdatesAPI.getUpdateStatus();
- setUpdateStatus(status);
-
- if (status.status === 'completed' || status.status === 'error') {
- clearInterval(pollStatus);
- if (status.status === 'error') {
- showError(status.error || 'Update failed');
- }
- }
- } catch (error) {
- // Service might be restarting
- console.log('Status check failed, service may be restarting');
- }
- }, 1000);
- } catch (error) {
- showError('Failed to start update');
- console.error('Update error:', error);
- }
- };
-
- return (
- <>
-
- {/* Header with better styling */}
-
-
-
Configuration Settings
-
- Manage Proxmox nodes and system configuration
-
-
-
-
- {/* Save notification bar - only show when there are unsaved changes */}
-
-
-
-
-
-
-
-
-
- You have unsaved changes
-
-
-
- Save Changes
-
- {
- window.location.reload();
- }}
- >
- Discard
-
-
-
-
-
-
- {/* Tab Navigation - modern style */}
-
-
-
-
- {(tab) => (
- setActiveTab(tab.id)}
- >
- {tab.label}
-
- )}
-
-
-
-
-
- {/* Tab Content */}
-
- {/* PVE Nodes Tab */}
-
-
-
-
Proxmox VE Nodes
- {
- setEditingNode(null);
- setShowNodeModal(true);
- }}
- class="px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2"
- >
-
-
-
-
- Add PVE Node
-
-
-
-
-
n.type === 'pve')}>
- {(node) => (
-
-
-
-
{
- // Find the corresponding node in the WebSocket state
- const stateNode = state.nodes.find(n => n.instance === node.name);
- // Check if the node has an error status or is offline
- if (stateNode?.connectionHealth === 'error' || stateNode?.status === 'offline') {
- return 'bg-red-500';
- }
- // Check if we have a healthy connection
- if (stateNode && stateNode.status === 'online') {
- return 'bg-green-500';
- }
- // Default to gray if no state data
- return 'bg-gray-400';
- })()
- }`}>
-
-
{node.name}
-
{node.host}
-
-
- {node.user ? `User: ${node.user}` : `Token: ${node.tokenName}`}
-
- {node.type === 'pve' && 'monitorVMs' in node && node.monitorVMs && VMs }
- {node.type === 'pve' && 'monitorContainers' in node && node.monitorContainers && Containers }
- {node.type === 'pve' && 'monitorStorage' in node && node.monitorStorage && Storage }
- {node.type === 'pve' && 'monitorBackups' in node && node.monitorBackups && Backups }
-
-
-
-
Cluster: {'clusterName' in node ? node.clusterName : 'Unknown'}
-
-
- {(endpoint) => (
-
- {endpoint.NodeName} ({endpoint.IP})
-
- )}
-
-
-
- Pulse will automatically failover between cluster nodes
-
-
-
-
-
-
-
testNodeConnection(node.id)}
- class="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100"
- title="Test connection"
- >
-
-
-
-
-
{
- setEditingNode(node);
- setShowNodeModal(true);
- }}
- class="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100"
- >
-
-
-
-
-
-
deleteNode(node.id)}
- class="p-2 text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300"
- >
-
-
-
-
-
-
-
-
- )}
-
-
- {nodes().filter(n => n.type === 'pve').length === 0 && (
-
-
No PVE nodes configured
-
Add a node to start monitoring
-
- )}
-
-
-
-
- {/* PBS Nodes Tab */}
-
-
-
-
Proxmox Backup Server Nodes
- {
- setEditingNode(null);
- setShowNodeModal(true);
- }}
- class="px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors flex items-center gap-2"
- >
-
-
-
-
- Add PBS Node
-
-
-
-
-
n.type === 'pbs')}>
- {(node) => (
-
-
-
-
{
- // Find the corresponding PBS instance in the WebSocket state
- const statePBS = state.pbs.find(p => p.name === node.name);
- // Check if the PBS has an error status or is offline
- if (statePBS?.connectionHealth === 'error' || statePBS?.status === 'offline') {
- return 'bg-red-500';
- }
- // Check if we have a healthy connection
- if (statePBS && statePBS.status === 'online') {
- return 'bg-green-500';
- }
- // Default to gray if no state data
- return 'bg-gray-400';
- })()
- }`}>
-
-
{node.name}
-
{node.host}
-
-
- {node.user ? `User: ${node.user}` : `Token: ${node.tokenName}`}
-
- {node.type === 'pbs' && 'monitorDatastores' in node && node.monitorDatastores && Datastores }
- {node.type === 'pbs' && 'monitorSyncJobs' in node && node.monitorSyncJobs && Sync Jobs }
- {node.type === 'pbs' && 'monitorVerifyJobs' in node && node.monitorVerifyJobs && Verify Jobs }
- {node.type === 'pbs' && 'monitorPruneJobs' in node && node.monitorPruneJobs && Prune Jobs }
-
-
-
-
-
testNodeConnection(node.id)}
- class="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100"
- title="Test connection"
- >
-
-
-
-
-
{
- setEditingNode(node);
- setShowNodeModal(true);
- }}
- class="p-2 text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100"
- >
-
-
-
-
-
-
deleteNode(node.id)}
- class="p-2 text-red-600 dark:text-red-400 hover:text-red-700 dark:hover:text-red-300"
- >
-
-
-
-
-
-
-
-
- )}
-
-
- {nodes().filter(n => n.type === 'pbs').length === 0 && (
-
-
No PBS nodes configured
-
Add a node to start monitoring
-
- )}
-
-
-
-
- {/* System Settings Tab */}
-
-
-
-
System Configuration
-
-
- {/* Performance Settings */}
-
-
-
-
-
- Performance Settings
-
-
-
-
-
-
Polling Interval
-
- How often to fetch data from servers
-
-
-
{
- setPollingInterval(parseInt(e.currentTarget.value));
- setHasUnsavedChanges(true);
- }}
- class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- >
- 3 seconds
- 5 seconds
- 10 seconds
- 30 seconds
- 1 minute
-
-
-
-
-
-
Connection Timeout
-
- Max wait time for node responses
-
-
-
{
- setConnectionTimeout(parseInt(e.currentTarget.value));
- setHasUnsavedChanges(true);
- }}
- class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- >
- 5 seconds
- 10 seconds
- 20 seconds
- 30 seconds
-
-
-
-
-
- {/* Network Settings */}
-
-
-
-
-
-
- Network Settings
-
-
-
-
-
Backend Port
-
API server port
-
{
- setBackendPort(parseInt(e.currentTarget.value));
- setHasUnsavedChanges(true);
- }}
- min="1"
- max="65535"
- class="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- />
-
-
-
-
Frontend Port
-
Web UI port
-
{
- setFrontendPort(parseInt(e.currentTarget.value));
- setHasUnsavedChanges(true);
- }}
- min="1"
- max="65535"
- class="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- />
-
-
-
-
-
CORS Allowed Origins
-
For reverse proxy setups (* = allow all)
-
{
- setAllowedOrigins(e.currentTarget.value);
- setHasUnsavedChanges(true);
- }}
- placeholder="* or https://example.com"
- class="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- />
-
-
-
-
- Note: Port changes require a service restart
-
-
-
-
- {/* Update Settings */}
-
-
-
-
-
-
-
- Updates
-
-
-
- {/* Version Info */}
-
-
-
Current Version
-
- {versionInfo()?.version || 'Loading...'}
- {versionInfo()?.isDevelopment && ' (Development)'}
- {versionInfo()?.isDocker && ' - Docker'}
-
-
-
- {checkingForUpdates() ? (
- <>
-
- Checking...
- >
- ) : (
- <>Check for Updates>
- )}
-
-
-
- {/* Docker Message */}
-
-
-
- Docker Installation: Updates are managed through Docker. Pull the latest image to update.
-
-
-
-
- {/* Update Available */}
-
-
-
-
-
- Update Available: {updateInfo()?.latestVersion}
-
-
- Released: {updateInfo()?.releaseDate ? new Date(updateInfo()!.releaseDate).toLocaleDateString() : 'Unknown'}
-
-
-
-
- Apply Update
-
-
-
-
-
- Release Notes
-
- {updateInfo()?.releaseNotes}
-
-
-
-
-
-
- {/* Update Progress */}
-
-
-
-
- {updateStatus()?.message || 'Processing update...'}
-
-
-
-
-
-
-
-
- {/* Update Settings */}
-
-
-
-
Update Channel
-
- Choose between stable and release candidate versions
-
-
-
{
- setUpdateChannel(e.currentTarget.value as 'stable' | 'rc');
- setHasUnsavedChanges(true);
- }}
- disabled={versionInfo()?.isDocker}
- class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800 disabled:opacity-50"
- >
- Stable
- Release Candidate
-
-
-
-
-
-
Auto-Update
-
- Automatically install updates when available
-
-
-
- {
- setAutoUpdateEnabled(e.currentTarget.checked);
- setHasUnsavedChanges(true);
- }}
- disabled={versionInfo()?.isDocker}
- class="sr-only peer"
- />
-
-
-
-
-
-
-
-
-
Check Interval
-
- How often to check for updates
-
-
-
{
- setAutoUpdateCheckInterval(parseInt(e.currentTarget.value));
- setHasUnsavedChanges(true);
- }}
- class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- >
- Every 6 hours
- Every 12 hours
- Daily
- Weekly
-
-
-
-
-
-
Update Time
-
- Preferred time for automatic updates
-
-
-
{
- setAutoUpdateTime(e.currentTarget.value);
- setHasUnsavedChanges(true);
- }}
- class="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"
- />
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Diagnostics Tab */}
-
-
-
-
System Diagnostics
-
-
- {/* System Information */}
-
-
System Information
-
-
- Version:
- 2.0.0
-
-
- Backend:
- Go 1.21
-
-
- Frontend:
- SolidJS + TypeScript
-
-
- WebSocket Status:
-
- {connected() ? 'Connected' : 'Disconnected'}
-
-
-
- Backend Port:
- {window.location.hostname === 'localhost' ? '3000' : '3000'}
-
-
- Frontend Port:
- {window.location.port || (window.location.protocol === 'https:' ? '443' : '80')}
-
-
-
-
- {/* Connection Status */}
-
-
Connection Status
-
-
- PVE Nodes:
- {nodes().filter(n => n.type === 'pve').length}
-
-
- PBS Nodes:
- {nodes().filter(n => n.type === 'pbs').length}
-
-
- Total VMs:
- {state.vms?.length || 0}
-
-
- Total Containers:
- {state.containers?.length || 0}
-
-
-
-
- {/* Export Diagnostics */}
-
-
Export Diagnostics
-
- Export system diagnostics data for troubleshooting
-
-
{
- const diagnostics = {
- timestamp: new Date().toISOString(),
- version: '2.0.0',
- environment: {
- userAgent: navigator.userAgent,
- platform: navigator.platform,
- language: navigator.language,
- screenResolution: `${window.screen.width}x${window.screen.height}`,
- windowSize: `${window.innerWidth}x${window.innerHeight}`,
- timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone
- },
- websocket: {
- connected: connected(),
- url: `${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}/ws`
- },
- nodes: nodes(),
- state: {
- nodesCount: state.nodes?.length || 0,
- vmsCount: state.vms?.length || 0,
- containersCount: state.containers?.length || 0,
- storageCount: state.storage?.length || 0
- },
- settings: {
- pollingInterval: pollingInterval()
- }
- };
-
- const blob = new Blob([JSON.stringify(diagnostics, null, 2)], { type: 'application/json' });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = `pulse-diagnostics-${new Date().toISOString().split('T')[0]}.json`;
- document.body.appendChild(a);
- a.click();
- document.body.removeChild(a);
- URL.revokeObjectURL(url);
- }}
- class="px-4 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
- >
- Export Diagnostics
-
-
-
-
-
-
-
-
-
- {/* Node Modal */}
-
{
- setShowNodeModal(false);
- setEditingNode(null);
- }}
- nodeType={activeTab() === 'pve' ? 'pve' : 'pbs'}
- editingNode={editingNode() ?? undefined}
- onSave={async (nodeData) => {
- try {
- if (editingNode()) {
- // Update existing node
- await NodesAPI.updateNode(editingNode()!.id, nodeData as NodeConfig);
-
- // Update local state
- setNodes(nodes().map(n =>
- n.id === editingNode()!.id
- ? {
- ...n,
- ...nodeData,
- // Update hasPassword/hasToken based on whether credentials were provided
- hasPassword: nodeData.password ? true : n.hasPassword,
- hasToken: nodeData.tokenValue ? true : n.hasToken
- }
- : n
- ));
- showSuccess('Node updated successfully');
- } else {
- // Add new node
- await NodesAPI.addNode(nodeData as NodeConfig);
-
- // Reload nodes to get the new ID
- const nodesList = await NodesAPI.getNodes();
- const nodesWithStatus = nodesList.map(node => ({
- ...node,
- // Use the hasPassword/hasToken from the API if available, otherwise check local fields
- hasPassword: node.hasPassword ?? !!node.password,
- hasToken: node.hasToken ?? !!node.tokenValue,
- status: node.status || 'disconnected' as const
- }));
- setNodes(nodesWithStatus);
- showSuccess('Node added successfully');
- }
-
- setShowNodeModal(false);
- setEditingNode(null);
- } catch (error) {
- showError(error instanceof Error ? error.message : 'Operation failed');
- }
- }}
- />
-
- >
- );
-};
-
-export default Settings;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Storage/Storage.tsx b/pulse-test-staging/frontend-modern/src/components/Storage/Storage.tsx
deleted file mode 100644
index 64e82ad33..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Storage/Storage.tsx
+++ /dev/null
@@ -1,449 +0,0 @@
-import { Component, For, Show, createSignal, createMemo, createEffect } from 'solid-js';
-import { useWebSocket } from '@/App';
-import { getAlertStyles } from '@/utils/alerts';
-import { AlertIndicator, AlertCountBadge } from '@/components/shared/AlertIndicators';
-import { formatBytes } from '@/utils/format';
-import { createTooltipSystem } from '@/components/shared/Tooltip';
-import type { Storage as StorageType } from '@/types/api';
-import { ComponentErrorBoundary } from '@/components/ErrorBoundary';
-
-
-const Storage: Component = () => {
- const { state, connected, activeAlerts, initialDataReceived } = useWebSocket();
- const [viewMode, setViewMode] = createSignal<'node' | 'storage'>('node');
- const [searchTerm, setSearchTerm] = createSignal('');
- const [showFilters, setShowFilters] = createSignal(
- localStorage.getItem('storageShowFilters') !== null
- ? localStorage.getItem('storageShowFilters') === 'true'
- : false // Default to collapsed
- );
-
- // Create tooltip system
- const TooltipComponent = createTooltipSystem();
-
- // Load preferences from localStorage
- createEffect(() => {
- const savedViewMode = localStorage.getItem('storageViewMode');
- if (savedViewMode === 'storage') setViewMode('storage');
- });
-
- // Save preferences to localStorage
- createEffect(() => {
- localStorage.setItem('storageViewMode', viewMode());
- });
-
- createEffect(() => {
- localStorage.setItem('storageShowFilters', showFilters().toString());
- });
-
- // Filter storage - in storage view, filter out 0 capacity
- const filteredStorage = createMemo(() => {
- const storage = state.storage || [];
- if (viewMode() === 'storage') {
- return storage.filter((s) => s.total > 0);
- }
- return storage;
- });
-
- // Sort and filter storage
- const sortedStorage = createMemo(() => {
- let storage = [...filteredStorage()];
-
- // Apply search filter
- const search = searchTerm().toLowerCase();
- if (search) {
- storage = storage.filter(s =>
- s.name.toLowerCase().includes(search) ||
- s.node.toLowerCase().includes(search) ||
- s.type.toLowerCase().includes(search) ||
- s.content?.toLowerCase().includes(search) ||
- (s.status && s.status.toLowerCase().includes(search))
- );
- }
-
- // Always sort by name alphabetically for consistent order
- return storage.sort((a, b) => a.name.localeCompare(b.name));
- });
-
- // Group storage by node or storage
- const groupedStorage = createMemo(() => {
- const storage = sortedStorage();
- const mode = viewMode();
-
- if (mode === 'node') {
- const groups: Record = {};
- storage.forEach(s => {
- if (!groups[s.node]) groups[s.node] = [];
- groups[s.node].push(s);
- });
- return groups;
- } else {
- // Group by storage name - show all storage as-is for maximum compatibility
- const groups: Record = {};
-
- storage.forEach(s => {
- if (!groups[s.name]) groups[s.name] = [];
- groups[s.name].push(s);
- });
-
- return groups;
- }
- });
-
- const getProgressBarColor = (usage: number) => {
- // Match MetricBar component styling - use the same disk/generic logic
- if (usage >= 90) return 'bg-red-500/60 dark:bg-red-500/50';
- if (usage >= 80) return 'bg-yellow-500/60 dark:bg-yellow-500/50';
- if (usage >= 70) return 'bg-amber-500/60 dark:bg-amber-500/50';
- if (usage >= 60) return 'bg-yellow-500/60 dark:bg-yellow-500/50';
- return 'bg-emerald-500/60 dark:bg-emerald-500/50';
- };
-
- const resetFilters = () => {
- setSearchTerm('');
- setViewMode('node');
- };
-
- const getTotalByNode = (storages: StorageType[]) => {
- const totals = { used: 0, total: 0, free: 0 };
- storages.forEach(s => {
- totals.used += s.used || 0;
- totals.total += s.total || 0;
- totals.free += s.free || 0;
- });
- return totals;
- };
-
- const calculateOverallUsage = (storages: StorageType[]) => {
- const totals = getTotalByNode(storages);
- return totals.total > 0 ? (totals.used / totals.total * 100) : 0;
- };
-
- // Handle keyboard shortcuts
- let searchInputRef: HTMLInputElement | undefined;
-
- createEffect(() => {
- const handleKeyDown = (e: KeyboardEvent) => {
- // Ignore if user is typing in an input
- const target = e.target as HTMLElement;
- const isInputField = target.tagName === 'INPUT' ||
- target.tagName === 'TEXTAREA' ||
- target.tagName === 'SELECT' ||
- target.contentEditable === 'true';
-
- // Escape key behavior
- if (e.key === 'Escape') {
- // First check if we have search/filters to clear
- if (searchTerm().trim() || viewMode() !== 'node') {
- // Clear search and reset filters
- resetFilters();
-
- // Blur the search input if it's focused
- if (searchInputRef && document.activeElement === searchInputRef) {
- searchInputRef.blur();
- }
- } else if (showFilters()) {
- // No search/filters active, so collapse the filters section
- setShowFilters(false);
- }
- // If filters are already collapsed, do nothing
- } else if (!isInputField && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
- // If it's a printable character and user is not in an input field
- // Expand filters section if collapsed
- if (!showFilters()) {
- setShowFilters(true);
- }
- // Focus the search input and let the character be typed
- if (searchInputRef) {
- searchInputRef.focus();
- // Don't prevent default - let the character be typed
- }
- }
- };
-
- document.addEventListener('keydown', handleKeyDown);
- return () => document.removeEventListener('keydown', handleKeyDown);
- });
-
- return (
-
-
- {/* Filters and Search */}
-
-
setShowFilters(!showFilters())}
- class="w-full px-4 py-3 flex items-center justify-between hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer"
- >
-
-
-
-
-
-
-
-
-
-
-
-
- Filters & Search
-
-
- Active
-
-
-
-
-
-
-
-
-
-
- {/* Search Bar Row */}
-
-
-
setSearchTerm(e.currentTarget.value)}
- class="w-full pl-9 pr-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg
- bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500
- focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 dark:focus:border-blue-400 outline-none transition-all"
- />
-
-
-
-
-
- {/* Reset Button */}
-
-
-
-
-
-
-
- Reset
-
-
-
- {/* Filters Row */}
-
- {/* View Mode Toggle */}
-
-
Group by:
-
- setViewMode('node')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- viewMode() === 'node'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Node
-
- setViewMode('storage')}
- class={`px-3 py-1.5 text-xs font-medium rounded-md transition-all ${
- viewMode() === 'storage'
- ? 'bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100'
- }`}
- >
- Storage
-
-
-
-
-
-
-
-
- {/* Loading State */}
-
-
-
-
-
-
-
-
Loading storage data...
-
Connecting to monitoring service
-
-
-
-
- {/* Empty State - No Storage Configured */}
-
-
-
-
-
-
-
No storage found
-
No storage repositories are configured or visible.
-
-
-
-
- {/* Storage Table */}
-
0}>
-
-
-
-
-
- Storage
-
- Node
-
- Type
- Content
- Status
-
- Shared
-
- Usage
- Free
- Total
-
-
-
- a.localeCompare(b))}>
- {([groupName, storages]) => (
- <>
- {/* Group Header */}
-
-
-
-
- {groupName}
-
-
-
-
- {getTotalByNode(storages).total > 0 && (
-
- {formatBytes(getTotalByNode(storages).used)} / {formatBytes(getTotalByNode(storages).total)} ({calculateOverallUsage(storages).toFixed(1)}%)
-
- )}
-
-
-
-
-
- {/* Storage Rows */}
- >}>
- {(storage) => {
- const usagePercent = storage.total > 0 ? (storage.used / storage.total * 100) : 0;
- const isDisabled = storage.status !== 'available';
-
- const alertStyles = getAlertStyles(storage.id || `${storage.instance}-${storage.name}`, activeAlerts);
- const rowClass = `${isDisabled ? 'opacity-60' : ''} ${alertStyles.rowClass} hover:shadow-sm transition-all duration-200`;
-
- return (
-
-
-
-
- {storage.name}
-
-
-
-
-
-
-
- {storage.node}
-
-
-
- {storage.type}
-
-
-
- {storage.content || '-'}
-
-
-
- {storage.status || 'unknown'}
-
-
-
-
- {storage.shared ? '✓' : '-'}
-
-
-
-
-
-
-
-
- {usagePercent.toFixed(0)}%
- {formatBytes(storage.used || 0)} / {formatBytes(storage.total || 0)} ({usagePercent.toFixed(1)}%)
-
-
-
-
- {formatBytes(storage.free || 0)}
- {formatBytes(storage.total || 0)}
-
- );
- }}
-
- >
- )}
-
-
-
-
-
-
-
- {/* Tooltip System */}
-
-
- );
-};
-
-export default Storage;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/Toast/Toast.tsx b/pulse-test-staging/frontend-modern/src/components/Toast/Toast.tsx
deleted file mode 100644
index f5a599049..000000000
--- a/pulse-test-staging/frontend-modern/src/components/Toast/Toast.tsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { Component, createSignal, For, Show } from 'solid-js';
-import { Portal } from 'solid-js/web';
-import { POLLING_INTERVALS, ANIMATIONS } from '@/constants';
-
-export type ToastType = 'success' | 'error' | 'warning' | 'info';
-
-export interface ToastMessage {
- id: string;
- type: ToastType;
- title: string;
- message?: string;
- duration?: number;
-}
-
-interface ToastProps {
- toast: ToastMessage;
- onRemove: (id: string) => void;
-}
-
-const Toast: Component = (props) => {
- const [show, setShow] = createSignal(true);
-
- const icons = {
- success: (
-
-
-
- ),
- error: (
-
-
-
- ),
- warning: (
-
-
-
- ),
- info: (
-
-
-
- )
- };
-
- const colors = {
- success: 'bg-green-50 dark:bg-green-900/20 text-green-800 dark:text-green-200 border-green-200 dark:border-green-800',
- error: 'bg-red-50 dark:bg-red-900/20 text-red-800 dark:text-red-200 border-red-200 dark:border-red-800',
- warning: 'bg-yellow-50 dark:bg-yellow-900/20 text-yellow-800 dark:text-yellow-200 border-yellow-200 dark:border-yellow-800',
- info: 'bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200 border-blue-200 dark:border-blue-800'
- };
-
- const iconColors = {
- success: 'text-green-500',
- error: 'text-red-500',
- warning: 'text-yellow-500',
- info: 'text-blue-500'
- };
-
- // Auto-remove after duration
- window.setTimeout(() => {
- setShow(false);
- window.setTimeout(() => props.onRemove(props.toast.id), ANIMATIONS.TOAST_SLIDE);
- }, props.toast.duration || POLLING_INTERVALS.TOAST_DURATION);
-
- return (
-
- );
-};
-
-// Toast Container Component
-// Declare global interface extension
-declare global {
- interface Window {
- showToast: (type: ToastType, title: string, message?: string, duration?: number) => void;
- }
-}
-
-export const ToastContainer: Component = () => {
- const [toasts, setToasts] = createSignal([]);
-
- const removeToast = (id: string) => {
- setToasts(toasts().filter(t => t.id !== id));
- };
-
- // Expose global toast function
- window.showToast = (type: ToastType, title: string, message?: string, duration?: number) => {
- const id = Date.now().toString();
- setToasts([...toasts(), { id, type, title, message, duration }]);
- };
-
- return (
-
-
-
- {(toast) => }
-
-
-
- );
-};
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/shared/AlertIndicators.tsx b/pulse-test-staging/frontend-modern/src/components/shared/AlertIndicators.tsx
deleted file mode 100644
index bc0e81714..000000000
--- a/pulse-test-staging/frontend-modern/src/components/shared/AlertIndicators.tsx
+++ /dev/null
@@ -1,115 +0,0 @@
-import { Component, Show, createSignal } from 'solid-js';
-import type { Alert } from '@/types/api';
-import { Portal } from 'solid-js/web';
-
-interface AlertIndicatorProps {
- severity: 'critical' | 'warning' | null;
- alerts?: Alert[];
-}
-
-export const AlertIndicator: Component = (props) => {
- if (!props.severity) return null;
-
- const [showTooltip, setShowTooltip] = createSignal(false);
- const [tooltipPosition, setTooltipPosition] = createSignal({ x: 0, y: 0 });
-
- const dotClass = props.severity === 'critical'
- ? 'bg-red-500 animate-pulse'
- : 'bg-orange-500';
-
- const handleMouseEnter = (e: MouseEvent) => {
- if (!props.alerts || props.alerts.length === 0) return;
- const rect = (e.target as HTMLElement).getBoundingClientRect();
- setTooltipPosition({ x: rect.left + rect.width / 2, y: rect.top - 5 });
- setShowTooltip(true);
- };
-
- const handleMouseLeave = () => {
- setShowTooltip(false);
- };
-
- return (
- <>
-
- 0}>
-
-
- {props.alerts!.map((alert, i) => (
-
0 ? 'mt-1' : ''}>
- {alert.type}: {alert.value.toFixed(1)}% (threshold: {alert.threshold}%)
-
- ))}
-
-
-
-
- >
- );
-};
-
-interface AlertCountBadgeProps {
- count: number;
- severity: 'critical' | 'warning';
- alerts?: Alert[];
-}
-
-export const AlertCountBadge: Component = (props) => {
- const [showTooltip, setShowTooltip] = createSignal(false);
- const [tooltipPosition, setTooltipPosition] = createSignal({ x: 0, y: 0 });
-
- const badgeClass = props.severity === 'critical'
- ? 'bg-red-500 text-white'
- : 'bg-orange-500 text-white';
-
- const handleMouseEnter = (e: MouseEvent) => {
- if (!props.alerts || props.alerts.length === 0) return;
- const rect = (e.target as HTMLElement).getBoundingClientRect();
- setTooltipPosition({ x: rect.left + rect.width / 2, y: rect.top - 5 });
- setShowTooltip(true);
- };
-
- const handleMouseLeave = () => {
- setShowTooltip(false);
- };
-
- return (
- <>
-
- {props.count}
-
- 0}>
-
-
-
{props.count} Active Alerts:
- {props.alerts!.map((alert, i) => (
-
0 ? 'mt-1' : ''}>
- {i + 1}. {alert.type}: {alert.value.toFixed(1)}% (threshold: {alert.threshold}%)
-
- ))}
-
-
-
-
- >
- );
-};
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/shared/ScrollableTable.tsx b/pulse-test-staging/frontend-modern/src/components/shared/ScrollableTable.tsx
deleted file mode 100644
index 4b3a574b0..000000000
--- a/pulse-test-staging/frontend-modern/src/components/shared/ScrollableTable.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import { Component, JSX, createSignal, createEffect, onMount } from 'solid-js';
-import { Show } from 'solid-js';
-
-interface ScrollableTableProps {
- children: JSX.Element;
- class?: string;
- minWidth?: string;
-}
-
-export const ScrollableTable: Component = (props) => {
- const [showLeftFade, setShowLeftFade] = createSignal(false);
- const [showRightFade, setShowRightFade] = createSignal(false);
- let scrollContainer: HTMLDivElement | undefined;
-
- const checkScroll = () => {
- if (!scrollContainer) return;
-
- const { scrollLeft, scrollWidth, clientWidth } = scrollContainer;
- setShowLeftFade(scrollLeft > 0);
- setShowRightFade(scrollLeft < scrollWidth - clientWidth - 1);
- };
-
- onMount(() => {
- checkScroll();
- window.addEventListener('resize', checkScroll);
- });
-
- createEffect(() => {
- if (scrollContainer) {
- scrollContainer.addEventListener('scroll', checkScroll);
- return () => scrollContainer?.removeEventListener('scroll', checkScroll);
- }
- });
-
- return (
-
- {/* Left fade */}
-
-
-
-
- {/* Scrollable container */}
-
-
- {/* Right fade */}
-
-
-
-
- );
-};
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/components/shared/Tooltip.tsx b/pulse-test-staging/frontend-modern/src/components/shared/Tooltip.tsx
deleted file mode 100644
index b1c40e717..000000000
--- a/pulse-test-staging/frontend-modern/src/components/shared/Tooltip.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { Component, createSignal, createEffect, Show } from 'solid-js';
-import { Portal } from 'solid-js/web';
-
-interface TooltipProps {
- content: string;
- x: number;
- y: number;
- visible: boolean;
-}
-
-const Tooltip: Component = (props) => {
- let tooltipRef: HTMLDivElement | undefined;
- const [position, setPosition] = createSignal({ x: 0, y: 0 });
-
- createEffect(() => {
- if (!props.visible) {
- setPosition({ x: props.x, y: props.y });
- return;
- }
-
- // Use requestAnimationFrame to ensure DOM is updated
- requestAnimationFrame(() => {
- if (!tooltipRef) return;
-
- // Calculate position to keep tooltip on screen
- const rect = tooltipRef.getBoundingClientRect();
- const padding = 10;
-
- let x = props.x + padding;
- let y = props.y - rect.height - padding;
-
- // Keep within viewport
- if (x + rect.width > window.innerWidth) {
- x = props.x - rect.width - padding;
- }
-
- if (y < 0) {
- y = props.y + padding;
- }
-
- // Ensure x and y are not negative
- x = Math.max(0, x);
- y = Math.max(0, y);
-
- setPosition({ x, y });
- });
- });
-
- return (
-
-
-
-
-
- );
-};
-
-// Global tooltip singleton
-let tooltipInstance: {
- show: (content: string, x: number, y: number) => void;
- hide: () => void;
-} | null = null;
-
-export function createTooltipSystem() {
- const [visible, setVisible] = createSignal(false);
- const [content, setContent] = createSignal('');
- const [position, setPosition] = createSignal({ x: 0, y: 0 });
-
- tooltipInstance = {
- show: (content: string, x: number, y: number) => {
- setContent(content);
- setPosition({ x, y });
- setVisible(true);
- },
- hide: () => {
- setVisible(false);
- }
- };
-
- return () => (
-
- );
-}
-
-export function showTooltip(content: string, x: number, y: number) {
- tooltipInstance?.show(content, x, y);
-}
-
-export function hideTooltip() {
- tooltipInstance?.hide();
-}
-
-export default Tooltip;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/constants.ts b/pulse-test-staging/frontend-modern/src/constants.ts
deleted file mode 100644
index 575b8bea3..000000000
--- a/pulse-test-staging/frontend-modern/src/constants.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-// Constants used throughout the application
-
-// Polling and update intervals (in milliseconds)
-export const POLLING_INTERVALS = {
- DEFAULT: 5000, // 5 seconds - default polling interval
- RECONNECT_BASE: 1000, // 1 second - base reconnect delay
- RECONNECT_MAX: 30000, // 30 seconds - max reconnect delay
- DATA_FLASH: 1000, // 1 second - data update indicator flash duration
- TOAST_DURATION: 5000, // 5 seconds - default toast notification duration
-} as const;
-
-// Display thresholds (percentages)
-export const THRESHOLDS = {
- WARNING: 60, // Yellow warning threshold
- CRITICAL: 80, // Orange critical threshold
- DANGER: 90, // Red danger threshold
-} as const;
-
-// Network and I/O metrics thresholds (MB/s)
-export const IO_THRESHOLDS = {
- LOW: 1,
- MEDIUM: 10,
- HIGH: 50,
- VERY_HIGH: 100,
-} as const;
-
-// Animation durations (in milliseconds)
-export const ANIMATIONS = {
- TOAST_SLIDE: 300, // Toast slide in/out animation
-} as const;
-
-// UI configuration
-export const UI = {
- DEBOUNCE_DELAY: 300, // 300ms - input debounce delay
-} as const;
-
-// WebSocket configuration
-export const WEBSOCKET = {
- PING_INTERVAL: 25000, // 25 seconds - WebSocket ping interval
- MESSAGE_TYPES: {
- INITIAL_STATE: 'initialState',
- RAW_DATA: 'rawData',
- ERROR: 'error',
- } as const,
-} as const;
-
-// Storage keys for localStorage
-export const STORAGE_KEYS = {
- DARK_MODE: 'darkMode',
- VIEW_MODE: 'viewMode',
- DISPLAY_MODE: 'displayMode',
- SORT_KEY: 'sortKey',
- SORT_DIRECTION: 'sortDirection',
- ALERT_THRESHOLDS: 'alertThresholds',
-} as const;
-
-// File size units
-export const FILE_SIZE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] as const;
-
-// Log levels for the logger
-export const LOG_LEVELS = {
- DEBUG: 0,
- INFO: 1,
- WARN: 2,
- ERROR: 3,
-} as const;
-
-export type LogLevel = keyof typeof LOG_LEVELS;
-
diff --git a/pulse-test-staging/frontend-modern/src/hooks/useIntersectionObserver.ts b/pulse-test-staging/frontend-modern/src/hooks/useIntersectionObserver.ts
deleted file mode 100644
index 52700a14d..000000000
--- a/pulse-test-staging/frontend-modern/src/hooks/useIntersectionObserver.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { onMount, onCleanup, createSignal } from 'solid-js';
-
-interface UseIntersectionObserverOptions {
- threshold?: number;
- rootMargin?: string;
- root?: Element | null;
-}
-
-export function useIntersectionObserver(
- ref: () => HTMLElement | undefined,
- options: UseIntersectionObserverOptions = {}
-) {
- const [isIntersecting, setIsIntersecting] = createSignal(false);
- let observer: IntersectionObserver | undefined;
-
- onMount(() => {
- const element = ref();
- if (!element || typeof window === 'undefined' || !window.IntersectionObserver) {
- // If IntersectionObserver is not supported, assume element is visible
- setIsIntersecting(true);
- return;
- }
-
- observer = new IntersectionObserver(
- ([entry]) => {
- setIsIntersecting(entry.isIntersecting);
- },
- {
- threshold: options.threshold || 0,
- rootMargin: options.rootMargin || '50px',
- root: options.root || null
- }
- );
-
- observer.observe(element);
- });
-
- onCleanup(() => {
- if (observer) {
- observer.disconnect();
- }
- });
-
- return isIntersecting;
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/index.css b/pulse-test-staging/frontend-modern/src/index.css
deleted file mode 100644
index 043a8dbc2..000000000
--- a/pulse-test-staging/frontend-modern/src/index.css
+++ /dev/null
@@ -1,299 +0,0 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/* Custom styles */
-@layer base {
- body {
- @apply bg-gray-100 dark:bg-gray-900 text-gray-900 dark:text-gray-100;
- /* Ensure body scrollbar follows our styling */
- overflow-y: auto;
- overflow-x: hidden;
- }
-
- /* Hide scrollbars during transitions to prevent flicker */
- html {
- overflow-y: scroll;
- scroll-behavior: smooth;
- }
-
- /* Threshold slider styles */
- .threshold-slider-container {
- @apply relative w-full;
- }
-
- .threshold-slider {
- @apply w-full h-3.5 appearance-none bg-transparent relative z-10;
- }
-
- /* Slider track styles - match progress bar height */
- .threshold-slider::-webkit-slider-runnable-track {
- @apply h-3.5 rounded bg-gray-200 dark:bg-gray-600;
- }
-
- .threshold-slider::-moz-range-track {
- @apply h-3.5 rounded bg-gray-200 dark:bg-gray-600;
- }
-
- /* Slider thumb styles with value display */
- .threshold-slider::-webkit-slider-thumb {
- @apply appearance-none w-12 h-5 rounded-full cursor-pointer relative;
- margin-top: -2.5px; /* Center thumb on track */
- background: white;
- border: 2px solid currentColor;
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
- }
-
- .threshold-slider::-moz-range-thumb {
- @apply appearance-none w-12 h-5 rounded-full cursor-pointer relative border-0;
- background: white;
- border: 2px solid currentColor;
- box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
- }
-
- /* Color coding for different metrics */
- .threshold-slider.slider-cpu {
- color: #3b82f6; /* blue-500 */
- }
-
- .threshold-slider.slider-memory {
- color: #10b981; /* green-500 */
- }
-
- .threshold-slider.slider-disk {
- color: #f59e0b; /* amber-500 */
- }
-
- /* Value display inside thumb */
- .threshold-value {
- @apply absolute inset-0 flex items-center justify-center text-[10px] font-semibold pointer-events-none;
- color: currentColor;
- }
-}
-
-@layer components {
- /* Card styles */
- .card {
- @apply bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700;
- }
-
- /* Table styles */
- .table-header {
- @apply text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider;
- }
-
- .table-row {
- @apply border-b border-gray-200 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-750;
- }
-
- /* Status indicators */
- .status-running {
- @apply text-green-600 dark:text-green-400;
- }
-
- .status-stopped {
- @apply text-gray-600 dark:text-gray-400;
- }
-
- .status-error {
- @apply text-red-600 dark:text-red-400;
- }
-
- /* Progress bars */
- .progress-bar {
- @apply bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden;
- }
-
- .progress-fill {
- @apply h-full;
- transition: width 300ms ease-out;
- }
-
- /* Stable chart containers */
- .chart-stable-container {
- contain: layout style;
- will-change: contents;
- }
-
- /* Prevent chart SVG flicker */
- .sparkline {
- backface-visibility: hidden;
- transform: translateZ(0);
- }
-
- /* Disable animations in charts mode to prevent blinking */
- .charts-mode .sparkline path {
- transition: none !important;
- }
-
- /* Custom scrollbar - subtle styling */
- .custom-scrollbar {
- scrollbar-width: thin;
- scrollbar-color: theme('colors.gray.300') theme('colors.gray.100');
- }
-
- .dark .custom-scrollbar {
- scrollbar-color: theme('colors.gray.700') theme('colors.gray.800');
- }
-
- .custom-scrollbar::-webkit-scrollbar {
- width: 6px;
- height: 6px;
- }
-
- .custom-scrollbar::-webkit-scrollbar-track {
- @apply bg-gray-100 dark:bg-gray-800;
- }
-
- .custom-scrollbar::-webkit-scrollbar-thumb {
- @apply bg-gray-300 dark:bg-gray-700 rounded-full;
- }
-
- .custom-scrollbar::-webkit-scrollbar-thumb:hover {
- @apply bg-gray-400 dark:bg-gray-600;
- }
-}
-
-/* Global scrollbar styling */
-* {
- scrollbar-width: thin;
- scrollbar-color: rgba(156, 163, 175, 0.5) transparent; /* gray-400 with transparency */
-}
-
-.dark * {
- scrollbar-color: rgba(55, 65, 81, 0.5) transparent; /* gray-700 with transparency */
-}
-
-/* Make scrollbars even more subtle on hover */
-*:hover {
- scrollbar-color: rgba(156, 163, 175, 0.7) rgba(243, 244, 246, 0.5); /* Slightly more visible on hover */
-}
-
-.dark *:hover {
- scrollbar-color: rgba(75, 85, 99, 0.7) rgba(31, 41, 55, 0.3); /* dark mode hover */
-}
-
-*::-webkit-scrollbar {
- width: 6px;
- height: 6px;
-}
-
-*::-webkit-scrollbar-track {
- background: transparent;
-}
-
-*::-webkit-scrollbar-thumb {
- background-color: rgba(156, 163, 175, 0.5);
- border-radius: 10px;
-}
-
-.dark *::-webkit-scrollbar-thumb {
- background-color: rgba(55, 65, 81, 0.5);
-}
-
-*::-webkit-scrollbar-thumb:hover {
- background-color: rgba(156, 163, 175, 0.8);
-}
-
-.dark *::-webkit-scrollbar-thumb:hover {
- background-color: rgba(75, 85, 99, 0.8);
-}
-
-/* Dark mode transitions - Only apply to elements that actually change colors */
-body,
-.card,
-.table-row,
-.table-header,
-.bg-white,
-.bg-gray-50,
-.bg-gray-100,
-.bg-gray-200,
-.bg-gray-300,
-.bg-gray-700,
-.bg-gray-800,
-.bg-gray-900,
-.text-gray-500,
-.text-gray-600,
-.text-gray-700,
-.text-gray-800,
-.text-gray-900,
-.border-gray-200,
-.border-gray-300,
-.border-gray-600,
-.border-gray-700,
-.dark\:bg-gray-700,
-.dark\:bg-gray-800,
-.dark\:bg-gray-900,
-.dark\:text-gray-100,
-.dark\:text-gray-200,
-.dark\:text-gray-300,
-.dark\:text-gray-400,
-.dark\:border-gray-600,
-.dark\:border-gray-700 {
- transition: background-color 150ms ease-in-out, color 150ms ease-in-out, border-color 150ms ease-in-out;
-}
-
-/* Pulse logo animation - subtle ripple effect */
-@keyframes pulse-logo {
- 0% {
- transform: scale(1);
- }
- 25% {
- transform: scale(1.05);
- }
- 50% {
- transform: scale(1);
- }
-}
-
-@keyframes pulse-ring {
- 0%, 100% {
- opacity: 0.92;
- transform: scale(1);
- }
- 50% {
- opacity: 0.6;
- transform: scale(1.1);
- }
-}
-
-.animate-pulse-logo {
- animation: pulse-logo 0.8s cubic-bezier(0.4, 0, 0.6, 1);
- transform-origin: center;
-}
-
-.animate-pulse-logo .pulse-ring {
- animation: pulse-ring 0.8s cubic-bezier(0.4, 0, 0.6, 1);
- transform-origin: center;
- transform-box: fill-box;
-}
-
-/* Stable table layout */
-.table-fixed {
- table-layout: fixed;
-}
-
-/* Prevent text from affecting column widths */
-.table-fixed td,
-.table-fixed th {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
-}
-
-/* Keep name column slightly flexible while maintaining stability */
-.table-fixed td:first-child {
- white-space: normal;
- word-break: break-word;
-}
-
-/* Hide scrollbars but keep functionality */
-.scrollbar-hide {
- -ms-overflow-style: none;
- scrollbar-width: none;
-}
-
-.scrollbar-hide::-webkit-scrollbar {
- display: none;
-}
-
diff --git a/pulse-test-staging/frontend-modern/src/index.tsx b/pulse-test-staging/frontend-modern/src/index.tsx
deleted file mode 100644
index e87d37f28..000000000
--- a/pulse-test-staging/frontend-modern/src/index.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-/* @refresh reload */
-import { render } from 'solid-js/web';
-import './index.css';
-import App from './App';
-import { logger } from './utils/logger';
-
-const root = document.getElementById('root');
-
-if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
- throw new Error(
- 'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?',
- );
-}
-
-// Initialize app with logging
-logger.info('Pulse monitoring dashboard starting');
-
-
-render(() => , root!);
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/pages/Alerts.tsx b/pulse-test-staging/frontend-modern/src/pages/Alerts.tsx
deleted file mode 100644
index 19f547a46..000000000
--- a/pulse-test-staging/frontend-modern/src/pages/Alerts.tsx
+++ /dev/null
@@ -1,2642 +0,0 @@
-import { createSignal, Show, For, createMemo, createEffect, onMount } from 'solid-js';
-import { ThresholdSlider } from '@/components/Dashboard/ThresholdSlider';
-import { EmailProviderSelect } from '@/components/Alerts/EmailProviderSelect';
-import { WebhookConfig } from '@/components/Alerts/WebhookConfig';
-import { CustomRulesTab } from '@/components/Alerts/CustomRulesTab';
-import { useWebSocket } from '@/App';
-import { showSuccess, showError } from '@/utils/toast';
-import { AlertsAPI } from '@/api/alerts';
-import { NotificationsAPI } from '@/api/notifications';
-import type { EmailConfig } from '@/api/notifications';
-import type { HysteresisThreshold, AlertThresholds } from '@/types/alerts';
-import type { Alert, State } from '@/types/api';
-
-type AlertTab = 'overview' | 'thresholds' | 'destinations' | 'schedule' | 'history' | 'custom-rules';
-
-// Webhook interface matching WebhookConfig component
-interface Webhook {
- id?: string;
- name: string;
- url: string;
- method: string;
- service: string;
- headers: Record;
- enabled: boolean;
-}
-
-// Store reference interfaces
-interface DestinationsRef {
- emailConfig?: () => EmailConfig;
-}
-
-interface ScheduleConfig {
- enabled?: boolean;
- quietHours?: {
- enabled: boolean;
- start: string;
- end: string;
- days: Record;
- timezone?: string;
- };
- cooldown?: number;
- groupingWindow?: number;
- grouping?: {
- enabled: boolean;
- window: number;
- byNode?: boolean;
- byGuest?: boolean;
- };
- maxAlertsHour?: number;
- escalation?: {
- enabled: boolean;
- };
-}
-
-interface ScheduleRef {
- setScheduleConfig?: (config: ScheduleConfig) => void;
- getScheduleConfig?: () => ScheduleConfig | undefined;
-}
-
-// Override interface for both guests and nodes
-interface Override {
- id: string; // Full ID (e.g. "Main-node1-105" for guest, "node-node1" for node)
- name: string; // Display name
- type: 'guest' | 'node';
- resourceType?: string; // VM, CT, or Node
- vmid?: number; // Only for guests
- node?: string; // Node name (for guests), undefined for nodes themselves
- instance?: string;
- thresholds: {
- cpu?: number;
- memory?: number;
- disk?: number;
- diskRead?: number;
- diskWrite?: number;
- networkIn?: number;
- networkOut?: number;
- };
-}
-
-
-// Local email config with UI-specific fields
-interface UIEmailConfig {
- enabled: boolean;
- provider: string;
- smtpHost: string;
- smtpPort: number;
- username: string;
- password: string;
- from: string;
- to: string[];
- tls: boolean;
- startTLS: boolean;
- replyTo: string;
- maxRetries: number;
- retryDelay: number;
- rateLimit: number;
-}
-
-export function Alerts() {
- const { state, activeAlerts } = useWebSocket();
- const [activeTab, setActiveTab] = createSignal('overview');
- const [hasUnsavedChanges, setHasUnsavedChanges] = createSignal(false);
-
- // Store references to child component data
- let destinationsRef: DestinationsRef = {};
- let scheduleRef: ScheduleRef = {};
-
- const [overrides, setOverrides] = createSignal([]);
-
- // Email configuration state moved to parent to persist across tab changes
- const [emailConfig, setEmailConfig] = createSignal({
- enabled: false,
- provider: '',
- smtpHost: '',
- smtpPort: 587,
- username: '',
- password: '',
- from: '',
- to: [] as string[],
- tls: true,
- startTLS: false,
- replyTo: '',
- maxRetries: 3,
- retryDelay: 5,
- rateLimit: 60
- });
-
- // Set up destinationsRef.emailConfig function immediately
- destinationsRef.emailConfig = () => {
- const config = emailConfig();
- return {
- enabled: config.enabled,
- provider: config.provider,
- server: config.smtpHost,
- port: config.smtpPort,
- username: config.username,
- password: config.password,
- from: config.from,
- to: config.to,
- tls: config.tls,
- starttls: config.startTLS
- } as EmailConfig;
- };
-
- // Load existing alert configuration on mount (only once)
- onMount(async () => {
- try {
- const config = await AlertsAPI.getConfig();
- if (config.guestDefaults) {
- // Extract trigger values from potentially hysteresis thresholds
- setGuestDefaults({
- cpu: getTriggerValue(config.guestDefaults.cpu) || 80,
- memory: getTriggerValue(config.guestDefaults.memory) || 85,
- disk: getTriggerValue(config.guestDefaults.disk) || 90,
- diskRead: getTriggerValue(config.guestDefaults.diskRead) || 150,
- diskWrite: getTriggerValue(config.guestDefaults.diskWrite) || 150,
- networkIn: getTriggerValue(config.guestDefaults.networkIn) || 200,
- networkOut: getTriggerValue(config.guestDefaults.networkOut) || 200
- });
- }
-
- if (config.nodeDefaults) {
- setNodeDefaults({
- cpu: getTriggerValue(config.nodeDefaults.cpu) || 80,
- memory: getTriggerValue(config.nodeDefaults.memory) || 85,
- disk: getTriggerValue(config.nodeDefaults.disk) || 90
- });
- }
-
- if (config.storageDefault) {
- setStorageDefault(getTriggerValue(config.storageDefault) || 85);
- }
- if (config.overrides) {
- // Convert overrides object to array format
- const overridesList: Override[] = [];
-
- Object.entries(config.overrides).forEach(([key, thresholds]) => {
- // Check if it's a node override by looking for matching node
- const node = (state.nodes || []).find((n) => n.id === key);
- if (node) {
- overridesList.push({
- id: key,
- name: node.name,
- type: 'node',
- resourceType: 'Node',
- thresholds: extractTriggerValues(thresholds)
- });
- } else {
- // Find the guest by matching the full ID
- const guest = [...(state.vms || []), ...(state.containers || [])].find((g) => g.id === key);
- if (guest) {
- overridesList.push({
- id: key,
- name: guest.name,
- type: 'guest',
- resourceType: guest.type === 'qemu' ? 'VM' : 'CT',
- vmid: guest.vmid,
- node: guest.node,
- instance: guest.instance,
- thresholds: extractTriggerValues(thresholds)
- });
- }
- }
- });
- setOverrides(overridesList);
- }
- // Pass schedule config to schedule tab if it exists
- if (config.schedule && scheduleRef.setScheduleConfig) {
- // Convert days array to Record if needed
- const scheduleConfig: ScheduleConfig = {
- ...config.schedule,
- quietHours: config.schedule.quietHours ? {
- ...config.schedule.quietHours,
- days: Array.isArray(config.schedule.quietHours.days)
- ? {
- '0': config.schedule.quietHours.days.includes(0),
- '1': config.schedule.quietHours.days.includes(1),
- '2': config.schedule.quietHours.days.includes(2),
- '3': config.schedule.quietHours.days.includes(3),
- '4': config.schedule.quietHours.days.includes(4),
- '5': config.schedule.quietHours.days.includes(5),
- '6': config.schedule.quietHours.days.includes(6),
- }
- : config.schedule.quietHours.days
- } : undefined
- };
- scheduleRef.setScheduleConfig(scheduleConfig);
- }
-
- // Load email configuration
- try {
- const emailConfigData = await NotificationsAPI.getEmailConfig();
- setEmailConfig({
- enabled: emailConfigData.enabled,
- provider: emailConfigData.provider,
- smtpHost: emailConfigData.server,
- smtpPort: emailConfigData.port,
- username: emailConfigData.username,
- password: emailConfigData.password || '',
- from: emailConfigData.from,
- to: emailConfigData.to,
- tls: emailConfigData.tls,
- startTLS: emailConfigData.starttls,
- replyTo: '',
- maxRetries: 3,
- retryDelay: 5,
- rateLimit: 60
- });
- } catch (emailErr) {
- console.error('Failed to load email configuration:', emailErr);
- }
- } catch (err) {
- console.error('Failed to load alert configuration:', err);
- }
- });
-
- // Get all guests from state - memoize to prevent unnecessary updates
- const allGuests = createMemo(() => {
- const vms = state.vms || [];
- const containers = state.containers || [];
- return [...vms, ...containers].map(g => ({
- id: g.id,
- name: g.name,
- vmid: g.vmid,
- type: g.type === 'qemu' ? 'VM' : 'LXC',
- node: g.node,
- instance: g.instance
- }));
- }, [], { equals: (prev, next) => {
- // Only update if the actual guest list changed
- if (prev.length !== next.length) return false;
- return prev.every((p, i) => p.vmid === next[i].vmid && p.name === next[i].name);
- }});
-
- // Helper function to extract trigger value from threshold
- const getTriggerValue = (threshold: number | HysteresisThreshold | undefined): number => {
- if (typeof threshold === 'number') {
- return threshold; // Legacy format
- }
- if (threshold && typeof threshold === 'object' && 'trigger' in threshold) {
- return threshold.trigger; // New hysteresis format
- }
- return 0; // Default fallback
- };
-
- // Helper to extract trigger values for all thresholds
- const extractTriggerValues = (thresholds: AlertThresholds): Record => {
- const result: Record = {};
- Object.entries(thresholds).forEach(([key, value]) => {
- result[key] = getTriggerValue(value);
- });
- return result;
- };
-
- // Threshold states - using trigger values for display
- const [guestDefaults, setGuestDefaults] = createSignal({
- cpu: 80,
- memory: 85,
- disk: 90,
- diskRead: 150,
- diskWrite: 150,
- networkIn: 200,
- networkOut: 200
- });
-
- const [nodeDefaults, setNodeDefaults] = createSignal({
- cpu: 80,
- memory: 85,
- disk: 90
- });
-
- const [storageDefault, setStorageDefault] = createSignal(85);
-
- const tabs: { id: AlertTab; label: string; icon: string }[] = [
- {
- id: 'overview',
- label: 'Overview',
- icon: 'M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6'
- },
- {
- id: 'thresholds',
- label: 'Thresholds',
- icon: 'M13 7h8m0 0v8m0-8l-8 8-4-4-6 6'
- },
- {
- id: 'destinations',
- label: 'Notifications',
- icon: 'M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9'
- },
- {
- id: 'schedule',
- label: 'Schedule',
- icon: 'M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z'
- },
- {
- id: 'history',
- label: 'History',
- icon: 'M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z'
- }
- ];
-
- return (
-
- {/* Header with better styling */}
-
-
-
Alert Configuration
-
- Configure monitoring thresholds and notification settings
-
-
-
-
- {/* Save notification bar - only show when there are unsaved changes */}
-
-
-
-
-
-
-
-
-
- You have unsaved changes
-
-
- {
- try {
- // Save alert configuration with hysteresis format
- const createHysteresisThreshold = (trigger: number, clearMargin: number = 5) => ({
- trigger,
- clear: Math.max(0, trigger - clearMargin)
- });
-
- const alertConfig = {
- enabled: true,
- guestDefaults: {
- cpu: createHysteresisThreshold(guestDefaults().cpu),
- memory: createHysteresisThreshold(guestDefaults().memory),
- disk: createHysteresisThreshold(guestDefaults().disk),
- diskRead: createHysteresisThreshold(guestDefaults().diskRead),
- diskWrite: createHysteresisThreshold(guestDefaults().diskWrite),
- networkIn: createHysteresisThreshold(guestDefaults().networkIn),
- networkOut: createHysteresisThreshold(guestDefaults().networkOut)
- },
- nodeDefaults: {
- cpu: createHysteresisThreshold(nodeDefaults().cpu),
- memory: createHysteresisThreshold(nodeDefaults().memory),
- disk: createHysteresisThreshold(nodeDefaults().disk)
- },
- storageDefault: createHysteresisThreshold(storageDefault()),
- minimumDelta: 2.0,
- suppressionWindow: 5,
- hysteresisMargin: 5.0,
- overrides: overrides().reduce((acc, o) => {
- // Convert thresholds to hysteresis format
- const hysteresisThresholds: AlertThresholds = {};
- Object.entries(o.thresholds).forEach(([metric, value]) => {
- hysteresisThresholds[metric] = createHysteresisThreshold(value as number);
- });
- acc[o.id] = hysteresisThresholds;
- return acc;
- }, {} as Record),
- schedule: scheduleRef.getScheduleConfig ? scheduleRef.getScheduleConfig() : {
- quietHours: {
- enabled: false,
- start: "22:00",
- end: "08:00",
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
- days: {
- monday: true,
- tuesday: true,
- wednesday: true,
- thursday: true,
- friday: true,
- saturday: false,
- sunday: false
- }
- },
- cooldown: 5,
- groupingWindow: 30
- },
- // Add missing required fields
- aggregation: {
- enabled: true,
- timeWindow: 10,
- countThreshold: 3,
- similarityWindow: 5.0
- },
- flapping: {
- enabled: true,
- threshold: 5,
- window: 10,
- suppressionTime: 30,
- minStability: 0.8
- },
- ioNormalization: {
- enabled: true,
- vmDiskMax: 500.0,
- containerDiskMax: 300.0,
- networkMax: 1000.0
- }
- };
-
- await AlertsAPI.updateConfig(alertConfig);
-
- // Save email config if it exists (regardless of active tab)
- console.log('Active tab:', activeTab());
- console.log('Has emailConfig:', !!destinationsRef.emailConfig);
- if (destinationsRef.emailConfig) {
- const emailData = destinationsRef.emailConfig();
- console.log('Saving email config:', emailData);
- await NotificationsAPI.updateEmailConfig(emailData);
- }
-
- setHasUnsavedChanges(false);
- showSuccess('Configuration saved successfully!');
- } catch (err) {
- console.error('Failed to save configuration:', err);
- showError(err instanceof Error ? err.message : 'Failed to save configuration');
- }
- }}
- >
- Save Changes
-
- {
- // Reset any changes made
- window.location.reload();
- }}
- >
- Discard
-
-
-
-
-
-
- {/* Tab Navigation - modern style */}
-
-
-
-
- {(tab) => (
- setActiveTab(tab.id)}
- >
- {tab.label}
-
- )}
-
-
-
-
-
- {/* Tab Content */}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/* Custom Rules Tab */}
-
- {}}
- onHasChanges={setHasUnsavedChanges}
- />
-
-
-
-
-
- );
-}
-
-// Overview Tab - Shows current alert status
-function OverviewTab(props: { overrides: Override[]; activeAlerts: Record }) {
- // Loading states for buttons
- const [processingAlerts, setProcessingAlerts] = createSignal>(new Set());
-
- // Get alert stats from actual active alerts
- const alertStats = createMemo(() => {
- const alerts = Object.values(props.activeAlerts);
- return {
- active: alerts.filter(a => !a.acknowledged).length,
- acknowledged: alerts.filter(a => a.acknowledged).length,
- total24h: alerts.length, // In real app, would filter by time
- overrides: props.overrides.length
- };
- });
-
- return (
-
- {/* Stats Cards */}
-
-
-
-
-
Active Alerts
-
{alertStats().active}
-
-
-
-
-
-
-
-
-
Acknowledged
-
{alertStats().acknowledged}
-
-
-
-
-
-
-
-
-
Last 24 Hours
-
{alertStats().total24h}
-
-
-
-
-
-
-
-
-
Guest Overrides
-
{alertStats().overrides}
-
-
-
-
-
-
- {/* Recent Alerts */}
-
-
Active Alerts
-
0}
- fallback={
-
-
No active alerts
-
Alerts will appear here when thresholds are exceeded
-
- }
- >
-
-
- {(alert) => (
-
-
-
-
-
- {alert.resourceName}
-
-
- ({alert.type})
-
-
-
- Acknowledged
-
-
-
-
- {alert.message}
-
-
- Started: {new Date(alert.startTime).toLocaleString()}
-
-
-
-
- {
- setProcessingAlerts(prev => new Set(prev).add(alert.id));
- try {
- await AlertsAPI.acknowledge(alert.id);
- showSuccess('Alert acknowledged');
- } catch (err) {
- console.error('Failed to acknowledge alert:', err);
- showError('Failed to acknowledge alert');
- } finally {
- setProcessingAlerts(prev => {
- const next = new Set(prev);
- next.delete(alert.id);
- return next;
- });
- }
- }}
- >
- {processingAlerts().has(alert.id) ? 'Processing...' : 'Acknowledge'}
-
-
- {
- setProcessingAlerts(prev => new Set(prev).add(alert.id));
- try {
- await AlertsAPI.clearAlert(alert.id);
- showSuccess('Alert cleared');
- } catch (err) {
- console.error('Failed to clear alert:', err);
- showError('Failed to clear alert');
- } finally {
- setProcessingAlerts(prev => {
- const next = new Set(prev);
- next.delete(alert.id);
- return next;
- });
- }
- }}
- >
- {processingAlerts().has(alert.id) ? 'Processing...' : 'Clear'}
-
-
-
-
- )}
-
-
-
-
-
- );
-}
-
-// Add Override Form Component
-function AddOverrideForm(props: {
- guests: Array<{ id: string; name: string; vmid: number; type: string; node: string; instance: string }>;
- nodes: Array<{ id: string; name: string }>;
- existingOverrides: Override[];
- onAdd: (override: Override) => void;
-}) {
- const [resourceType, setResourceType] = createSignal<'guest' | 'node'>('guest');
- const [selectedResource, setSelectedResource] = createSignal('');
- const [thresholds, setThresholds] = createSignal({
- cpu: 80,
- memory: 85,
- disk: 90
- });
- const [enabledThresholds, setEnabledThresholds] = createSignal({
- cpu: false,
- memory: false,
- disk: false
- });
-
- const availableResources = createMemo(() => {
- const existingIds = new Set(props.existingOverrides.map(o => o.id));
-
- if (resourceType() === 'node') {
- return props.nodes.filter(n => !existingIds.has(n.id));
- } else {
- return props.guests.filter(g => !existingIds.has(g.id));
- }
- });
-
- const handleAdd = () => {
- const resourceId = selectedResource();
- if (!resourceId) return;
-
- const activeThresholds: Record = {};
- const thresholdValues = thresholds();
- Object.entries(enabledThresholds()).forEach(([key, enabled]) => {
- if (enabled && key in thresholdValues) {
- activeThresholds[key] = thresholdValues[key as keyof typeof thresholdValues];
- }
- });
-
- if (Object.keys(activeThresholds).length === 0) return;
-
- let newOverride: Override;
-
- if (resourceType() === 'node') {
- const node = props.nodes.find(n => n.id === resourceId);
- if (!node) return;
-
- newOverride = {
- id: node.id,
- name: node.name,
- type: 'node',
- resourceType: 'Node',
- thresholds: activeThresholds
- };
- } else {
- const guest = props.guests.find(g => g.id === resourceId);
- if (!guest) return;
-
- newOverride = {
- id: guest.id,
- name: guest.name,
- type: 'guest',
- resourceType: guest.type === 'qemu' ? 'VM' : 'CT',
- vmid: guest.vmid,
- node: guest.node,
- instance: guest.instance,
- thresholds: activeThresholds
- };
- }
-
- props.onAdd(newOverride);
-
- // Reset form
- setSelectedResource('');
- setThresholds({ cpu: 80, memory: 85, disk: 90 });
- setEnabledThresholds({ cpu: false, memory: false, disk: false });
- };
-
- return (
-
-
-
-
-
- Add New Override
-
-
-
- {/* Resource Selection */}
-
-
-
- Select Resource
-
-
- {/* Resource Type Toggle */}
-
- {
- setResourceType('guest');
- setSelectedResource('');
- }}
- class={`flex-1 py-2 px-4 text-sm font-medium rounded-md transition-colors ${
- resourceType() === 'guest'
- ? 'bg-white dark:bg-gray-800 text-blue-600 dark:text-blue-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200'
- }`}
- >
- Guests
-
- {
- setResourceType('node');
- setSelectedResource('');
- }}
- class={`flex-1 py-2 px-4 text-sm font-medium rounded-md transition-colors ${
- resourceType() === 'node'
- ? 'bg-white dark:bg-gray-800 text-blue-600 dark:text-blue-400 shadow-sm'
- : 'text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200'
- }`}
- >
- Nodes
-
-
-
-
setSelectedResource(e.target.value)}
- class="w-full px-4 py-2.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg
- bg-white dark:bg-gray-700 focus:ring-2 focus:ring-blue-500 focus:border-transparent
- transition-colors"
- >
- Choose a {resourceType()}...
-
- {(resource) => (
-
- {resource.name}
- {resourceType() === 'guest' && 'vmid' in resource && ` (${resource.vmid})`}
-
- )}
-
-
-
-
-
- {/* Threshold Configuration */}
-
-
- Configure Thresholds
-
-
-
- {(metric) => (
-
-
-
- {metric === 'cpu' ? 'CPU' : metric === 'memory' ? 'Memory' : 'Disk'} Usage
-
- {thresholds()[metric as keyof typeof thresholds]}%
-
-
{
- setThresholds({
- ...thresholds(),
- [metric]: value
- });
- // Auto-enable this threshold when value changes
- setEnabledThresholds({
- ...enabledThresholds(),
- [metric]: true
- });
- }}
- type={metric as 'cpu' | 'memory' | 'disk'}
- />
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
- Add Override
-
-
-
-
- );
-}
-
-// Override Item Component
-function OverrideItem(props: {
- override: Override;
- onUpdate: (override: Override) => void;
- onRemove: () => void;
-}) {
- const [editing, setEditing] = createSignal(false);
- const [editValues, setEditValues] = createSignal({ ...props.override.thresholds });
-
- const handleSave = () => {
- props.onUpdate({
- ...props.override,
- thresholds: { ...editValues() }
- });
- setEditing(false);
- };
-
- return (
-
-
-
-
-
- {props.override.name}
-
- ({props.override.vmid})
-
-
-
- {props.override.type === 'node' ? 'Node' : props.override.resourceType}
-
-
-
-
-
-
v)}>
- {([key, value]) => (
-
- {key.toUpperCase()}:
- {value as number}%
-
- )}
-
-
-
-
-
-
-
v)}>
- {([key]) => (
-
-
-
- {key === 'cpu' ? 'CPU' : key === 'memory' ? 'Memory' : 'Disk'} Usage
-
- {editValues()[key as keyof typeof editValues]}%
-
-
setEditValues({
- ...editValues(),
- [key]: value
- })}
- type={key === 'cpu' ? 'cpu' : key === 'memory' ? 'memory' : 'disk'}
- />
-
- )}
-
-
-
-
-
-
-
- {
- setEditValues({ ...props.override.thresholds });
- setEditing(true);
- }}
- class="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400"
- >
- Edit
-
-
- Remove
-
-
-
-
- Save
-
- {
- setEditing(false);
- setEditValues({ ...props.override.thresholds });
- }}
- class="px-3 py-1 text-sm bg-gray-500 text-white rounded hover:bg-gray-600"
- >
- Cancel
-
-
-
-
-
- );
-}
-
-// Thresholds Tab - Improved design
-interface ThresholdsTabProps {
- allGuests: () => Array<{ id: string; name: string; vmid: number; type: string; node: string; instance: string }>;
- state: State;
- guestDefaults: Record;
- nodeDefaults: Record;
- storageDefault: () => number;
- overrides: () => Override[];
- setGuestDefaults: (value: Record | ((prev: Record) => Record)) => void;
- setNodeDefaults: (value: Record | ((prev: Record) => Record)) => void;
- setStorageDefault: (value: number) => void;
- setOverrides: (value: Override[]) => void;
- activeAlerts: Record;
- setHasUnsavedChanges: (value: boolean) => void;
-}
-
-function ThresholdsTab(props: ThresholdsTabProps) {
- return (
-
- {/* Step 1: Global Default Thresholds */}
-
-
-
-
Default Alert Thresholds
-
- These thresholds apply to all resources unless overridden below
-
-
-
{
- props.setGuestDefaults({
- cpu: 80,
- memory: 85,
- disk: 90,
- diskRead: 150,
- diskWrite: 150,
- networkIn: 200,
- networkOut: 200
- });
- props.setNodeDefaults({
- cpu: 80,
- memory: 85,
- disk: 90
- });
- props.setStorageDefault(85);
- // Changed
- }}
- class="text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 font-medium">
- Reset All to Defaults
-
-
-
-
- {/* VMs & Containers */}
-
-
-
-
-
-
-
-
- VMs & Containers
-
-
-
-
-
- CPU Usage
- {props.guestDefaults.cpu}%
-
-
{
- props.setGuestDefaults((prev) => ({...prev, cpu: v}));
- props.setHasUnsavedChanges(true);
- }}
- type="cpu"
- />
-
-
-
-
- Memory Usage
- {props.guestDefaults.memory}%
-
-
{
- props.setGuestDefaults((prev) => ({...prev, memory: v}));
- props.setHasUnsavedChanges(true);
- }}
- type="memory"
- />
-
-
-
-
- Disk Usage
- {props.guestDefaults.disk}%
-
-
{
- props.setGuestDefaults((prev) => ({...prev, disk: v}));
- props.setHasUnsavedChanges(true);
- }}
- type="disk"
- />
-
-
-
-
- {/* Proxmox Nodes */}
-
-
-
-
-
- Proxmox Nodes
-
-
-
-
-
- CPU Usage
- {props.nodeDefaults.cpu}%
-
-
{
- props.setNodeDefaults((prev) => ({...prev, cpu: v}));
- props.setHasUnsavedChanges(true);
- }}
- type="cpu"
- />
-
-
-
-
- Memory Usage
- {props.nodeDefaults.memory}%
-
-
{
- props.setNodeDefaults((prev) => ({...prev, memory: v}));
- props.setHasUnsavedChanges(true);
- }}
- type="memory"
- />
-
-
-
-
- Disk Usage
- {props.nodeDefaults.disk}%
-
-
{
- props.setNodeDefaults((prev) => ({...prev, disk: v}));
- props.setHasUnsavedChanges(true);
- }}
- type="disk"
- />
-
-
-
-
- {/* Storage */}
-
-
-
-
-
-
-
- Storage
-
-
-
-
-
- Usage Threshold
- {props.storageDefault()}%
-
-
{
- props.setStorageDefault(v);
- props.setHasUnsavedChanges(true);
- }}
- type="disk"
- />
-
-
-
-
-
-
- {/* Step 2: Resource-Specific Overrides */}
-
-
-
Custom Overrides
-
- Override default thresholds for specific VMs, containers, or nodes
-
-
-
- {/* Existing Overrides List */}
-
0}>
-
-
- Active Overrides ({props.overrides().length})
-
-
-
- {(override) => (
- {
- props.setOverrides(props.overrides().map((o: Override) =>
- o.id === override.id ? updatedOverride : o
- ));
- // Changed
- }}
- onRemove={() => {
- props.setOverrides(props.overrides().filter((o) => o.id !== override.id));
- // Changed
- }}
- />
- )}
-
-
-
-
-
- {/* Add New Override Form */}
-
-
-
-
-
-
-
-
-
-
Add Custom Override
-
Set different thresholds for a specific resource
-
-
-
-
{
- props.setOverrides([...props.overrides(), override]);
- // Changed
- }}
- />
-
-
-
- );
-}
-
-// Destinations Tab - Notification settings
-interface DestinationsTabProps {
- ref: DestinationsRef;
- hasUnsavedChanges: () => boolean;
- setHasUnsavedChanges: (value: boolean) => void;
- emailConfig: () => UIEmailConfig;
- setEmailConfig: (config: UIEmailConfig) => void;
-}
-
-function DestinationsTab(props: DestinationsTabProps) {
-
- const [webhooks, setWebhooks] = createSignal([]);
- const [testingEmail, setTestingEmail] = createSignal(false);
- const [testingWebhook, setTestingWebhook] = createSignal(null);
-
- // Load webhooks on mount (email config is now loaded in parent)
- onMount(async () => {
- try {
- const hooks = await NotificationsAPI.getWebhooks();
- // Map to local Webhook type
- setWebhooks(hooks.map(h => ({
- ...h,
- service: 'custom' // Default service type
- })));
- } catch (err) {
- console.error('Failed to load webhooks:', err);
- }
- });
-
- const testEmailConfig = async () => {
- setTestingEmail(true);
- try {
- // Don't send config - let backend use saved config which has the actual password
- await NotificationsAPI.testNotification({
- type: 'email'
- // No config - use saved backend config
- });
- alert('Test email sent successfully! Check your inbox.');
- } catch (err) {
- console.error('Failed to send test email:', err);
- alert(`Failed to send test email: ${err instanceof Error ? err.message : 'Unknown error'}`);
- } finally {
- setTestingEmail(false);
- }
- };
-
- const testWebhook = async (webhookId: string) => {
- setTestingWebhook(webhookId);
- try {
- await NotificationsAPI.testNotification({ type: 'webhook', webhookId });
- alert('Test webhook sent successfully!');
- } catch (err) {
- alert(`Failed to send test webhook: ${err instanceof Error ? err.message : 'Unknown error'}`);
- } finally {
- setTestingWebhook(null);
- }
- };
-
- return (
-
- {/* Email Configuration */}
-
-
-
-
-
-
-
- Email Notifications
-
-
- {
- props.setEmailConfig({...props.emailConfig(), enabled: e.currentTarget.checked});
- props.setHasUnsavedChanges(true);
- }}
- class="sr-only peer"
- />
-
-
-
-
-
- {
- props.setEmailConfig(config);
- props.setHasUnsavedChanges(true);
- }}
- onTest={testEmailConfig}
- testing={testingEmail()}
- />
-
-
-
- {/* Webhook Configuration */}
-
-
-
-
-
-
- Webhooks
-
-
-
{
- setWebhooks([...webhooks(), {
- ...webhook,
- id: Date.now().toString()
- }]);
- props.setHasUnsavedChanges(true);
- }}
- onUpdate={(webhook) => {
- setWebhooks(webhooks().map(w =>
- w.id === webhook.id ? webhook : w
- ));
- props.setHasUnsavedChanges(true);
- }}
- onDelete={(id) => {
- setWebhooks(webhooks().filter(w => w.id !== id));
- props.setHasUnsavedChanges(true);
- }}
- onTest={testWebhook}
- testing={testingWebhook()}
- />
-
-
- );
-}
-
-// History Tab - Alert history
-// Schedule Tab - Quiet hours, cooldown, and grouping
-interface ScheduleTabProps {
- ref: ScheduleRef;
- hasUnsavedChanges: () => boolean;
- setHasUnsavedChanges: (value: boolean) => void;
-}
-
-function ScheduleTab(props: ScheduleTabProps) {
- const [quietHours, setQuietHours] = createSignal({
- enabled: false,
- start: '22:00',
- end: '08:00',
- timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC',
- days: {
- monday: true,
- tuesday: true,
- wednesday: true,
- thursday: true,
- friday: true,
- saturday: false,
- sunday: false
- } as Record
- });
-
- const [cooldown, setCooldown] = createSignal({
- enabled: true,
- minutes: 30,
- maxAlerts: 3
- });
-
- const [grouping, setGrouping] = createSignal({
- enabled: true,
- window: 5,
- byNode: true,
- byGuest: false
- });
-
- const [escalation, setEscalation] = createSignal({
- enabled: false,
- levels: [
- { after: 15, notify: 'email' },
- { after: 30, notify: 'webhook' },
- { after: 60, notify: 'all' }
- ]
- });
-
- const timezones = [
- 'UTC',
- 'America/New_York',
- 'America/Chicago',
- 'America/Denver',
- 'America/Los_Angeles',
- 'Europe/London',
- 'Europe/Paris',
- 'Europe/Berlin',
- 'Asia/Tokyo',
- 'Asia/Shanghai',
- 'Australia/Sydney'
- ];
-
- const days = [
- { id: 'monday', label: 'M', fullLabel: 'Monday' },
- { id: 'tuesday', label: 'T', fullLabel: 'Tuesday' },
- { id: 'wednesday', label: 'W', fullLabel: 'Wednesday' },
- { id: 'thursday', label: 'T', fullLabel: 'Thursday' },
- { id: 'friday', label: 'F', fullLabel: 'Friday' },
- { id: 'saturday', label: 'S', fullLabel: 'Saturday' },
- { id: 'sunday', label: 'S', fullLabel: 'Sunday' }
- ];
-
- // Expose schedule config via ref
- if (props.ref) {
- props.ref.getScheduleConfig = () => ({
- quietHours: quietHours(),
- cooldown: cooldown().enabled ? cooldown().minutes : 5,
- groupingWindow: grouping().enabled && grouping().window ? grouping().window * 60 : 30, // Convert minutes to seconds
- maxAlertsHour: cooldown().enabled && cooldown().maxAlerts ? cooldown().maxAlerts : 10,
- escalation: escalation(),
- grouping: grouping()
- });
-
- props.ref.setScheduleConfig = (config: ScheduleConfig) => {
- if (config.quietHours) {
- const qh = config.quietHours;
- setQuietHours(prev => ({
- ...prev,
- ...qh,
- // Ensure timezone is preserved if not provided
- timezone: qh.timezone || prev.timezone
- }));
- }
- if (config.cooldown !== undefined) {
- setCooldown({
- enabled: config.cooldown > 0,
- minutes: config.cooldown,
- maxAlerts: 3
- });
- }
- if (config.groupingWindow !== undefined) {
- const gw = config.groupingWindow;
- setGrouping(prev => ({
- ...prev,
- enabled: gw > 0,
- window: Math.floor(gw / 60), // Convert seconds to minutes
- // Preserve existing grouping preferences
- byNode: config.grouping?.byNode !== undefined ? config.grouping.byNode : prev.byNode,
- byGuest: config.grouping?.byGuest !== undefined ? config.grouping.byGuest : prev.byGuest
- }));
- }
- if (config.maxAlertsHour !== undefined) {
- setCooldown(prev => ({ ...prev, maxAlerts: config.maxAlertsHour! }));
- }
- if (config.escalation !== undefined) {
- setEscalation(prev => ({
- ...prev,
- enabled: config.escalation!.enabled
- }));
- }
- if (config.grouping !== undefined) {
- setGrouping(prev => ({
- ...prev,
- enabled: config.grouping!.enabled,
- window: config.grouping!.window,
- byNode: config.grouping!.byNode ?? prev.byNode,
- byGuest: config.grouping!.byGuest ?? prev.byGuest
- }));
- }
- };
- }
-
- return (
-
- {/* Header */}
-
-
Notification Schedule
-
Control when and how alerts are delivered
-
-
- {/* Quiet Hours */}
-
-
-
-
-
-
Quiet Hours
-
Pause non-critical alerts during specific times
-
-
-
- {
- setQuietHours({ ...quietHours(), enabled: e.currentTarget.checked });
- // Changed
- }}
- class="sr-only peer"
- />
-
-
-
-
-
-
-
-
- Start Time
- {
- setQuietHours({ ...quietHours(), start: e.currentTarget.value });
- // Changed
- }}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-600 dark:border-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- />
-
-
- End Time
- {
- setQuietHours({ ...quietHours(), end: e.currentTarget.value });
- // Changed
- }}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-600 dark:border-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- />
-
-
- Timezone
- {
- setQuietHours({ ...quietHours(), timezone: e.currentTarget.value });
- // Changed
- }}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-600 dark:border-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- >
-
- {(tz) => {tz} }
-
-
-
-
-
-
-
Quiet Days
-
-
- {(day) => (
- {
- const currentDays = quietHours().days;
- setQuietHours({
- ...quietHours(),
- days: { ...currentDays, [day.id]: !currentDays[day.id] }
- });
- // Changed
- }}
- title={day.fullLabel}
- class={`px-2 py-2 text-xs rounded-lg transition-all duration-200 font-medium ${
- quietHours().days[day.id]
- ? 'bg-blue-500 text-white shadow-sm'
- : 'bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-gray-200 dark:hover:bg-gray-600'
- }`}
- >
- {day.label}
-
- )}
-
-
-
-
- Weekdays only
-
-
- Weekends only
-
-
-
-
-
-
-
- {/* Cooldown Period */}
-
-
-
-
-
-
Alert Cooldown
-
Limit alert frequency to prevent spam
-
-
-
- {
- setCooldown({ ...cooldown(), enabled: e.currentTarget.checked });
- // Changed
- }}
- class="sr-only peer"
- />
-
-
-
-
-
-
-
-
-
- Cooldown Period
-
-
- {
- setCooldown({ ...cooldown(), minutes: parseInt(e.currentTarget.value) });
- // Changed
- }}
- class="w-full px-3 py-2 pr-16 text-sm border rounded-lg dark:bg-gray-600 dark:border-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- />
- minutes
-
-
- Minimum time between alerts for the same issue
-
-
-
-
-
- Max Alerts/Hour
-
-
- {
- setCooldown({ ...cooldown(), maxAlerts: parseInt(e.currentTarget.value) });
- // Changed
- }}
- class="w-full px-3 py-2 pr-16 text-sm border rounded-lg dark:bg-gray-600 dark:border-gray-500 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- />
- alerts
-
-
- Per guest/metric combination
-
-
-
-
-
-
-
- {/* Alert Grouping */}
-
-
-
-
-
-
Smart Grouping
-
Bundle similar alerts together
-
-
-
- {
- setGrouping({ ...grouping(), enabled: e.currentTarget.checked });
- // Changed
- }}
- class="sr-only peer"
- />
-
-
-
-
-
-
-
-
- Grouping Window
-
-
-
{
- setGrouping({ ...grouping(), window: parseInt(e.currentTarget.value) });
- // Changed
- }}
- class="flex-1"
- />
-
- {grouping().window} min
-
-
-
- Alerts within this window will be grouped together
-
-
-
-
-
-
-
-
- {/* Escalation Rules */}
-
-
-
-
-
-
Alert Escalation
-
Notify additional contacts for persistent issues
-
-
-
- {
- setEscalation({ ...escalation(), enabled: e.currentTarget.checked });
- // Changed
- }}
- class="sr-only peer"
- />
-
-
-
-
-
-
-
Define escalation levels for unresolved alerts:
-
- {(level, index) => (
-
-
-
- After
- {
- const newLevels = [...escalation().levels];
- newLevels[index()] = { ...level, after: parseInt(e.currentTarget.value) };
- setEscalation({ ...escalation(), levels: newLevels });
- // Changed
- }}
- class="w-16 px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- />
- min
-
-
- notify
- {
- const newLevels = [...escalation().levels];
- newLevels[index()] = { ...level, notify: e.currentTarget.value };
- setEscalation({ ...escalation(), levels: newLevels });
- // Changed
- }}
- class="flex-1 px-2 py-1 text-sm border rounded dark:bg-gray-700 dark:border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
- >
- Email
- Webhooks
- All Channels
-
-
-
-
{
- const newLevels = escalation().levels.filter((_, i) => i !== index());
- setEscalation({ ...escalation(), levels: newLevels });
- // Changed
- }}
- class="p-1.5 text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg transition-colors"
- title="Remove escalation level"
- >
-
-
-
-
-
- )}
-
-
-
{
- const lastLevel = escalation().levels[escalation().levels.length - 1];
- const newAfter = lastLevel ? lastLevel.after + 30 : 15;
- setEscalation({
- ...escalation(),
- levels: [...escalation().levels, { after: newAfter, notify: 'all' }]
- });
- // Changed
- }}
- class="w-full py-2 border-2 border-dashed border-gray-300 dark:border-gray-600 rounded-lg text-sm text-gray-600 dark:text-gray-400 hover:border-gray-400 dark:hover:border-gray-500 hover:bg-gray-50 dark:hover:bg-gray-700 transition-all duration-200 flex items-center justify-center gap-2"
- >
-
-
-
- Add Escalation Level
-
-
-
-
-
- {/* Configuration Summary */}
-
-
-
-
-
- Current Configuration Summary
-
-
-
- • Quiet hours active from {quietHours().start} to {quietHours().end} ({quietHours().timezone})
-
-
- • {cooldown().minutes} minute cooldown between alerts, max {cooldown().maxAlerts} alerts per hour
-
-
- • Grouping alerts within {grouping().window} minute windows
-
- {' '}by {[grouping().byNode && 'node', grouping().byGuest && 'guest'].filter(Boolean).join(' and ')}
-
-
-
-
0}>
- • {escalation().levels.length} escalation level{escalation().levels.length > 1 ? 's' : ''} configured
-
-
- • All notification controls are disabled - alerts will be sent immediately
-
-
-
-
- );
-}
-
-// History Tab - Comprehensive alert table
-function HistoryTab() {
- const { state, activeAlerts } = useWebSocket();
-
- // Filter states with localStorage persistence
- const [timeFilter, setTimeFilter] = createSignal(localStorage.getItem('alertHistoryTimeFilter') || '7d');
- const [severityFilter, setSeverityFilter] = createSignal(localStorage.getItem('alertHistorySeverityFilter') || 'all');
- const [searchTerm, setSearchTerm] = createSignal('');
- const [alertHistory, setAlertHistory] = createSignal([]);
- const [loading, setLoading] = createSignal(true);
- const [selectedBarIndex, setSelectedBarIndex] = createSignal(null);
-
- // Ref for search input
- let searchInputRef: HTMLInputElement | undefined;
-
- // Persist filter changes to localStorage
- createEffect(() => {
- localStorage.setItem('alertHistoryTimeFilter', timeFilter());
- });
-
- createEffect(() => {
- localStorage.setItem('alertHistorySeverityFilter', severityFilter());
- });
-
- // Load alert history on mount
- onMount(async () => {
- try {
- const history = await AlertsAPI.getHistory({ limit: 1000 });
- setAlertHistory(history);
- } catch (err) {
- console.error('Failed to load alert history:', err);
- } finally {
- setLoading(false);
- }
-
- // Add keyboard event listeners
- const handleKeydown = (e: KeyboardEvent) => {
- // If already focused on an input, select, or textarea, don't interfere
- const activeElement = document.activeElement;
- if (activeElement && (
- activeElement.tagName === 'INPUT' ||
- activeElement.tagName === 'TEXTAREA' ||
- activeElement.tagName === 'SELECT'
- )) {
- // Handle Escape to clear and unfocus
- if (e.key === 'Escape' && activeElement === searchInputRef) {
- setSearchTerm('');
- searchInputRef.blur();
- }
- return;
- }
-
- // If typing a letter, number, or space, focus the search input
- if (e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {
- searchInputRef?.focus();
- }
- };
-
- document.addEventListener('keydown', handleKeydown);
-
- // Cleanup on unmount
- return () => {
- document.removeEventListener('keydown', handleKeydown);
- };
- });
-
- // Format duration for display
- const formatDuration = (startTime: string, endTime?: string) => {
- const start = new Date(startTime).getTime();
- const end = endTime ? new Date(endTime).getTime() : Date.now();
- const duration = end - start;
-
- // Handle negative durations (clock skew or timezone issues)
- if (duration < 0) {
- return '0m';
- }
-
- const minutes = Math.floor(duration / 60000);
- const hours = Math.floor(minutes / 60);
- const days = Math.floor(hours / 24);
-
- if (days > 0) return `${days}d ${hours % 24}h`;
- if (hours > 0) return `${hours}h ${minutes % 60}m`;
- return `${minutes}m`;
- };
-
- // Get resource type (VM, CT, Node, Storage)
- const getResourceType = (resourceName: string) => {
- // Check VMs and containers
- const vm = state.vms?.find((v) => v.name === resourceName);
- if (vm) return 'VM';
-
- const container = state.containers?.find((c) => c.name === resourceName);
- if (container) return 'CT';
-
- // Check nodes
- const node = state.nodes?.find((n) => n.name === resourceName);
- if (node) return 'Node';
-
- // Check storage
- const storage = state.storage?.find((s) => s.name === resourceName || s.id === resourceName);
- if (storage) return 'Storage';
-
- return 'Unknown';
- };
-
- // Extended alert type for display
- interface ExtendedAlert extends Alert {
- status?: string;
- duration?: string;
- resourceType?: string;
- }
-
- // Prepare all alerts without filtering
- const allAlertsData = createMemo(() => {
- // Combine active and historical alerts
- const allAlerts: ExtendedAlert[] = [];
-
- // Add active alerts
- Object.values(activeAlerts || {}).forEach((alert) => {
- allAlerts.push({
- ...alert,
- status: 'active',
- duration: formatDuration(alert.startTime),
- resourceType: getResourceType(alert.resourceName)
- });
- });
-
- // Create a set of active alert IDs for quick lookup
- const activeAlertIds = new Set(Object.keys(activeAlerts || {}));
-
- // Add historical alerts
- alertHistory().forEach(alert => {
- // Skip if this alert is already in active alerts (avoid duplicates)
- if (activeAlertIds.has(alert.id)) {
- return;
- }
-
- allAlerts.push({
- ...alert,
- status: alert.acknowledged ? 'acknowledged' : 'resolved',
- duration: formatDuration(alert.startTime, alert.lastSeen),
- resourceType: getResourceType(alert.resourceName)
- });
- });
-
- return allAlerts;
- });
-
- // Apply filters to get the final alert data
- const alertData = createMemo(() => {
- let filtered = allAlertsData();
-
- // Selected bar filter (takes precedence over time filter)
- if (selectedBarIndex() !== null) {
- const trends = alertTrends();
- const index = selectedBarIndex()!;
- const bucketStart = trends.bucketTimes[index];
- const bucketEnd = bucketStart + trends.bucketSize * 60 * 60 * 1000;
-
- filtered = filtered.filter(alert => {
- const alertTime = new Date(alert.startTime).getTime();
- return alertTime >= bucketStart && alertTime < bucketEnd;
- });
- } else {
- // Time filter
- if (timeFilter() !== 'all') {
- const now = Date.now();
- const cutoff = {
- '24h': now - 24 * 60 * 60 * 1000,
- '7d': now - 7 * 24 * 60 * 60 * 1000,
- '30d': now - 30 * 24 * 60 * 60 * 1000
- }[timeFilter()];
-
- if (cutoff) {
- filtered = filtered.filter(a => new Date(a.startTime).getTime() > cutoff);
- }
- }
- }
-
- // Severity filter
- if (severityFilter() !== 'all') {
- filtered = filtered.filter(a => a.level === severityFilter());
- }
-
- // Search filter
- if (searchTerm()) {
- const term = searchTerm().toLowerCase();
- filtered = filtered.filter(alert =>
- alert.resourceName.toLowerCase().includes(term) ||
- alert.message.toLowerCase().includes(term) ||
- alert.type.toLowerCase().includes(term) ||
- alert.node.toLowerCase().includes(term)
- );
- }
-
- // Sort by start time (newest first)
- return filtered.sort((a, b) =>
- new Date(b.startTime).getTime() - new Date(a.startTime).getTime()
- );
- });
-
- // Group alerts by day for display
- const groupedAlerts = createMemo(() => {
- const groups = new Map();
-
- alertData().forEach(alert => {
- const date = new Date(alert.startTime);
- const dayKey = date.toLocaleDateString();
-
- if (!groups.has(dayKey)) {
- groups.set(dayKey, {
- date: date,
- alerts: []
- });
- }
-
- groups.get(dayKey).alerts.push(alert);
- });
-
- // Convert to array and sort by date (newest first)
- return Array.from(groups.values()).sort((a, b) =>
- b.date.getTime() - a.date.getTime()
- );
- });
-
- // Calculate alert trends for mini-chart
- const alertTrends = createMemo(() => {
- const now = Date.now();
- const timeRange = timeFilter() === '24h' ? 24 : timeFilter() === '7d' ? 7 * 24 : timeFilter() === '30d' ? 30 * 24 : 90 * 24; // hours
- const bucketSize = timeFilter() === '24h' ? 1 : timeFilter() === '7d' ? 6 : timeFilter() === '30d' ? 24 : 72; // hours per bucket
- const numBuckets = Math.min(Math.floor(timeRange / bucketSize), 30); // Limit to 30 buckets max
-
- // Calculate start time for the chart
- const startTime = now - timeRange * 60 * 60 * 1000;
-
- // Initialize buckets
- const buckets = new Array(numBuckets).fill(0);
- // bucketTimes represents the START of each bucket
- const bucketTimes = new Array(numBuckets).fill(0).map((_, i) =>
- startTime + i * bucketSize * 60 * 60 * 1000
- );
-
- // Filter alerts based on current time filter
- let alertsToCount = allAlertsData();
- if (timeFilter() !== 'all') {
- const cutoff = {
- '24h': now - 24 * 60 * 60 * 1000,
- '7d': now - 7 * 24 * 60 * 60 * 1000,
- '30d': now - 30 * 24 * 60 * 60 * 1000
- }[timeFilter()];
-
- if (cutoff) {
- alertsToCount = alertsToCount.filter(a => new Date(a.startTime).getTime() > cutoff);
- }
- }
-
- alertsToCount.forEach(alert => {
- const alertTime = new Date(alert.startTime).getTime();
- if (alertTime >= startTime && alertTime <= now) {
- const bucketIndex = Math.floor((alertTime - startTime) / (bucketSize * 60 * 60 * 1000));
- if (bucketIndex >= 0 && bucketIndex < numBuckets) {
- buckets[bucketIndex]++;
- }
- }
- });
-
- // Find max for scaling
- const max = Math.max(...buckets, 1);
-
- return {
- buckets,
- max,
- bucketSize,
- bucketTimes
- };
- });
-
- return (
-
- {/* Alert Trends Mini-Chart */}
-
-
-
- Alert Frequency
- ({alertData().length} alerts)
-
-
-
- setSelectedBarIndex(null)}
- class="px-2 py-0.5 text-xs bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 rounded hover:bg-blue-200 dark:hover:bg-blue-800/50 transition-colors"
- >
- Clear filter
-
-
-
-
-
- {alertData().filter(a => a.level === 'warning').length} warnings
-
-
-
- {alertData().filter(a => a.level === 'critical').length} critical
-
-
-
-
-
- {/* Mini sparkline chart */}
-
- Showing {alertTrends().buckets.length} time periods - Total: {alertData().length} alerts
-
-
- {/* Alert frequency chart */}
-
- {alertTrends().buckets.map((val, i) => {
- const scaledHeight = val > 0 ? Math.min(100, Math.max(20, Math.log(val + 1) * 20)) : 0;
- const pixelHeight = val > 0 ? Math.max(8, (scaledHeight / 100) * 40) : 0; // 40px is roughly the inner height
- const isSelected = selectedBarIndex() === i;
- return (
-
setSelectedBarIndex(i === selectedBarIndex() ? null : i)}
- >
- {/* Background track for all slots */}
-
- {/* Actual bar */}
-
0 ? (isSelected ? '#2563eb' : '#3b82f6') : 'transparent',
- 'opacity': isSelected ? '1' : '0.8',
- 'box-shadow': isSelected ? '0 0 0 2px rgba(37, 99, 235, 0.4)' : 'none'
- }}
- title={`${val} alert${val !== 1 ? 's' : ''}`}
- >
- {/* Tooltip on hover */}
-
-
-
- );
- })}
-
-
- {/* Time labels */}
-
- {timeFilter() === '24h' ? '24h ago' : timeFilter() === '7d' ? '7d ago' : timeFilter() === '30d' ? '30d ago' : '90d ago'}
- Now
-
-
-
- {/* Filters */}
-
-
setTimeFilter(e.currentTarget.value)}
- class="px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600">
- Last 24h
- Last 7d
- Last 30d
- All Time
-
-
-
setSeverityFilter(e.currentTarget.value)}
- class="px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600">
- All Levels
- Critical Only
- Warning Only
-
-
-
- setSearchTerm(e.currentTarget.value)}
- onKeyDown={(e) => {
- if (e.key === 'Escape') {
- setSearchTerm('');
- e.currentTarget.blur();
- }
- }}
- class="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600
- dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-500"
- />
-
-
-
- {/* Alert History Table */}
-
0}
- fallback={
-
-
No alerts found
-
Try adjusting your filters or check back later
-
- }
- >
- {/* Table */}
-
-
-
-
-
- Timestamp
- Resource
- Type
- Severity
- Message
- Duration
- Status
- Node
-
-
-
-
- {(group) => (
- <>
- {/* Date divider */}
-
-
- {group.date.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' })}
-
-
-
- {/* Alerts for this day */}
-
- {(alert) => (
-
- {/* Timestamp */}
-
- {new Date(alert.startTime).toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' })}
-
-
- {/* Resource */}
-
- {alert.resourceName}
-
-
- {/* Type */}
-
-
- {alert.type}
-
-
-
- {/* Severity */}
-
-
- {alert.level}
-
-
-
- {/* Message */}
-
- {alert.message}
-
-
- {/* Duration */}
-
- {alert.duration}
-
-
- {/* Status */}
-
-
- {alert.status}
-
-
-
- {/* Node */}
-
- {alert.node || '—'}
-
-
- )}
-
- >
- )}
-
-
-
-
-
-
- }
- >
-
-
Loading alert history...
-
-
-
- {/* Administrative Actions - Only show if there's history to clear */}
-
0}>
-
-
-
-
-
- Administrative Actions
-
-
- Permanently clear all alert history. Use with caution - this action cannot be undone.
-
-
-
{
- if (confirm('Are you sure you want to clear all alert history?\n\nThis will permanently delete all historical alert data and cannot be undone.\n\nThis is typically only used for system maintenance or when starting fresh with a new monitoring setup.')) {
- try {
- await AlertsAPI.clearHistory();
- setAlertHistory([]);
- console.log('Alert history cleared successfully');
- } catch (err) {
- console.error('Error clearing alert history:', err);
- alert('Error clearing alert history. Please check your connection and try again.');
- }
- }
- }}
- class="px-3 py-2 text-xs border border-red-300 dark:border-red-600 text-red-600 dark:text-red-400
- rounded-md hover:bg-red-50 dark:hover:bg-red-900/20 transition-colors flex-shrink-0"
- >
- Clear All History
-
-
-
-
-
-
- );
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/stores/websocket-global.ts b/pulse-test-staging/frontend-modern/src/stores/websocket-global.ts
deleted file mode 100644
index 26400c187..000000000
--- a/pulse-test-staging/frontend-modern/src/stores/websocket-global.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { createWebSocketStore } from './websocket';
-
-// Store the instance on window to survive hot reloads
-declare global {
- interface Window {
- __pulseWsStore?: ReturnType;
- }
-}
-
-export function getGlobalWebSocketStore() {
- if (!window.__pulseWsStore) {
- const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
- // Use relative URL that works behind proxies
- const wsUrl = `${protocol}//${window.location.host}/ws`;
-
- window.__pulseWsStore = createWebSocketStore(wsUrl);
- }
-
- return window.__pulseWsStore;
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/stores/websocket.ts b/pulse-test-staging/frontend-modern/src/stores/websocket.ts
deleted file mode 100644
index 01207af2d..000000000
--- a/pulse-test-staging/frontend-modern/src/stores/websocket.ts
+++ /dev/null
@@ -1,258 +0,0 @@
-import { createSignal, onCleanup } from 'solid-js';
-import { createStore } from 'solid-js/store';
-import type { State, WSMessage, Alert, ResolvedAlert, PVEBackups } from '@/types/api';
-import { logger } from '@/utils/logger';
-import { POLLING_INTERVALS, WEBSOCKET } from '@/constants';
-
-// Type-safe WebSocket store
-export function createWebSocketStore(url: string) {
- const [connected, setConnected] = createSignal(false);
- const [reconnecting, setReconnecting] = createSignal(false);
- const [initialDataReceived, setInitialDataReceived] = createSignal(false);
- const [state, setState] = createStore({
- nodes: [],
- vms: [],
- containers: [],
- storage: [],
- pbs: [],
- metrics: [],
- pveBackups: {
- backupTasks: [],
- storageBackups: [],
- guestSnapshots: []
- } as PVEBackups,
- pbsBackups: [],
- performance: {
- apiCallDuration: {},
- lastPollDuration: 0,
- pollingStartTime: '',
- totalApiCalls: 0,
- failedApiCalls: 0,
- cacheHits: 0,
- cacheMisses: 0
- },
- connectionHealth: {},
- stats: {
- startTime: new Date().toISOString(),
- uptime: 0,
- pollingCycles: 0,
- webSocketClients: 0,
- version: '2.0.0'
- },
- activeAlerts: [],
- recentlyResolved: [],
- lastUpdate: ''
- });
- const [activeAlerts, setActiveAlerts] = createStore>({});
- const [recentlyResolved, setRecentlyResolved] = createStore>({});
- const [updateProgress, setUpdateProgress] = createSignal(null);
-
- let ws: WebSocket | null = null;
- let reconnectTimeout: number;
- let reconnectAttempt = 0;
- let isReconnecting = false;
- const maxReconnectDelay = POLLING_INTERVALS.RECONNECT_MAX;
- const initialReconnectDelay = POLLING_INTERVALS.RECONNECT_BASE;
-
- const connect = () => {
- try {
- // Close existing connection if any
- if (ws && ws.readyState !== WebSocket.CLOSED) {
- ws.close();
- }
-
- ws = new WebSocket(url);
-
- ws.onopen = () => {
- logger.debug('connect');
- setConnected(true);
- setReconnecting(false); // Clear reconnecting state
- reconnectAttempt = 0; // Reset reconnect attempts on successful connection
-
- // Alerts will come with the initial state broadcast
- };
-
- ws.onmessage = (event) => {
- try {
- const data = JSON.parse(event.data);
-
- const message: WSMessage = data;
-
- if (message.type === WEBSOCKET.MESSAGE_TYPES.INITIAL_STATE || message.type === WEBSOCKET.MESSAGE_TYPES.RAW_DATA) {
- // Update state properties individually to ensure reactivity
- if (message.data) {
- // Mark that we've received initial data
- if (message.type === WEBSOCKET.MESSAGE_TYPES.INITIAL_STATE) {
- setInitialDataReceived(true);
- }
-
- // Only update if we have actual data, don't overwrite with empty arrays
- if (message.data.nodes !== undefined) setState('nodes', message.data.nodes);
- if (message.data.vms !== undefined) setState('vms', message.data.vms);
- if (message.data.containers !== undefined) setState('containers', message.data.containers);
- if (message.data.storage !== undefined) setState('storage', message.data.storage);
- if (message.data.pbs !== undefined) setState('pbs', message.data.pbs);
- if (message.data.pbsBackups !== undefined) setState('pbsBackups', message.data.pbsBackups);
- if (message.data.metrics !== undefined) setState('metrics', message.data.metrics);
- if (message.data.pveBackups !== undefined) setState('pveBackups', message.data.pveBackups);
- if (message.data.performance !== undefined) setState('performance', message.data.performance);
- if (message.data.connectionHealth !== undefined) setState('connectionHealth', message.data.connectionHealth);
- if (message.data.stats !== undefined) setState('stats', message.data.stats);
- // Sync active alerts from state
- if (message.data.activeAlerts !== undefined) {
- console.log('[WebSocket] Received activeAlerts:', message.data.activeAlerts);
-
- // First, remove all existing alerts
- const currentAlertIds = Object.keys(activeAlerts);
- currentAlertIds.forEach(id => {
- setActiveAlerts(id, undefined!);
- });
-
- // Then add the new alerts
- message.data.activeAlerts.forEach((alert: Alert) => {
- setActiveAlerts(alert.id, alert);
- });
-
- console.log('[WebSocket] Updated activeAlerts to:', activeAlerts);
- }
- // Sync recently resolved alerts
- if (message.data.recentlyResolved !== undefined) {
- console.log('[WebSocket] Received recentlyResolved:', message.data.recentlyResolved);
-
- // First, remove all existing resolved alerts
- const currentResolvedIds = Object.keys(recentlyResolved);
- currentResolvedIds.forEach(id => {
- setRecentlyResolved(id, undefined!);
- });
-
- // Then add the new resolved alerts
- message.data.recentlyResolved.forEach((alert: ResolvedAlert) => {
- setRecentlyResolved(alert.id, alert);
- });
-
- console.log('[WebSocket] Updated recentlyResolved to:', recentlyResolved);
- }
- setState('lastUpdate', message.data.lastUpdate || new Date().toISOString());
- }
- logger.debug('message', {
- type: message.type,
- hasData: !!message.data,
- nodeCount: message.data?.nodes?.length || 0,
- vmCount: message.data?.vms?.length || 0,
- containerCount: message.data?.containers?.length || 0
- });
- } else if (message.type === WEBSOCKET.MESSAGE_TYPES.ERROR) {
- logger.debug('error', message.error);
- } else if (message.type === 'ping') {
- // Respond to ping with pong
- if (ws && ws.readyState === WebSocket.OPEN) {
- ws.send(JSON.stringify({ type: 'pong', data: { timestamp: Date.now() } }));
- }
- } else if (message.type === 'pong') {
- // Server acknowledged our ping
- logger.debug('Received pong from server');
- } else if (message.type === 'welcome') {
- // Welcome message from server
- logger.info('WebSocket connection established');
- } else if (message.type === 'alert') {
- // Individual alerts now handled via state sync
- logger.warn('New alert received (will sync with next state update)', message.data);
- } else if (message.type === 'alertResolved') {
- // Individual alert resolution now handled via state sync
- logger.info('Alert resolved (will sync with next state update)', { alertId: message.data.alertId });
- } else if (message.type === 'update:progress') {
- // Update progress event
- setUpdateProgress(message.data);
- logger.info('Update progress:', message.data);
- }
- } catch (err) {
- logger.error('Failed to parse WebSocket message', err);
- }
- };
-
- ws.onclose = (event) => {
- logger.debug('disconnect', { code: event.code, reason: event.reason });
- setConnected(false);
- setInitialDataReceived(false);
-
- // Don't reconnect if we're already trying
- if (isReconnecting) {
- return;
- }
-
- isReconnecting = true;
- setReconnecting(true);
-
- // Calculate exponential backoff delay
- const delay = Math.min(
- initialReconnectDelay * Math.pow(2, reconnectAttempt),
- maxReconnectDelay
- );
-
- logger.info(`Reconnecting in ${delay}ms (attempt ${reconnectAttempt + 1})`);
- reconnectAttempt++;
-
- reconnectTimeout = window.setTimeout(() => {
- isReconnecting = false;
- setReconnecting(false);
- connect();
- }, delay);
- };
-
- ws.onerror = (error) => {
- // Don't log connection errors if we're already connected
- // Browser may show errors for initial connection attempts even after success
- if (!connected()) {
- logger.debug('error', error);
- }
- };
- } catch (err) {
- logger.error('Failed to connect', err);
- setConnected(false);
-
- // Don't reconnect if we're already trying
- if (isReconnecting) return;
-
- isReconnecting = true;
- setReconnecting(true);
-
- // Use exponential backoff for connection errors too
- const delay = Math.min(
- initialReconnectDelay * Math.pow(2, reconnectAttempt),
- maxReconnectDelay
- );
-
- reconnectAttempt++;
- reconnectTimeout = window.setTimeout(() => {
- isReconnecting = false;
- setReconnecting(false);
- connect();
- }, delay);
- }
- };
-
- // Connect immediately
- connect();
-
- // Cleanup on unmount
- onCleanup(() => {
- window.clearTimeout(reconnectTimeout);
- ws?.close();
- });
-
- return {
- state,
- activeAlerts,
- recentlyResolved,
- connected,
- reconnecting,
- initialDataReceived,
- updateProgress,
- reconnect: () => {
- ws?.close();
- window.clearTimeout(reconnectTimeout);
- reconnectAttempt = 0; // Reset attempts for manual reconnect
- connect();
- }
- };
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/types/alerts.ts b/pulse-test-staging/frontend-modern/src/types/alerts.ts
deleted file mode 100644
index e1d01be36..000000000
--- a/pulse-test-staging/frontend-modern/src/types/alerts.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import type { FilterStack } from '@/utils/searchQuery';
-
-export interface HysteresisThreshold {
- trigger: number;
- clear: number;
-}
-
-export interface AlertThresholds {
- cpu?: HysteresisThreshold;
- memory?: HysteresisThreshold;
- disk?: HysteresisThreshold;
- diskRead?: HysteresisThreshold;
- diskWrite?: HysteresisThreshold;
- networkIn?: HysteresisThreshold;
- networkOut?: HysteresisThreshold;
- // Legacy support for backward compatibility
- cpuLegacy?: number;
- memoryLegacy?: number;
- diskLegacy?: number;
- diskReadLegacy?: number;
- diskWriteLegacy?: number;
- networkInLegacy?: number;
- networkOutLegacy?: number;
- // Allow indexing with string
- [key: string]: HysteresisThreshold | number | undefined;
-}
-
-export interface CustomAlertRule {
- id: string;
- name: string;
- description?: string;
- filterConditions: FilterStack;
- thresholds: AlertThresholds;
- priority: number;
- enabled: boolean;
- notifications: {
- email?: {
- enabled: boolean;
- recipients: string[];
- };
- webhook?: {
- enabled: boolean;
- url: string;
- };
- };
- createdAt: string;
- updatedAt: string;
-}
-
-export interface AlertConfig {
- enabled: boolean;
- guestDefaults: AlertThresholds;
- nodeDefaults: AlertThresholds;
- storageDefault: HysteresisThreshold;
- customRules?: CustomAlertRule[];
- overrides: Record; // key: resource ID
- minimumDelta?: number;
- suppressionWindow?: number;
- hysteresisMargin?: number;
- notifications?: {
- email?: {
- server: string;
- port: number;
- username: string;
- password: string;
- from: string;
- tls: boolean;
- };
- webhooks?: Array<{
- id: string;
- name: string;
- url: string;
- enabled: boolean;
- }>;
- };
- schedule?: {
- enabled?: boolean;
- quietHours?: {
- enabled: boolean;
- start: string;
- end: string;
- days: number[] | Record;
- };
- cooldown?: number;
- groupingWindow?: number;
- };
-}
-
-// Priority levels:
-// 0: Global defaults
-// 1-99: Reserved for system rules
-// 100+: Custom user rules
-// 1000+: Guest-specific overrides
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/types/api.ts b/pulse-test-staging/frontend-modern/src/types/api.ts
deleted file mode 100644
index 502f59ffb..000000000
--- a/pulse-test-staging/frontend-modern/src/types/api.ts
+++ /dev/null
@@ -1,332 +0,0 @@
-// Properly typed TypeScript interfaces for Pulse API
-
-export interface State {
- nodes: Node[];
- vms: VM[];
- containers: Container[];
- storage: Storage[];
- pbs: PBSInstance[];
- pbsBackups: PBSBackup[];
- metrics: Metric[];
- pveBackups: PVEBackups;
- performance: Performance;
- connectionHealth: Record;
- stats: Stats;
- activeAlerts: Alert[];
- recentlyResolved: ResolvedAlert[];
- lastUpdate: string;
-}
-
-export interface Node {
- id: string;
- name: string;
- instance: string;
- status: string;
- type: string;
- cpu: number;
- memory: Memory;
- disk: Disk;
- uptime: number;
- loadAverage: number[];
- kernelVersion: string;
- pveVersion: string;
- cpuInfo: CPUInfo;
- lastSeen: string;
- connectionHealth: string;
-}
-
-export interface VM {
- id: string;
- vmid: number;
- name: string;
- node: string;
- instance: string;
- status: string;
- type: string;
- cpu: number;
- cpus: number;
- memory: Memory;
- disk: Disk;
- networkIn: number;
- networkOut: number;
- diskRead: number;
- diskWrite: number;
- uptime: number;
- template: boolean;
- lastBackup: string;
- tags: string[];
- lock: string;
- lastSeen: string;
-}
-
-export interface Container {
- id: string;
- vmid: number;
- name: string;
- node: string;
- instance: string;
- status: string;
- type: string;
- cpu: number;
- cpus: number;
- memory: Memory;
- disk: Disk;
- networkIn: number;
- networkOut: number;
- diskRead: number;
- diskWrite: number;
- uptime: number;
- template: boolean;
- lastBackup: string;
- tags: string[];
- lock: string;
- lastSeen: string;
-}
-
-export interface Storage {
- id: string;
- name: string;
- node: string;
- instance: string;
- type: string;
- status: string;
- total: number;
- used: number;
- free: number;
- usage: number;
- content: string;
- shared: boolean;
- enabled: boolean;
- active: boolean;
-}
-
-export interface PBSInstance {
- id: string;
- name: string;
- host: string;
- status: string;
- version: string;
- datastores: PBSDatastore[];
- backupJobs: PBSBackupJob[];
- syncJobs: PBSSyncJob[];
- verifyJobs: PBSVerifyJob[];
- pruneJobs: PBSPruneJob[];
- garbageJobs: PBSGarbageJob[];
- connectionHealth: string;
- lastSeen: string;
-}
-
-export interface PBSDatastore {
- name: string;
- total: number;
- used: number;
- free: number;
- usage: number;
- status: string;
- error: string;
- namespaces: PBSNamespace[];
-}
-
-export interface PBSNamespace {
- path: string;
- parent: string;
- depth: number;
-}
-
-export interface PBSBackup {
- id: string;
- instance: string;
- datastore: string;
- namespace: string;
- backupType: string;
- vmid: string;
- backupTime: string;
- size: number;
- protected: boolean;
- verified: boolean;
- comment: string;
- files: string[];
-}
-
-export interface PBSBackupJob {
- id: string;
- store: string;
- type: string;
- vmid: string;
- lastBackup: string;
- nextRun: string;
- status: string;
- error: string;
-}
-
-export interface PBSSyncJob {
- id: string;
- store: string;
- remote: string;
- status: string;
- lastSync: string;
- nextRun: string;
- error: string;
-}
-
-export interface PBSVerifyJob {
- id: string;
- store: string;
- status: string;
- lastVerify: string;
- nextRun: string;
- error: string;
-}
-
-export interface PBSPruneJob {
- id: string;
- store: string;
- status: string;
- lastPrune: string;
- nextRun: string;
- error: string;
-}
-
-export interface PBSGarbageJob {
- id: string;
- store: string;
- status: string;
- lastGarbage: string;
- nextRun: string;
- removedBytes: number;
- error: string;
-}
-
-export interface Memory {
- total: number;
- used: number;
- free: number;
- usage: number;
-}
-
-export interface Disk {
- total: number;
- used: number;
- free: number;
- usage: number;
-}
-
-export interface CPUInfo {
- model: string;
- cores: number;
- sockets: number;
- mhz: string;
-}
-
-export interface Metric {
- timestamp: string;
- type: string;
- id: string;
- values: Record;
-}
-
-export interface BackupTask {
- id: string;
- node: string;
- type: string;
- vmid: number;
- status: string;
- startTime: string;
- endTime?: string;
- size?: number;
- error?: string;
-}
-
-export interface StorageBackup {
- id: string;
- storage: string;
- node: string;
- type: string;
- vmid: number;
- time: string;
- ctime: number;
- size: number;
- format: string;
- notes?: string;
- protected: boolean;
- volid: string;
- isPBS: boolean;
- verified: boolean;
- verification?: string;
-}
-
-export interface PVEBackups {
- backupTasks: BackupTask[];
- storageBackups: StorageBackup[];
- guestSnapshots: GuestSnapshot[];
-}
-
-export interface GuestSnapshot {
- id: string;
- name: string;
- node: string;
- type: string;
- vmid: number;
- time: string;
- description: string;
- parent: string;
- vmstate: boolean;
-}
-
-export interface Performance {
- apiCallDuration: Record;
- lastPollDuration: number;
- pollingStartTime: string;
- totalApiCalls: number;
- failedApiCalls: number;
- cacheHits?: number;
- cacheMisses?: number;
-}
-
-export interface Stats {
- startTime: string;
- uptime: number;
- pollingCycles: number;
- webSocketClients: number;
- version: string;
-}
-
-// Alert types
-export interface Alert {
- id: string;
- type: string;
- level: 'warning' | 'critical';
- resourceId: string;
- resourceName: string;
- node: string;
- instance: string;
- message: string;
- value: number;
- threshold: number;
- startTime: string;
- lastSeen?: string;
- acknowledged: boolean;
- ackTime?: string;
- ackUser?: string;
- metadata?: Record;
-}
-
-export interface ResolvedAlert extends Alert {
- resolvedTime: string;
-}
-
-// WebSocket message types
-export type WSMessage =
- | { type: 'initialState'; data: State }
- | { type: 'rawData'; data: State }
- | { type: 'error'; error: string }
- | { type: 'ping'; data?: unknown }
- | { type: 'pong'; data?: unknown }
- | { type: 'welcome'; data?: unknown }
- | { type: 'alert'; data: Alert }
- | { type: 'alertResolved'; data: { alertId: string } }
- | { type: 'update:progress'; data: any };
-
-// Utility types
-export type Status = 'running' | 'stopped' | 'paused' | 'unknown';
-export type GuestType = 'qemu' | 'lxc';
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/types/backups.ts b/pulse-test-staging/frontend-modern/src/types/backups.ts
deleted file mode 100644
index 3d9742377..000000000
--- a/pulse-test-staging/frontend-modern/src/types/backups.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-// Unified backup types for the backup view
-
-export interface UnifiedBackup {
- // Common fields
- backupType: 'backup' | 'snapshot' | 'pbs';
- vmid: number;
- name: string;
- type: 'VM' | 'LXC' | 'CT';
- node: string;
- backupTime: number; // Unix timestamp in seconds
- backupName: string;
- description: string;
- status: string;
- size: number | null;
- storage: string | null;
-
- // PBS specific
- datastore: string | null;
- namespace: string | null;
- verified: boolean | null;
-
- // Common flags
- protected: boolean;
-
- // UI specific
- instance?: string;
- isPBS?: boolean;
-}
-
-// PBS-specific backup file info
-export interface PBSBackupFile {
- filename: string;
- size: number;
- crypt?: string;
-}
-
-// Extended PBS backup with file details
-export interface PBSBackupWithFiles {
- id: string;
- instance: string;
- datastore: string;
- namespace?: string;
- backupType: string;
- vmid: number;
- backupTime: string;
- size: number;
- protected: boolean;
- verified: boolean;
- comment?: string;
- files: PBSBackupFile[];
-}
-
-// PBS datastore with snapshots
-export interface PBSDatastoreSnapshot {
- id: string;
- backupTime: string;
- size: number;
- owner?: string;
- verified?: boolean;
- protected?: boolean;
- files?: PBSBackupFile[];
-}
-
-export interface PBSDatastore {
- name: string;
- total: number;
- used: number;
- free: number;
- snapshots: PBSDatastoreSnapshot[];
-}
-
-export interface PBSInstanceData {
- id: string;
- name: string;
- host: string;
- backups: PBSBackupWithFiles[];
- datastores: PBSDatastore[];
-}
-
-// Filter options for the backup view
-export interface BackupFilters {
- instance: string;
- type: 'all' | 'VM' | 'LXC';
- node: string;
- storage: string;
- protected: 'all' | 'protected' | 'unprotected';
- verified: 'all' | 'verified' | 'unverified';
-}
-
-// Sorting options
-export interface BackupSort {
- key: keyof UnifiedBackup;
- order: 'asc' | 'desc';
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/types/monitoring.ts b/pulse-test-staging/frontend-modern/src/types/monitoring.ts
deleted file mode 100644
index 3871c9c21..000000000
--- a/pulse-test-staging/frontend-modern/src/types/monitoring.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-// Monitoring data types
-
-export interface CPUInfo {
- usage: number;
- cores: number;
- sockets: number;
- model: string;
-}
-
-export interface MemoryInfo {
- used: number;
- total: number;
- free: number;
- usage: number;
-}
-
-export interface DiskInfo {
- used: number;
- total: number;
- free: number;
- usage: number;
- device?: string;
- filesystem?: string;
-}
-
-export interface NetworkInfo {
- in: number;
- out: number;
- device?: string;
-}
-
-export interface Node {
- id: string;
- name: string;
- type: string;
- status: 'online' | 'offline' | 'unknown';
- instance: string;
- uptime: number;
- cpu: CPUInfo;
- memory: MemoryInfo;
- disk?: DiskInfo;
- network?: NetworkInfo;
- loadAverage?: [number, number, number];
- kernelVersion?: string;
-}
-
-export interface Guest {
- id: string;
- vmid: number;
- name: string;
- node: string;
- type: 'qemu' | 'lxc';
- status: 'running' | 'stopped' | 'paused' | 'suspended';
- instance: string;
- uptime?: number;
- cpu: {
- usage: number;
- cores: number;
- limit?: number;
- };
- memory: {
- used: number;
- total: number;
- usage: number;
- };
- disk: {
- read: number;
- write: number;
- used?: number;
- total?: number;
- };
- network: {
- in: number;
- out: number;
- };
- template?: boolean;
- haState?: string;
- protection?: boolean;
- tags?: string[];
-}
-
-export type VM = Guest & { type: 'qemu' };
-export type Container = Guest & { type: 'lxc' };
-
-export interface Storage {
- id: string;
- name: string;
- type: string;
- status: 'online' | 'offline' | 'unknown';
- node: string;
- instance: string;
- used: number;
- total: number;
- available: number;
- usage: number;
- content: string[];
- shared?: boolean;
- enabled?: boolean;
-}
-
-export interface Backup {
- id: string;
- vmid: number;
- name: string;
- type: 'VM' | 'CT';
- size: number;
- backupTime: number;
- node: string;
- storage?: string;
- instance: string;
- notes?: string;
- protected?: boolean;
- encrypted?: boolean;
- verified?: boolean;
- format?: string;
-}
-
-export interface PBSBackup extends Backup {
- datastore: string;
- snapshotTime: number;
- owner?: string;
- fingerprint?: string;
-}
-
-export interface Alert {
- id: string;
- resourceId: string;
- resourceName: string;
- node: string;
- instance: string;
- type: string;
- level: 'warning' | 'critical';
- message: string;
- value: number;
- threshold: number;
- startTime: string;
- lastSeen?: string;
- acknowledged: boolean;
- acknowledgedBy?: string;
- acknowledgedAt?: string;
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/types/nodes.ts b/pulse-test-staging/frontend-modern/src/types/nodes.ts
deleted file mode 100644
index 27f79b0fc..000000000
--- a/pulse-test-staging/frontend-modern/src/types/nodes.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-// Node configuration types
-
-export interface ClusterEndpoint {
- NodeID: string;
- NodeName: string;
- Host: string;
- IP: string;
- Online: boolean;
- LastSeen: string;
-}
-
-export interface PVENodeConfig {
- id: string;
- name: string;
- host: string;
- user: string;
- hasPassword?: boolean;
- hasToken?: boolean;
- tokenName?: string;
- tokenValue?: string;
- password?: string;
- verifySSL: boolean;
- monitorVMs: boolean;
- monitorContainers: boolean;
- monitorStorage: boolean;
- monitorBackups: boolean;
- // Cluster information
- isCluster?: boolean;
- clusterName?: string;
- clusterEndpoints?: ClusterEndpoint[];
-}
-
-export interface PBSNodeConfig {
- id: string;
- name: string;
- host: string;
- user: string;
- hasPassword?: boolean;
- hasToken?: boolean;
- tokenName?: string;
- tokenValue?: string;
- password?: string;
- fingerprint?: string;
- verifySSL: boolean;
- monitorDatastores: boolean;
- monitorSyncJobs: boolean;
- monitorVerifyJobs: boolean;
- monitorPruneJobs: boolean;
- monitorGarbageJobs: boolean;
-}
-
-export type NodeConfig = (PVENodeConfig | PBSNodeConfig) & {
- type: 'pve' | 'pbs';
- status?: 'connected' | 'disconnected' | 'error';
-};
-
-export interface NodesResponse {
- pve_instances: PVENodeConfig[];
- pbs_instances: PBSNodeConfig[];
-}
-
-export interface NodeUpdateRequest {
- node: NodeConfig;
-}
-
-export interface NodeDeleteResponse {
- success: boolean;
- message: string;
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/types/settings.ts b/pulse-test-staging/frontend-modern/src/types/settings.ts
deleted file mode 100644
index 54499de2a..000000000
--- a/pulse-test-staging/frontend-modern/src/types/settings.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-// Settings API Types - Keep in sync with Go backend
-
-export interface ServerSettings {
- backend: {
- port: number;
- host: string;
- };
- frontend: {
- port: number;
- host: string;
- };
-}
-
-export interface MonitoringSettings {
- pollingInterval: number;
- concurrentPolling: boolean;
- backupPollingCycles: number;
- metricsRetentionDays: number;
-}
-
-export interface LoggingSettings {
- level: string;
- file: string;
- maxSize: number;
- maxBackups: number;
- maxAge: number;
- compress: boolean;
-}
-
-export interface SecuritySettings {
- apiToken: string;
- allowedOrigins: string[];
- iframeEmbedding: string;
- enableAuthentication: boolean;
-}
-
-export interface Settings {
- server: ServerSettings;
- monitoring: MonitoringSettings;
- logging: LoggingSettings;
- security: SecuritySettings;
-}
-
-export interface SettingsCapabilities {
- canRestart: boolean;
- canValidatePorts: boolean;
- requiresRestart: boolean;
-}
-
-export interface SettingsResponse {
- current: Settings;
- defaults: Settings;
- capabilities: SettingsCapabilities;
-}
-
-export interface SettingsUpdateRequest {
- server?: Partial;
- monitoring?: Partial;
- logging?: Partial;
- security?: Partial;
-}
-
-export interface SettingsUpdateResponse {
- success: boolean;
- requiresRestart: boolean;
- message?: string;
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/utils/alerts.ts b/pulse-test-staging/frontend-modern/src/utils/alerts.ts
deleted file mode 100644
index 146e4aefe..000000000
--- a/pulse-test-staging/frontend-modern/src/utils/alerts.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import type { Alert } from '@/types/api';
-
-// Get alert highlighting styles based on active alerts for a resource
-export const getAlertStyles = (
- resourceId: string,
- activeAlerts: Record
-) => {
- // Find the highest severity alert for this resource
- let highestSeverity: 'critical' | 'warning' | null = null;
- let alertCount = 0;
-
- Object.values(activeAlerts).forEach(alert => {
- if (alert.resourceId === resourceId) {
- alertCount++;
- if (alert.level === 'critical' || (alert.level === 'warning' && highestSeverity !== 'critical')) {
- highestSeverity = alert.level;
- }
- }
- });
-
- // Return appropriate styling based on alert severity
- if (highestSeverity === 'critical') {
- return {
- rowClass: 'bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500',
- indicatorClass: 'bg-red-500',
- badgeClass: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200',
- hasAlert: true,
- alertCount,
- severity: 'critical' as const
- };
- }
-
- if (highestSeverity === 'warning') {
- return {
- rowClass: 'bg-orange-50 dark:bg-orange-900/20 border-l-4 border-orange-500',
- indicatorClass: 'bg-orange-500',
- badgeClass: 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-200',
- hasAlert: true,
- alertCount,
- severity: 'warning' as const
- };
- }
-
- return {
- rowClass: '',
- indicatorClass: '',
- badgeClass: '',
- hasAlert: false,
- alertCount: 0,
- severity: null
- };
-};
-
-// Get alert messages for a specific resource
-export const getResourceAlerts = (
- resourceId: string,
- activeAlerts: Record
-): Alert[] => {
- return Object.values(activeAlerts).filter(alert => alert.resourceId === resourceId);
-};
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/utils/clipboard.ts b/pulse-test-staging/frontend-modern/src/utils/clipboard.ts
deleted file mode 100644
index 78579d932..000000000
--- a/pulse-test-staging/frontend-modern/src/utils/clipboard.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-export async function copyToClipboard(text: string): Promise {
- try {
- if (navigator.clipboard && window.isSecureContext) {
- await navigator.clipboard.writeText(text);
- return true;
- } else {
- // Fallback for older browsers
- const textArea = document.createElement('textarea');
- textArea.value = text;
- textArea.style.position = 'fixed';
- textArea.style.left = '-999999px';
- textArea.style.top = '-999999px';
- document.body.appendChild(textArea);
- textArea.focus();
- textArea.select();
- const successful = document.execCommand('copy');
- document.body.removeChild(textArea);
- return successful;
- }
- } catch (err) {
- console.error('Failed to copy to clipboard:', err);
- return false;
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/utils/format.ts b/pulse-test-staging/frontend-modern/src/utils/format.ts
deleted file mode 100644
index 8e1cc7b03..000000000
--- a/pulse-test-staging/frontend-modern/src/utils/format.ts
+++ /dev/null
@@ -1,75 +0,0 @@
-// Type-safe formatting utilities
-
-export function formatBytes(bytes: number, decimals = 0): string {
- if (!bytes || bytes < 0) return '0 B';
-
- const k = 1024;
- const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
- const i = Math.floor(Math.log(bytes) / Math.log(k));
-
- return `${(bytes / Math.pow(k, i)).toFixed(decimals)} ${sizes[i]}`;
-}
-
-export function formatSpeed(bytesPerSecond: number, decimals = 0): string {
- if (!bytesPerSecond || bytesPerSecond < 0) return '0 B/s';
- return `${formatBytes(bytesPerSecond, decimals)}/s`;
-}
-
-export function formatUptime(seconds: number): string {
- if (!seconds || seconds < 0) return '0s';
-
- const days = Math.floor(seconds / 86400);
- const hours = Math.floor((seconds % 86400) / 3600);
- const minutes = Math.floor((seconds % 3600) / 60);
-
- if (days > 0) {
- return `${days}d ${hours}h`;
- } else if (hours > 0) {
- return `${hours}h ${minutes}m`;
- } else {
- return `${minutes}m`;
- }
-}
-
-
-export function formatAbsoluteTime(timestamp: number): string {
- if (!timestamp) return '';
- const date = new Date(timestamp);
-
- const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
- 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
-
- const month = months[date.getMonth()];
- const day = date.getDate();
- const hours = date.getHours().toString().padStart(2, '0');
- const minutes = date.getMinutes().toString().padStart(2, '0');
-
- return `${day} ${month} ${hours}:${minutes}`;
-}
-
-export function formatRelativeTime(timestamp: number): string {
- if (!timestamp) return '';
-
- const now = Date.now();
- const diffMs = now - timestamp;
- const diffSeconds = Math.floor(diffMs / 1000);
- const diffMinutes = Math.floor(diffSeconds / 60);
- const diffHours = Math.floor(diffMinutes / 60);
- const diffDays = Math.floor(diffHours / 24);
- const diffMonths = Math.floor(diffDays / 30);
- const diffYears = Math.floor(diffDays / 365);
-
- if (diffSeconds < 60) {
- return diffSeconds <= 1 ? 'just now' : `${diffSeconds}s ago`;
- } else if (diffMinutes < 60) {
- return diffMinutes === 1 ? '1 min ago' : `${diffMinutes} mins ago`;
- } else if (diffHours < 24) {
- return diffHours === 1 ? '1 hour ago' : `${diffHours} hours ago`;
- } else if (diffDays < 30) {
- return diffDays === 1 ? '1 day ago' : `${diffDays} days ago`;
- } else if (diffMonths < 12) {
- return diffMonths === 1 ? '1 month ago' : `${diffMonths} months ago`;
- } else {
- return diffYears === 1 ? '1 year ago' : `${diffYears} years ago`;
- }
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/utils/logger.ts b/pulse-test-staging/frontend-modern/src/utils/logger.ts
deleted file mode 100644
index a21c482ca..000000000
--- a/pulse-test-staging/frontend-modern/src/utils/logger.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-// Simple logger - just console.log with timestamps
-const isDev = import.meta.env.DEV;
-
-export const logger = {
- debug: (message: string, data?: unknown) => {
- if (isDev) console.log(`[DEBUG] ${message}`, data || '');
- },
-
- info: (message: string, data?: unknown) => {
- console.log(`[INFO] ${message}`, data || '');
- },
-
- warn: (message: string, data?: unknown) => {
- console.warn(`[WARN] ${message}`, data || '');
- },
-
- error: (message: string, error?: unknown) => {
- console.error(`[ERROR] ${message}`, error || '');
- }
-};
-
-export const logError = logger.error;
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/utils/searchQuery.ts b/pulse-test-staging/frontend-modern/src/utils/searchQuery.ts
deleted file mode 100644
index 5da9cd738..000000000
--- a/pulse-test-staging/frontend-modern/src/utils/searchQuery.ts
+++ /dev/null
@@ -1,311 +0,0 @@
-import type { VM, Container } from '@/types/api';
-
-export type ComparisonOperator = '>' | '<' | '>=' | '<=' | '=' | '==';
-export type LogicalOperator = 'AND' | 'OR';
-
-export interface MetricCondition {
- field: 'cpu' | 'memory' | 'disk' | 'diskRead' | 'diskWrite' | 'networkIn' | 'networkOut';
- operator: ComparisonOperator;
- value: number;
-}
-
-export interface TextCondition {
- field: 'name' | 'node' | 'vmid';
- value: string;
-}
-
-export type Condition = MetricCondition | TextCondition;
-
-export interface ParsedQuery {
- conditions: Condition[];
- logicalOperator: LogicalOperator;
- rawText?: string; // Fallback for simple text search
-}
-
-// New interfaces for stackable filters
-export interface ParsedFilter {
- type: 'metric' | 'text' | 'raw';
- rawText?: string;
- field?: string;
- operator?: ComparisonOperator;
- value?: string | number;
-}
-
-export interface FilterStack {
- filters: ParsedFilter[];
- operators: LogicalOperator[]; // Operators between filters (length = filters.length - 1)
- logicalOperator?: LogicalOperator; // Deprecated, kept for compatibility
-}
-
-
-// Parse a single filter from a search term
-export function parseFilter(term: string): ParsedFilter {
- term = term.trim();
-
- // Try to parse metric condition (e.g., "cpu>80")
- const metricMatch = term.match(/^(cpu|memory|disk|diskRead|diskWrite|networkIn|networkOut)\s*(>|<|>=|<=|=|==)\s*(\d+(?:\.\d+)?)$/i);
- if (metricMatch) {
- const [, field, operator, value] = metricMatch;
- return {
- type: 'metric',
- field: field.toLowerCase(),
- operator: operator as ComparisonOperator,
- value: parseFloat(value)
- };
- }
-
- // Try to parse text condition (e.g., "name:prod")
- const textMatch = term.match(/^(name|node|vmid)\s*:\s*(.+)$/i);
- if (textMatch) {
- const [, field, value] = textMatch;
- return {
- type: 'text',
- field: field.toLowerCase(),
- value: value.trim()
- };
- }
-
- // Otherwise treat as raw text search
- return {
- type: 'raw',
- rawText: term
- };
-}
-
-// Parse multiple filters from a search string
-export function parseFilterStack(searchString: string): FilterStack {
- const trimmed = searchString.trim();
- if (!trimmed) {
- return { filters: [], operators: [] };
- }
-
- // Split by AND/OR operators while preserving them
- const regex = /\s+(AND|OR)\s+/gi;
- const parts = trimmed.split(regex);
- const filters: ParsedFilter[] = [];
- const operators: LogicalOperator[] = [];
-
- // Process the parts
- for (let i = 0; i < parts.length; i++) {
- const part = parts[i].trim();
- if (!part) continue;
-
- if (i % 2 === 0) {
- // Even indices are filter expressions
- const filter = parseFilter(part);
- filters.push(filter);
- } else {
- // Odd indices are operators
- operators.push(part.toUpperCase() as LogicalOperator);
- }
- }
-
- // For backward compatibility, include logicalOperator as the first operator
- const logicalOperator = operators.length > 0 ? operators[0] : 'AND';
-
- return { filters, operators, logicalOperator };
-}
-
-function parseCondition(conditionStr: string): Condition | null {
- // Try to parse metric condition (e.g., "cpu>80")
- const metricMatch = conditionStr.match(/^(cpu|memory|disk|diskRead|diskWrite|networkIn|networkOut)\s*(>|<|>=|<=|=|==)\s*(\d+(?:\.\d+)?)$/i);
- if (metricMatch) {
- const [, field, operator, value] = metricMatch;
- return {
- field: field.toLowerCase() as MetricCondition['field'],
- operator: operator as ComparisonOperator,
- value: parseFloat(value)
- } as MetricCondition;
- }
-
- // Try to parse text condition (e.g., "name:prod")
- const textMatch = conditionStr.match(/^(name|node|vmid)\s*:\s*(.+)$/i);
- if (textMatch) {
- const [, field, value] = textMatch;
- return {
- field: field.toLowerCase() as 'name' | 'node' | 'vmid',
- value: value.trim()
- } as TextCondition;
- }
-
- return null;
-}
-
-export function parseSearchQuery(query: string): ParsedQuery {
- query = query.trim();
-
- // Check for logical operators
- const hasAnd = /\bAND\b/i.test(query);
- const hasOr = /\bOR\b/i.test(query);
-
- // If no operators or invalid query, treat as simple text search
- if (!hasAnd && !hasOr && !query.match(/[><=:]/)) {
- return {
- conditions: [],
- logicalOperator: 'AND',
- rawText: query
- };
- }
-
- // Split by logical operator
- const logicalOperator: LogicalOperator = hasAnd ? 'AND' : 'OR';
- const parts = query.split(hasAnd ? /\bAND\b/i : /\bOR\b/i);
-
- const conditions: Condition[] = [];
-
- for (const part of parts) {
- const condition = parseCondition(part.trim());
- if (condition) {
- conditions.push(condition);
- }
- }
-
- // If no valid conditions parsed, fall back to text search
- if (conditions.length === 0) {
- return {
- conditions: [],
- logicalOperator: 'AND',
- rawText: query
- };
- }
-
- return {
- conditions,
- logicalOperator
- };
-}
-
-function evaluateMetricCondition(guest: VM | Container, condition: MetricCondition): boolean {
- let value: number;
-
- switch (condition.field) {
- case 'cpu':
- // CPU is stored as decimal (0-1), convert to percentage
- value = (guest.cpu || 0) * 100;
- break;
- case 'memory':
- value = guest.memory ? guest.memory.usage : 0;
- break;
- case 'disk':
- value = guest.disk ? guest.disk.usage : 0;
- break;
- default:
- return false;
- }
-
- switch (condition.operator) {
- case '>':
- return value > condition.value;
- case '<':
- return value < condition.value;
- case '>=':
- return value >= condition.value;
- case '<=':
- return value <= condition.value;
- case '=':
- case '==':
- return Math.abs(value - condition.value) < 0.01;
- default:
- return false;
- }
-}
-
-function evaluateTextCondition(guest: VM | Container, condition: TextCondition): boolean {
- const searchValue = condition.value.toLowerCase();
-
- switch (condition.field) {
- case 'name':
- return guest.name.toLowerCase().includes(searchValue);
- case 'node':
- return guest.node.toLowerCase().includes(searchValue);
- case 'vmid':
- return guest.vmid.toString().includes(searchValue);
- default:
- return false;
- }
-}
-
-export function evaluateSearchQuery(guest: VM | Container, query: ParsedQuery): boolean {
- // If it's a simple text search
- if (query.rawText) {
- const searchTerms = query.rawText.toLowerCase().split(',').map(term => term.trim()).filter(term => term.length > 0);
- return searchTerms.some(term =>
- guest.name.toLowerCase().includes(term) ||
- guest.vmid.toString().includes(term) ||
- guest.node.toLowerCase().includes(term) ||
- guest.status.toLowerCase().includes(term)
- );
- }
-
- // If no conditions, match all
- if (query.conditions.length === 0) {
- return true;
- }
-
- // Evaluate conditions
- const results = query.conditions.map(condition => {
- if ('operator' in condition) {
- return evaluateMetricCondition(guest, condition);
- } else {
- return evaluateTextCondition(guest, condition);
- }
- });
-
- // Apply logical operator
- if (query.logicalOperator === 'AND') {
- return results.every(result => result);
- } else {
- return results.some(result => result);
- }
-}
-
-// Evaluate a filter stack against a guest
-export function evaluateFilterStack(guest: VM | Container, stack: FilterStack): boolean {
- if (stack.filters.length === 0) {
- return true;
- }
-
- const results = stack.filters.map(filter => {
- if (filter.type === 'metric' && filter.field && filter.operator && filter.value !== undefined) {
- const condition: MetricCondition = {
- field: filter.field as MetricCondition['field'],
- operator: filter.operator,
- value: filter.value as number
- };
- return evaluateMetricCondition(guest, condition);
- } else if (filter.type === 'text' && filter.field && filter.value) {
- const condition: TextCondition = {
- field: filter.field as TextCondition['field'],
- value: filter.value as string
- };
- return evaluateTextCondition(guest, condition);
- } else if (filter.type === 'raw' && filter.rawText) {
- const term = filter.rawText.toLowerCase();
- return guest.name.toLowerCase().includes(term) ||
- guest.vmid.toString().includes(term) ||
- guest.node.toLowerCase().includes(term) ||
- guest.status.toLowerCase().includes(term);
- }
- return true;
- });
-
- // If only one filter, return its result
- if (results.length === 1) {
- return results[0];
- }
-
- // Apply operators between filters
- let result = results[0];
- for (let i = 0; i < stack.operators.length && i < results.length - 1; i++) {
- const operator = stack.operators[i];
- const nextResult = results[i + 1];
-
- if (operator === 'AND') {
- result = result && nextResult;
- } else {
- result = result || nextResult;
- }
- }
-
- return result;
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/utils/toast.ts b/pulse-test-staging/frontend-modern/src/utils/toast.ts
deleted file mode 100644
index cf9bd191a..000000000
--- a/pulse-test-staging/frontend-modern/src/utils/toast.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import type { ToastType } from '@/components/Toast/Toast';
-
-// Global declaration is in Toast.tsx
-
-export const showToast = (type: ToastType, title: string, message?: string, duration?: number) => {
- // Use the global toast function exposed by ToastContainer
- if (typeof window !== 'undefined' && window.showToast) {
- window.showToast(type, title, message, duration);
- } else {
- // Fallback to console if toast system not ready
- console.log(`[${type.toUpperCase()}] ${title}${message ? ': ' + message : ''}`);
- }
-};
-
-// Convenience functions - only export what's used
-export const showSuccess = (title: string, message?: string) => showToast('success', title, message);
-export const showError = (title: string, message?: string) => showToast('error', title, message);
-export const showInfo = (title: string, message?: string) => showToast('info', title, message);
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/src/vite-env.d.ts b/pulse-test-staging/frontend-modern/src/vite-env.d.ts
deleted file mode 100644
index 151aa6856..000000000
--- a/pulse-test-staging/frontend-modern/src/vite-env.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-///
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/tailwind.config.js b/pulse-test-staging/frontend-modern/tailwind.config.js
deleted file mode 100644
index 2e56f29ae..000000000
--- a/pulse-test-staging/frontend-modern/tailwind.config.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export default {
- content: [
- "./index.html",
- "./src/**/*.{js,ts,jsx,tsx}",
- ],
- darkMode: 'class',
- theme: {
- extend: {
- colors: {
- gray: {
- 750: '#2d3748',
- }
- },
- animation: {
- 'spin-slow': 'spin 2s linear infinite',
- }
- },
- },
- plugins: [],
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/tsconfig.json b/pulse-test-staging/frontend-modern/tsconfig.json
deleted file mode 100644
index e32748923..000000000
--- a/pulse-test-staging/frontend-modern/tsconfig.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "compilerOptions": {
- "target": "ES2020",
- "useDefineForClassFields": true,
- "module": "ESNext",
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
- "skipLibCheck": true,
- "jsx": "preserve",
- "jsxImportSource": "solid-js",
-
- /* Bundler mode */
- "moduleResolution": "bundler",
- "allowImportingTsExtensions": true,
- "resolveJsonModule": true,
- "isolatedModules": true,
- "noEmit": true,
-
- /* Linting */
- "strict": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "noFallthroughCasesInSwitch": true,
-
- "paths": {
- "@/*": ["./src/*"]
- }
- },
- "include": ["src"],
- "references": [{ "path": "./tsconfig.node.json" }]
-}
\ No newline at end of file
diff --git a/pulse-test-staging/frontend-modern/tsconfig.node.json b/pulse-test-staging/frontend-modern/tsconfig.node.json
deleted file mode 100644
index 97ede7ee6..000000000
--- a/pulse-test-staging/frontend-modern/tsconfig.node.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "compilerOptions": {
- "composite": true,
- "skipLibCheck": true,
- "module": "ESNext",
- "moduleResolution": "bundler",
- "allowSyntheticDefaultImports": true,
- "strict": true
- },
- "include": ["vite.config.ts"]
-}
diff --git a/pulse-test-staging/frontend-modern/vite.config.ts b/pulse-test-staging/frontend-modern/vite.config.ts
deleted file mode 100644
index daf3bab70..000000000
--- a/pulse-test-staging/frontend-modern/vite.config.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { defineConfig } from 'vite';
-import solid from 'vite-plugin-solid';
-import path from 'path';
-
-export default defineConfig({
- plugins: [solid()],
- resolve: {
- alias: {
- '@': path.resolve(__dirname, './src'),
- },
- },
- server: {
- port: 7655,
- host: '0.0.0.0', // Listen on all interfaces for remote access
- proxy: {
- '/ws': {
- target: 'ws://127.0.0.1:3000',
- ws: true,
- changeOrigin: true,
- },
- '/api': {
- target: 'http://127.0.0.1:3000',
- changeOrigin: true,
- },
- },
- },
- build: {
- target: 'esnext',
- },
- test: {
- environment: 'jsdom',
- globals: true,
- setupFiles: ['./src/test/setup.ts'],
- },
-});
\ No newline at end of file