Release v0.9.194

Automated sync from private repository.
Built with obfuscation enabled.
This commit is contained in:
GitHub Actions Bot
2026-01-29 18:28:52 +00:00
parent 75110f5ebc
commit ec0e888042
60 changed files with 650 additions and 52 deletions
+5 -7
View File
@@ -159,11 +159,11 @@ cd pymc_console
sudo bash manage.sh install
```
> **⚠️ Important: Branch Selection**
> **Note: Branch Selection**
>
> During installation, you'll be asked to select a pyMC_Repeater branch. **Select `feat/dmg`** (the default/recommended option). This branch contains the login/authentication functionality required for the dashboard to work properly.
> During installation, you'll be asked to select a pyMC_Repeater branch. **Select `dev`** (the default/recommended option). The `dev` branch contains the latest features and improvements.
>
> If you select `dev` or `main`, you may encounter "error 200" or login issues.
The installer will:
1. Install all system dependencies (Python, pip, etc.)
@@ -296,7 +296,7 @@ sudo journalctl -u pymc-repeater -f
### "Error 200" or Login Issues
This typically means you installed with the wrong pyMC_Repeater branch. The login functionality is only available in the `feat/dmg` branch.
This can occur with older installations or mismatched versions.
**To fix:**
```bash
@@ -304,9 +304,7 @@ cd pymc_console
sudo bash manage.sh upgrade
```
Select **Full pyMC Stack** upgrade and choose the `feat/dmg` branch.
> **Note:** When entering the branch name, use `feat/dmg` (not just `dmg`).
Select **Full pyMC Stack** upgrade to update pyMC_Repeater and pyMC_core to the latest versions.
### Service won't start
+600
View File
@@ -0,0 +1,600 @@
# Cosmograph v2 — AI Agent Reference
> **Purpose**: This document provides AI coding assistants (Claude, GPT, etc.) with the essential context needed to correctly implement Cosmograph v2 visualizations. It consolidates the v2 API patterns, data requirements, and common pitfalls into a single reference optimized for agent consumption.
## Quick Context
**What is Cosmograph?**
Cosmograph is a high-performance graph visualization library that uses WebGL and DuckDB-Wasm for rendering large networks. v2 introduced a new data pipeline requiring explicit data preparation.
**Packages:**
- `@cosmograph/cosmograph` — Core library (vanilla JS/TS)
- `@cosmograph/react` — React wrapper + Data Kit utilities
**Key Concept — Data Kit:**
Raw data (arrays, CSV, JSON, etc.) must be processed through `prepareCosmographData()` before rendering. This function:
1. Converts raw data to Arrow tables (DuckDB-compatible)
2. Generates index columns automatically
3. Returns a `cosmographConfig` with correct mapping props
---
## Critical Pattern: Data Preparation
### The Golden Rule
```typescript
// ❌ WRONG - Passing raw data directly
<Cosmograph points={rawPoints} links={rawLinks} />
// ✅ CORRECT - Using Data Kit
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
const { points, links, cosmographConfig } = result;
<Cosmograph points={points} links={links} {...cosmographConfig} />
```
### Minimal Data Config
**Case A: You have a points array with IDs (most common)**
```typescript
const dataConfig = {
points: { pointIdBy: "id" },
links: { linkSourceBy: "source", linkTargetsBy: ["target"] },
};
```
**Case B: Generate points from links (no separate points array)**
```typescript
const dataConfig = {
points: { linkSourceBy: "source", linkTargetsBy: ["target"] },
links: { linkSourceBy: "source", linkTargetsBy: ["target"] },
};
```
### What NOT to Include in dataConfig
**DO NOT manually specify index columns:**
- `pointIndexBy` — auto-generated by Data Kit
- `linkSourceIndexBy` — auto-generated by Data Kit
- `linkTargetsIndexBy` — auto-generated by Data Kit
These are internal indices that Data Kit computes. Specifying them manually will cause errors.
---
## React Integration
### Complete Working Example
```tsx
import { useEffect, useMemo, useState } from "react";
import { Cosmograph, prepareCosmographData } from "@cosmograph/react";
import type { CosmographConfig, CosmographData } from "@cosmograph/react";
export function Graph() {
// Raw data - your actual graph data
const rawPoints = useMemo(() => [
{ id: "a", label: "Node A", color: "#FF0000" },
{ id: "b", label: "Node B", color: "#00FF00" },
{ id: "c", label: "Node C", color: "#0000FF" },
], []);
const rawLinks = useMemo(() => [
{ source: "a", target: "b" },
{ source: "b", target: "c" },
], []);
// Prepared data state
const [preparedPoints, setPreparedPoints] = useState<CosmographData | null>(null);
const [preparedLinks, setPreparedLinks] = useState<CosmographData | null>(null);
const [config, setConfig] = useState<CosmographConfig>({});
// Prepare data on mount or when raw data changes
useEffect(() => {
const prepare = async () => {
const dataConfig = {
points: {
pointIdBy: "id",
pointColorBy: "color", // Optional: map color column
pointLabelBy: "label", // Optional: map label column
},
links: {
linkSourceBy: "source",
linkTargetsBy: ["target"], // Note: array!
linkColorBy: "color", // Optional: if links have colors
},
};
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
if (!result) return;
const { points, links, cosmographConfig } = result;
setPreparedPoints(points);
setPreparedLinks(links);
setConfig(cosmographConfig);
};
prepare();
}, [rawPoints, rawLinks]);
// Don't render until data is ready
if (!preparedPoints) return <div>Loading...</div>;
return (
<Cosmograph
points={preparedPoints}
links={preparedLinks}
{...config}
// Override with your settings (these don't conflict with mapping props)
backgroundColor="#1a1a2e"
fitViewOnInit={true}
showLabels={true}
/>
);
}
```
### Imperative Access via onMount
```tsx
const [api, setApi] = useState<any>(null);
<Cosmograph
{...config}
onMount={(cosmograph) => setApi(cosmograph)}
/>
// Later: call methods imperatively
<button onClick={() => api?.fitView(300)}>Fit View</button>
<button onClick={() => api?.pause()}>Pause Simulation</button>
```
### Using CosmographProvider + useCosmograph
```tsx
import { CosmographProvider, Cosmograph, useCosmograph } from "@cosmograph/react";
function Controls() {
const { cosmograph } = useCosmograph();
return <button onClick={() => cosmograph?.fitView()}>Fit</button>;
}
function App() {
return (
<CosmographProvider>
<Cosmograph {...config} />
<Controls />
</CosmographProvider>
);
}
```
---
## Vanilla JS/TS Integration
```typescript
import { Cosmograph, prepareCosmographData } from "@cosmograph/cosmograph";
const container = document.getElementById("graph")!;
const rawPoints = [{ id: "a" }, { id: "b" }, { id: "c" }];
const rawLinks = [{ source: "a", target: "b" }, { source: "b", target: "c" }];
const dataConfig = {
points: { pointIdBy: "id" },
links: { linkSourceBy: "source", linkTargetsBy: ["target"] },
};
async function init() {
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
if (!result) return;
const { points, links, cosmographConfig } = result;
const graph = new Cosmograph(container, { points, links, ...cosmographConfig });
// Wait for data to load
await graph.dataUploaded();
// Sanity check
console.log(graph.stats); // { pointsCount: 3, linksCount: 2, ... }
// Ensure visible
graph.fitView();
// Cleanup later
// await graph.destroy();
}
init();
```
---
## Data Format Requirements
### Points Array
```typescript
interface Point {
id: string; // Required: unique identifier
label?: string; // Optional: display label
color?: string; // Optional: hex color (#RRGGBB)
size?: number; // Optional: node size
x?: number; // Optional: fixed x position
y?: number; // Optional: fixed y position
[key: string]: any; // Additional columns for tooltips, filtering, etc.
}
```
### Links Array
```typescript
interface Link {
source: string; // Required: source point ID
target: string; // Required: target point ID
color?: string; // Optional: hex color
width?: number; // Optional: line width (for linkWidthBy)
strength?: number; // Optional: physics spring strength (for linkStrengthBy)
[key: string]: any; // Additional columns
}
```
### Link Width Configuration
To use custom edge widths based on data (e.g., traffic volume):
```typescript
const dataConfig = {
points: { pointIdBy: "id" },
links: {
linkSourceBy: "source",
linkTargetsBy: ["target"],
linkColorBy: "color",
// Map width column for edge thickness
linkWidthBy: "width",
// Auto-scale widths to this range (pixels)
linkWidthRange: [0.5, 6.0],
// Default width for edges without width data
linkDefaultWidth: 0.5,
},
};
```
**Width Strategies** (via `linkWidthStrategy`):
- `undefined` (default): Auto-select based on data
- `"direct"`: Use values from `linkWidthBy` column as-is (1:1 pixel values)
- `"sum"`: Sum of values for multi-edges between same nodes
- `"average"`: Average of values for multi-edges
- `"count"`: Width based on number of links between same nodes
**Custom Width Function** (for dynamic calculation):
```typescript
const dataConfig = {
links: {
linkWidthBy: "rawTraffic", // Column with raw values
linkWidthByFn: (value: number, index: number) => {
// Custom calculation (e.g., logarithmic scaling)
return 0.5 + Math.log1p(value) * 0.5;
},
},
};
```
### Position Handling (x/y coordinates)
When you have fixed positions for some or all nodes:
```typescript
const dataConfig = {
points: {
pointIdBy: "id",
pointXBy: "x", // Map x position column
pointYBy: "y", // Map y position column
},
links: { ... },
};
```
**Important DuckDB constraint:** If mapping x/y positions, you need **at least 2 points with valid positions**. DuckDB's STDDEV_SAMP function (used internally) requires ≥2 values. If you have fewer, omit `pointXBy`/`pointYBy` from the config.
---
## Common Config Props
### Layout & Simulation
```typescript
{
disableSimulation: false, // true = fixed layout, no physics
fitViewOnInit: true, // Auto-fit view after data loads
fitViewDelay: 300, // Delay before fitView (ms)
fitViewPadding: 0.1, // Padding around nodes (0-1)
// Simulation physics (only when disableSimulation: false)
simulationRepulsion: 1.0, // Node repulsion strength
simulationLinkSpring: 0.5, // Link spring strength
simulationLinkDistance: 50, // Target link length
simulationGravity: 0.1, // Pull toward center
simulationFriction: 0.85, // Velocity damping
simulationAlpha: 1.0, // Initial simulation "heat"
simulationAlphaDecay: 0.01, // How fast simulation cools
}
```
### Visual Styling
```typescript
{
backgroundColor: "#1a1a2e",
// Points
pointDefaultSize: 10,
pointDefaultColor: "#666666",
pointGreyoutOpacity: 0.3, // Opacity when not selected
// Links
linkDefaultWidth: 1,
linkDefaultColor: "#444444",
linkGreyoutOpacity: 0.3,
// Labels
showLabels: true,
showDynamicLabels: true, // Show labels on zoom
showTopLabels: true, // Always show top N labels
showTopLabelsLimit: 50,
showHoveredPointLabel: true,
pointLabelColor: "#ffffff",
pointLabelFontSize: 12,
}
```
---
## Cosmograph Class API (Imperative Methods)
### Lifecycle
```typescript
await cosmograph.dataUploaded() // Wait for async data to load
await cosmograph.destroy() // Cleanup (important!)
cosmograph.stats // { pointsCount, linksCount, ... }
```
### View Control
```typescript
cosmograph.fitView(duration?) // Fit all nodes in view
cosmograph.fitViewByIndices(indices, duration?) // Fit specific nodes
cosmograph.setZoomLevel(level, duration?) // Set zoom (1 = default)
cosmograph.zoomToPoint(index, duration?, scale?) // Zoom to specific node
```
### Simulation Control
```typescript
cosmograph.isSimulationAvailable // Check if simulation is possible
cosmograph.isSimulationRunning // Check if currently running
cosmograph.start(alpha?) // Start simulation
cosmograph.pause() // Pause simulation
cosmograph.unpause() // Resume simulation
cosmograph.stop() // Stop simulation
```
### Selection
```typescript
// Activate selection modes
cosmograph.activateRectSelection()
cosmograph.activatePolygonalSelection()
cosmograph.deactivateRectSelection()
// Programmatic selection
cosmograph.selectPoint(index, addToSelection?)
cosmograph.selectPoints(indices, addToSelection?)
cosmograph.selectPointsInRect(rect, addToSelection?)
cosmograph.unselectAllPoints()
// Read selection
cosmograph.getSelectedPointIndices() // number[] | undefined
```
### ID ↔ Index Conversion
```typescript
// Point ID = your data's identifier (string)
// Point Index = Cosmograph's internal array index (number)
await cosmograph.getPointIndicesByIds(["node-a", "node-b"]) // [0, 1]
await cosmograph.getPointIdsByIndices([0, 1]) // ["node-a", "node-b"]
```
### Dynamic Data Updates
```typescript
await cosmograph.addPoints([{ id: "new", label: "New Node" }])
await cosmograph.addLinks([{ source: "a", target: "new" }])
await cosmograph.removePointsByIds(["node-to-remove"])
await cosmograph.removeLinksByPointIdPairs([["a", "b"]])
```
---
## Troubleshooting
### Blank Canvas / Nothing Renders
1. **Data not loaded:**
```typescript
await cosmograph.dataUploaded();
console.log(cosmograph.stats); // Should show non-zero counts
```
2. **Nodes off-screen:**
```typescript
cosmograph.fitView();
```
3. **Config not spread correctly:**
```typescript
// ❌ Wrong
<Cosmograph config={cosmographConfig} />
// ✅ Correct
<Cosmograph {...cosmographConfig} points={points} links={links} />
```
### "STDDEV_SAMP is out of range" Error
This DuckDB error occurs when computing statistics on columns with insufficient variance:
1. Column has fewer than 2 values
2. **All values are identical (variance = 0)** ← Common gotcha!
**Cause:** Mapping numeric columns (x, y, size, width, etc.) when there isn't enough variance.
**Fix for positions:** Check for actual variance in BOTH x AND y coordinates:
```typescript
// Filter to points with valid position data
const pointsWithPos = rawPoints.filter(
(p): p is typeof p & { x: number; y: number } =>
'x' in p && 'y' in p && typeof p.x === 'number' && typeof p.y === 'number'
);
const positionCount = pointsWithPos.length;
// IMPORTANT: Check variance, not just count!
// Nodes clustered at identical coordinates will still fail with positionCount >= 2
const uniqueX = new Set(pointsWithPos.map(p => p.x));
const uniqueY = new Set(pointsWithPos.map(p => p.y));
const hasVaryingPositions = positionCount >= 2 && uniqueX.size >= 2 && uniqueY.size >= 2;
const dataConfig = {
points: {
pointIdBy: "id",
// Only map positions when BOTH x and y have variance
...(hasVaryingPositions ? { pointXBy: "x", pointYBy: "y" } : {}),
},
links: { ... },
};
```
**Fix for link widths:** Only include `linkWidthBy` when ≥2 links have varying widths:
```typescript
const linkWidths = rawLinks.map(l => l.width).filter((w): w is number => w != null);
const uniqueWidths = new Set(linkWidths);
const hasVaryingWidths = linkWidths.length >= 2 && uniqueWidths.size >= 2;
const dataConfig = {
points: { ... },
links: {
linkSourceBy: "source",
linkTargetsBy: ["target"],
linkColorBy: "color", // String columns are safe - no STDDEV
// Only map width when we have variance
...(hasVaryingWidths ? {
linkWidthBy: "width",
linkWidthRange: [0.5, 6.0],
} : {}),
linkDefaultWidth: 0.5, // Fallback when no width mapping
},
};
```
**Why this happens:** DuckDB's `STDDEV_SAMP` function computes sample standard deviation, which requires variance in the data. When all values are identical (e.g., nodes at same GPS coordinates), the variance is 0, causing the "out of range" error. The count check alone is insufficient.
### "Missing required properties: pointIdBy" Error
**Cause:** Passing raw data without going through Data Kit.
**Fix:** Always use `prepareCosmographData()`:
```typescript
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
// result.cosmographConfig contains the required mapping props
```
### Simulation Not Working
```typescript
// Check if simulation is even possible
console.log(cosmograph.isSimulationAvailable); // Should be true
// If false, check:
// - disableSimulation: true in config?
// - No links in data?
// - Fixed positions for all nodes?
// If true but not running:
cosmograph.start(); // or cosmograph.unpause();
```
### Wrong Node Selected (ID vs Index Confusion)
**Symptom:** Clicking node "A" selects node "B"
**Cause:** Confusing user IDs with internal indices.
```typescript
// Your data uses string IDs
const nodeId = "my-node-a";
// Cosmograph uses numeric indices internally
const index = await cosmograph.getPointIndicesByIds([nodeId]);
cosmograph.selectPoint(index[0]);
// Or convert back
const ids = await cosmograph.getPointIdsByIndices([selectedIndex]);
```
---
## External DuckDB Tables (Advanced)
When loading pre-existing DuckDB-Wasm tables (not using Data Kit):
```typescript
<Cosmograph
duckDBConnection={{ duckdb: db, connection }}
points="my_points_table"
links="my_links_table"
// You MUST specify all mapping columns manually:
pointIdBy="id"
pointIndexBy="idx" // Your table must have this column
linkSourceBy="source"
linkSourceIndexBy="source_idx"
linkTargetsBy={["target"]}
linkTargetsIndexBy={["target_idx"]}
/>
```
**Required table columns for external loading:**
- Points: `id` (string), `idx` (integer index)
- Links: `source` (string), `source_idx` (integer), `target` (string), `target_idx` (integer)
---
## Checklist for Implementation
When implementing Cosmograph v2:
- [ ] Install `@cosmograph/react` (or `@cosmograph/cosmograph` for vanilla)
- [ ] Create raw points array with unique `id` field
- [ ] Create raw links array with `source` and `target` string fields
- [ ] Define `dataConfig` with `pointIdBy: "id"` and `linkSourceBy/linkTargetsBy`
- [ ] Call `prepareCosmographData(dataConfig, rawPoints, rawLinks)`
- [ ] Extract `{ points, links, cosmographConfig }` from result
- [ ] Pass to Cosmograph: `<Cosmograph points={points} links={links} {...cosmographConfig} />`
- [ ] Add visual overrides (backgroundColor, showLabels, etc.) AFTER spreading config
- [ ] Handle loading state (don't render until `preparedPoints` exists)
- [ ] Call `fitView()` if nodes appear off-screen
- [ ] Call `destroy()` on cleanup if using imperative API
---
## Version Notes
This document covers **Cosmograph v2**. Key differences from v1:
- Data Kit is required (no direct raw data passing)
- DuckDB-Wasm is used internally for data processing
- Index columns are auto-generated (don't specify manually)
- Arrow tables are the internal format
- `linkTargetsBy` is an array (supports multi-target edges)
+1 -1
View File
@@ -1 +1 @@
0.9.193
0.9.194
@@ -1 +1 @@
import{i as t,bR as e,r}from"./vendor-react-LAbPDfrQ.js";const a="pymc-basemap-mode",o="dark";function s(){if("undefined"==typeof window)return o;try{const t=localStorage.getItem(a);if("light"===t||"dark"===t)return t}catch{}return o}function n(t){if("undefined"!=typeof window)try{localStorage.setItem(a,t)}catch{}}const c=t(t=>({mode:s(),toggle:()=>t(t=>{const e="light"===t.mode?"dark":"light";return n(e),{mode:e}}),setMode:e=>{n(e),t({mode:e})}})),i=()=>c(t=>t.mode),l=()=>c(t=>t.toggle),u={light:"https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",dark:"https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"},d={light:"basemap-light-",dark:"basemap-dark-"},f={};function y({mode:t}){const{current:a}=e(),[o,s]=r.useState(null),n=r.useRef({light:!1,dark:!1}),c=r.useRef({light:[],dark:[]});r.useEffect(()=>{const t=()=>{var t;const e=null==(t=null==a?void 0:a.getMap)?void 0:t.call(a);e&&!o&&s(e)};t();const e=setInterval(t,50),r=setTimeout(()=>clearInterval(e),5e3);return()=>{clearInterval(e),clearTimeout(r)}},[a,o]);const i=r.useCallback(async(t,e,r)=>{var a,o;if(n.current[e])return;const s=d[e],i=await async function(t){if(f[t])return f[t];const e=await fetch(u[t]),r=await e.json();return f[t]=r,r}(e),l=[];for(const[n,c]of Object.entries(i.sources||{})){const e=s+n;t.getSource(e)||t.addSource(e,c)}const y=null==(o=((null==(a=t.getStyle())?void 0:a.layers)||[]).find(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-")))?void 0:o.id;for(const n of i.layers||[]){const e=s+n.id;if(l.push(e),t.getLayer(e))continue;const a={...n,id:e};"source"in a&&"string"==typeof a.source&&(a.source=s+a.source),a.layout||(a.layout={}),a.layout.visibility=r?"visible":"none";try{t.addLayer(a,y)}catch(g){}}c.current[e]=l,n.current[e]=!0},[]),l=r.useCallback((t,e,r)=>{const a=c.current[e],o=r?"visible":"none";for(const s of a)if(t.getLayer(s))try{t.setLayoutProperty(s,"visibility",o)}catch{}},[]),y=r.useCallback(t=>{var e;const r=((null==(e=t.getStyle())?void 0:e.layers)||[]).filter(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-"));for(const a of r)try{t.moveLayer(a.id)}catch{}},[]);return r.useEffect(()=>{if(!o)return;let e=!1;const r=async()=>{if(!e)try{await Promise.all([i(o,"light","light"===t),i(o,"dark","dark"===t)]),e||y(o)}catch(r){}};o.isStyleLoaded()?r():(o.once("style.load",r),o.once("load",()=>{e||n.current.light||r()}));const a=()=>{e||setTimeout(()=>{!e&&n.current.light&&n.current.dark&&y(o)},100)};return o.on("styledata",a),()=>{e=!0,o.off("styledata",a)}},[o,i,y,t]),r.useEffect(()=>{o&&n.current.light&&n.current.dark&&(l(o,"light","light"===t),l(o,"dark","dark"===t))},[o,t,l]),null}export{y as B,l as a,i as u};
import{i as t,bO as e,r}from"./vendor-react-C341c8YC.js";const a="pymc-basemap-mode",o="dark";function s(){if("undefined"==typeof window)return o;try{const t=localStorage.getItem(a);if("light"===t||"dark"===t)return t}catch{}return o}function n(t){if("undefined"!=typeof window)try{localStorage.setItem(a,t)}catch{}}const c=t(t=>({mode:s(),toggle:()=>t(t=>{const e="light"===t.mode?"dark":"light";return n(e),{mode:e}}),setMode:e=>{n(e),t({mode:e})}})),i=()=>c(t=>t.mode),l=()=>c(t=>t.toggle),u={light:"https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",dark:"https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"},d={light:"basemap-light-",dark:"basemap-dark-"},f={};function y({mode:t}){const{current:a}=e(),[o,s]=r.useState(null),n=r.useRef({light:!1,dark:!1}),c=r.useRef({light:[],dark:[]});r.useEffect(()=>{const t=()=>{var t;const e=null==(t=null==a?void 0:a.getMap)?void 0:t.call(a);e&&!o&&s(e)};t();const e=setInterval(t,50),r=setTimeout(()=>clearInterval(e),5e3);return()=>{clearInterval(e),clearTimeout(r)}},[a,o]);const i=r.useCallback(async(t,e,r)=>{var a,o;if(n.current[e])return;const s=d[e],i=await async function(t){if(f[t])return f[t];const e=await fetch(u[t]),r=await e.json();return f[t]=r,r}(e),l=[];for(const[n,c]of Object.entries(i.sources||{})){const e=s+n;t.getSource(e)||t.addSource(e,c)}const y=null==(o=((null==(a=t.getStyle())?void 0:a.layers)||[]).find(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-")))?void 0:o.id;for(const n of i.layers||[]){const e=s+n.id;if(l.push(e),t.getLayer(e))continue;const a={...n,id:e};"source"in a&&"string"==typeof a.source&&(a.source=s+a.source),a.layout||(a.layout={}),a.layout.visibility=r?"visible":"none";try{t.addLayer(a,y)}catch(g){}}c.current[e]=l,n.current[e]=!0},[]),l=r.useCallback((t,e,r)=>{const a=c.current[e],o=r?"visible":"none";for(const s of a)if(t.getLayer(s))try{t.setLayoutProperty(s,"visibility",o)}catch{}},[]),y=r.useCallback(t=>{var e;const r=((null==(e=t.getStyle())?void 0:e.layers)||[]).filter(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-"));for(const a of r)try{t.moveLayer(a.id)}catch{}},[]);return r.useEffect(()=>{if(!o)return;let e=!1;const r=async()=>{if(!e)try{await Promise.all([i(o,"light","light"===t),i(o,"dark","dark"===t)]),e||y(o)}catch(r){}};o.isStyleLoaded()?r():(o.once("style.load",r),o.once("load",()=>{e||n.current.light||r()}));const a=()=>{e||setTimeout(()=>{!e&&n.current.light&&n.current.dark&&y(o)},100)};return o.on("styledata",a),()=>{e=!0,o.off("styledata",a)}},[o,i,y,t]),r.useEffect(()=>{o&&n.current.light&&n.current.dark&&(l(o,"light","light"===t),l(o,"dark","dark"===t))},[o,t,l]),null}export{y as B,l as a,i as u};
@@ -1 +1 @@
import{j as e}from"./vendor-react-LAbPDfrQ.js";import{c as s}from"./recharts-D38YBQhj.js";import{B as t}from"./index-UmM6aLcb.js";function l({title:l,icon:r,badge:i,subtitle:a,actions:c,iconColor:n="text-icon-card-title",largeTitle:x=!1,listHeader:m=!1,stackActionsOnMobile:d=!1}){return d&&c?e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]}):e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),c&&e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]})}function r({children:t,centered:l,className:r}){return e.jsx("div",{className:s("flex-1 min-h-0",l&&"flex items-center justify-center",r),children:t})}export{l as C,r as a};
import{j as e}from"./vendor-react-C341c8YC.js";import{n as s}from"./recharts-6XUQYgRA.js";import{B as t}from"./index-CPdqYR4z.js";function l({title:l,icon:r,badge:i,subtitle:a,actions:c,iconColor:n="text-icon-card-title",largeTitle:x=!1,listHeader:m=!1,stackActionsOnMobile:d=!1}){return d&&c?e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]}):e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),c&&e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]})}function r({children:t,centered:l,className:r}){return e.jsx("div",{className:s("flex-1 min-h-0",l&&"flex items-center justify-center",r),children:t})}export{l as C,r as a};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{r as e,j as t,as as n}from"./vendor-react-LAbPDfrQ.js";import{c as s}from"./recharts-D38YBQhj.js";import{K as r,aF as o,M as a,aG as c}from"./index-UmM6aLcb.js";const i={danger:{icon:"text-accent-danger",button:"bg-accent-danger hover:brightness-110 active:brightness-90"},warning:{icon:"text-accent-secondary",button:"bg-accent-secondary hover:brightness-110 active:brightness-90 text-bg-body"},default:{icon:"text-accent-primary",button:"bg-accent-primary hover:brightness-110 active:brightness-90 text-bg-body"}},l=e.memo(function({isOpen:e,title:l="Confirm",message:b,confirmLabel:d="Confirm",cancelLabel:m="Cancel",variant:x="default",onConfirm:g,onCancel:h}){const u=i[x];return t.jsxs(r,{open:e,onClose:h,size:"sm",children:[t.jsx(o,{icon:t.jsx(n,{className:s("w-5 h-5",u.icon)}),title:l,onClose:h}),t.jsx(a,{children:t.jsx("p",{className:"text-sm text-text-secondary",children:b})}),t.jsxs(c,{children:[t.jsx("button",{onClick:h,className:"flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-secondary bg-bg-subtle hover:bg-bg-elevated border border-border-subtle transition-colors",children:m}),t.jsx("button",{onClick:g,className:s("flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-primary transition-colors",u.button),children:d})]})]})});export{l as C};
import{r as e,j as t,at as n}from"./vendor-react-C341c8YC.js";import{n as s}from"./recharts-6XUQYgRA.js";import{N as r,aL as o,O as a,aM as c}from"./index-CPdqYR4z.js";const i={danger:{icon:"text-accent-danger",button:"bg-accent-danger hover:brightness-110 active:brightness-90"},warning:{icon:"text-accent-secondary",button:"bg-accent-secondary hover:brightness-110 active:brightness-90 text-bg-body"},default:{icon:"text-accent-primary",button:"bg-accent-primary hover:brightness-110 active:brightness-90 text-bg-body"}},l=e.memo(function({isOpen:e,title:l="Confirm",message:b,confirmLabel:d="Confirm",cancelLabel:m="Cancel",variant:x="default",onConfirm:g,onCancel:h}){const u=i[x];return t.jsxs(r,{open:e,onClose:h,size:"sm",children:[t.jsx(o,{icon:t.jsx(n,{className:s("w-5 h-5",u.icon)}),title:l,onClose:h}),t.jsx(a,{children:t.jsx("p",{className:"text-sm text-text-secondary",children:b})}),t.jsxs(c,{children:[t.jsx("button",{onClick:h,className:"flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-secondary bg-bg-subtle hover:bg-bg-elevated border border-border-subtle transition-colors",children:m}),t.jsx("button",{onClick:g,className:s("flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-primary transition-colors",u.button),children:d})]})]})});export{l as C};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
import{r as e,j as t,$ as o,a0 as n}from"./vendor-react-C341c8YC.js";import{n as a}from"./recharts-6XUQYgRA.js";const s={standard:"w-3 h-3",compact:"w-2.5 h-2.5",responsive:"w-2.5 h-2.5 sm:w-3 sm:h-3"};function c({children:c,copyValue:r,copy:i=!1,size:l="standard",className:p,title:u,color:d,truncate:m}){const[h,x]=e.useState(!1),[w,y]=e.useState(!1),f=e.useRef(null),v=r??("string"==typeof c?c:""),b=s[l],g=(()=>{if(!m||"string"!=typeof c)return c;const e=c,[t,o]=!0===m?[6,4]:m;return e.length<=t+o+3?e:`${e.slice(0,t)}${e.slice(-o)}`})(),j=e.useCallback(e=>{i&&(e.preventDefault(),e.stopPropagation(),f.current&&clearTimeout(f.current),function(e){var t;if("undefined"!=typeof window&&(window.isSecureContext||"https:"===window.location.protocol||"localhost"===window.location.hostname)&&(null==(t=navigator.clipboard)?void 0:t.writeText))return navigator.clipboard.writeText(e).catch(()=>{}),!0;try{const{scrollX:t,scrollY:o}=window,n=document.createElement("textarea");n.value=e,n.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none",n.setAttribute("readonly",""),document.body.appendChild(n),n.focus({preventScroll:!0}),n.select(),n.setSelectionRange(0,e.length);const a=document.execCommand("copy");return document.body.removeChild(n),window.scrollTo(t,o),a}catch(o){return!1}}(v),x(!0),f.current=setTimeout(()=>x(!1),2e3))},[i,v]),C="compact"===l?"data-box-compact":"responsive"===l?"data-box-responsive":"",N=i?u||`Click to copy: ${v}`:u;return i?t.jsxs("button",{type:"button",onClick:j,onMouseEnter:()=>y(!0),onMouseLeave:()=>y(!1),className:a("data-box",C,"cursor-pointer select-none gap-1","hover:bg-white/[0.08] hover:border-white/[0.12]","transition-all duration-200",d,p),title:N,"aria-label":`Copy ${v}`,children:[t.jsx("span",{className:a("transition-colors duration-200",h?"text-accent-success":""),children:g}),t.jsx("span",{className:a("flex items-center justify-center","compact"===l?"w-3 h-3":"w-3.5 h-3.5"),children:h?t.jsx(o,{className:a("text-accent-success",b)}):t.jsx(n,{className:a("transition-opacity duration-200",w?"opacity-70":"opacity-40",b)})})]}):t.jsx("span",{className:a("data-box",C,d,p),title:N,children:g})}export{c as D};
-1
View File
@@ -1 +0,0 @@
import{r as e,j as t,ag as o,ai as n}from"./vendor-react-LAbPDfrQ.js";import{c as a}from"./recharts-D38YBQhj.js";const s={standard:"w-3 h-3",compact:"w-2.5 h-2.5",responsive:"w-2.5 h-2.5 sm:w-3 sm:h-3"};function c({children:c,copyValue:r,copy:i=!1,size:l="standard",className:p,title:u,color:d,truncate:m}){const[h,x]=e.useState(!1),[w,y]=e.useState(!1),f=e.useRef(null),v=r??("string"==typeof c?c:""),b=s[l],g=(()=>{if(!m||"string"!=typeof c)return c;const e=c,[t,o]=!0===m?[6,4]:m;return e.length<=t+o+3?e:`${e.slice(0,t)}${e.slice(-o)}`})(),j=e.useCallback(e=>{i&&(e.preventDefault(),e.stopPropagation(),f.current&&clearTimeout(f.current),function(e){var t;if("undefined"!=typeof window&&(window.isSecureContext||"https:"===window.location.protocol||"localhost"===window.location.hostname)&&(null==(t=navigator.clipboard)?void 0:t.writeText))return navigator.clipboard.writeText(e).catch(()=>{}),!0;try{const{scrollX:t,scrollY:o}=window,n=document.createElement("textarea");n.value=e,n.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none",n.setAttribute("readonly",""),document.body.appendChild(n),n.focus({preventScroll:!0}),n.select(),n.setSelectionRange(0,e.length);const a=document.execCommand("copy");return document.body.removeChild(n),window.scrollTo(t,o),a}catch(o){return!1}}(v),x(!0),f.current=setTimeout(()=>x(!1),2e3))},[i,v]),C="compact"===l?"data-box-compact":"responsive"===l?"data-box-responsive":"",N=i?u||`Click to copy: ${v}`:u;return i?t.jsxs("button",{type:"button",onClick:j,onMouseEnter:()=>y(!0),onMouseLeave:()=>y(!1),className:a("data-box",C,"cursor-pointer select-none gap-1","hover:bg-white/[0.08] hover:border-white/[0.12]","transition-all duration-200",d,p),title:N,"aria-label":`Copy ${v}`,children:[t.jsx("span",{className:a("transition-colors duration-200",h?"text-accent-success":""),children:g}),t.jsx("span",{className:a("flex items-center justify-center","compact"===l?"w-3 h-3":"w-3.5 h-3.5"),children:h?t.jsx(o,{className:a("text-accent-success",b)}):t.jsx(n,{className:a("transition-opacity duration-200",w?"opacity-70":"opacity-40",b)})})]}):t.jsx("span",{className:a("data-box",C,d,p),title:N,children:g})}export{c as D};
+1
View File
@@ -0,0 +1 @@
import{r as e,j as t,m as s,$ as a,aJ as i,bW as n,aA as c,q as l,aq as r}from"./vendor-react-C341c8YC.js";import{n as m}from"./recharts-6XUQYgRA.js";import{N as d,aS as x,O as o,aT as p}from"./index-CPdqYR4z.js";function h({label:e,icon:s,status:i,detail:n}){return t.jsxs("div",{className:m("flex items-center gap-3 py-3 px-4 rounded-xl transition-all duration-300","active"===i&&"bg-accent-primary/10","complete"===i&&"bg-accent-primary/10 ring-2 ring-inset ring-accent-primary","pending"===i&&"opacity-40"),children:[t.jsx("div",{className:m("w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 transition-all duration-300","active"===i&&"bg-accent-primary/20","complete"===i&&"bg-accent-primary/20","pending"===i&&"bg-subtle-fill"),children:"complete"===i?t.jsx(a,{className:"w-4 h-4 text-accent-primary"}):"active"===i?t.jsx(r,{className:"w-4 h-4 animate-spin text-accent-primary"}):t.jsx("span",{className:"text-text-muted",children:s})}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("div",{className:m("text-sm font-medium transition-colors","active"===i&&"text-accent-primary","complete"===i&&"text-accent-primary","pending"===i&&"text-text-muted"),children:e}),n&&"pending"!==i&&t.jsx("div",{className:"text-xs text-text-muted mt-0.5 truncate",children:n})]})]})}const g=e.memo(function({isOpen:e,currentStep:r,packetCount:m,onClose:g}){const j="complete"===r,u=e=>{const t=["fetching","analyzing","building","discovering","complete"],s=t.indexOf(r),a=t.indexOf(e);return a<s?"complete":a===s?"active":"pending"},y=g??(()=>{});return t.jsx(d,{open:e,onClose:y,size:"sm",bottomSheet:!1,children:t.jsx(x,{isLoading:!j,borderRadius:16,children:t.jsx(o,{className:"p-6",children:j?t.jsxs("div",{className:"flex flex-col items-center py-6",children:[t.jsx(s.div,{variants:p,initial:"hidden",animate:"visible",className:"w-16 h-16 rounded-full flex items-center justify-center mb-4 bg-accent-primary/20",children:t.jsx(a,{className:"w-8 h-8 text-accent-primary"})}),t.jsx("h3",{className:"text-lg font-semibold text-accent-primary",children:"Ready!"})]}):t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"flex items-center gap-3 mb-5",children:[t.jsx("div",{className:"w-10 h-10 rounded-xl flex items-center justify-center bg-accent-primary/15",children:t.jsx(i,{className:"w-5 h-5 text-accent-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-base font-semibold text-text-primary",children:"Deep Analysis"}),t.jsx("p",{className:"text-xs text-text-muted",children:"Building mesh topology"})]})]}),t.jsxs("div",{className:"space-y-2",children:[t.jsx(h,{label:"Fetching Packets",icon:t.jsx(n,{className:"w-4 h-4"}),status:u("fetching"),detail:m>0?`${m.toLocaleString()} packets`:"Loading database..."}),t.jsx(h,{label:"Analyzing Database",icon:t.jsx(c,{className:"w-4 h-4"}),status:u("analyzing"),detail:"Processing packet paths"}),t.jsx(h,{label:"Building Topology",icon:t.jsx(i,{className:"w-4 h-4"}),status:u("building"),detail:"Computing mesh edges"}),t.jsx(h,{label:"Discovering Nodes",icon:t.jsx(l,{className:"w-4 h-4"}),status:u("discovering"),detail:"Viterbi HMM ghost detection"})]}),t.jsx("p",{className:"text-xs text-text-muted text-center mt-5",children:"This may take a few seconds..."})]})})})})});export{g as D};
@@ -1 +1 @@
import{r as o,j as e}from"./vendor-react-LAbPDfrQ.js";import{c as t}from"./recharts-D38YBQhj.js";const l={hero:{mobile:12},"hero-tall":{mobile:12},"hero-auto":{mobile:12},panel:{mobile:12,md:6},feature:{mobile:12,md:6,lg:4},standard:{mobile:12,sm:6,lg:4,xl:3},compact:{mobile:6,lg:3},widget:{mobile:6,sm:4,md:3,lg:2},auto:{mobile:12}},a={hero:"bento-row-hero","hero-tall":"bento-row-hero-tall","hero-auto":"bento-row-hero-auto",panel:"bento-row-panel",feature:"bento-row-feature",standard:"bento-row-standard",compact:"bento-row-compact",widget:"bento-row-widget",auto:"bento-row-auto"};function n({template:n,children:r,className:s,gap:c}){const i=l[n],b=a[n],d="none"===c?"gap-0":"sm"===c?"bento-gap-sm":"lg"===c?"bento-gap-lg":"bento-gap",p=o.Children.map(r,t=>o.isValidElement(t)?t.type===m?t:e.jsx(m,{span:i.mobile,sm:i.sm,md:i.md,lg:i.lg,xl:i.xl,children:t}):t);return e.jsx("div",{className:t("bento-row",b,d,s),children:p})}function r(o,e=""){const t=e?`${e}:`:"";return"full"===o?`${t}col-span-full`:"auto"===o?`${t}col-auto`:1.5===o?`${t}bento-col-1-5`:`${t}bento-col-${o}`}function m({children:o,span:l,sm:a,md:n,lg:m,xl:s,className:c}){const i=t("bento-cell",r(l),a&&r(a,"sm"),n&&r(n,"md"),m&&r(m,"lg"),s&&r(s,"xl"),c);return e.jsx("div",{className:i,children:o})}export{m as C,n as R};
import{r as o,j as e}from"./vendor-react-C341c8YC.js";import{n as t}from"./recharts-6XUQYgRA.js";const l={hero:{mobile:12},"hero-tall":{mobile:12},"hero-auto":{mobile:12},panel:{mobile:12,md:6},feature:{mobile:12,md:6,lg:4},standard:{mobile:12,sm:6,lg:4,xl:3},compact:{mobile:6,lg:3},widget:{mobile:6,sm:4,md:3,lg:2},auto:{mobile:12}},a={hero:"bento-row-hero","hero-tall":"bento-row-hero-tall","hero-auto":"bento-row-hero-auto",panel:"bento-row-panel",feature:"bento-row-feature",standard:"bento-row-standard",compact:"bento-row-compact",widget:"bento-row-widget",auto:"bento-row-auto"};function n({template:n,children:r,className:s,gap:c}){const i=l[n],b=a[n],d="none"===c?"gap-0":"sm"===c?"bento-gap-sm":"lg"===c?"bento-gap-lg":"bento-gap",p=o.Children.map(r,t=>o.isValidElement(t)?t.type===m?t:e.jsx(m,{span:i.mobile,sm:i.sm,md:i.md,lg:i.lg,xl:i.xl,children:t}):t);return e.jsx("div",{className:t("bento-row",b,d,s),children:p})}function r(o,e=""){const t=e?`${e}:`:"";return"full"===o?`${t}col-span-full`:"auto"===o?`${t}col-auto`:1.5===o?`${t}bento-col-1-5`:`${t}bento-col-${o}`}function m({children:o,span:l,sm:a,md:n,lg:m,xl:s,className:c}){const i=t("bento-cell",r(l),a&&r(a,"sm"),n&&r(n,"md"),m&&r(m,"lg"),s&&r(s,"xl"),c);return e.jsx("div",{className:i,children:o})}export{m as C,n as R};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{r as s,j as e,F as a,bl as t,bm as l}from"./vendor-react-LAbPDfrQ.js";import{c as r}from"./recharts-D38YBQhj.js";import{ao as i,ap as o,b as n,aq as c,r as m,am as x,ar as d}from"./index-UmM6aLcb.js";import{u as p}from"./usePolling-Dc-LnIv7.js";import{P as h,b as j,a as u,L as g}from"./PageLayout-COD3p9tO.js";import{C as f}from"./Card-xXPckJMj.js";import"./vendor-core-WoOfkQwm.js";import"./deckgl-DTsmDcfs.js";const b=s.memo(function({log:s}){return e.jsx("div",{className:"p-3 rounded-2xl bg-subtle-fill hover:bg-subtle-fill-strong transition-colors",children:e.jsxs("div",{className:"flex items-baseline gap-3",children:[e.jsx("span",{className:r("type-data-sm w-14 shrink-0",d(s.level)),children:s.level}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"type-data-sm text-text-primary break-words whitespace-pre-wrap",children:s.message}),e.jsx("p",{className:"type-data-xs text-text-muted mt-1",children:new Date(s.timestamp).toLocaleString()})]})]})})});function v({showDebug:s,onToggle:a}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:r("type-data-sm",s?"text-accent-tertiary":"text-accent-primary"),children:s?"DEBUG":"INFO"}),e.jsx("button",{onClick:a,className:r("relative w-10 h-5 rounded-full transition-colors duration-200",s?"bg-accent-tertiary":"bg-accent-primary"),role:"switch","aria-checked":s,children:e.jsx("span",{className:r("absolute top-[2px] left-[2px] w-4 h-4 bg-white rounded-full shadow-sm transition-transform duration-200",s?"translate-x-5":"translate-x-0")})})]})}function N(){const d=i(),N=o(),w=n(),y=c(),k=m(),[C,D]=s.useState(!1),L=s.useCallback(()=>{D(s=>!s)},[]),P=C?d:d.filter(s=>"DEBUG"!==s.level);return p(y,x.logs,w),e.jsxs(h,{children:[e.jsx(j,{title:"System Logs",icon:e.jsx(a,{}),controls:e.jsx(v,{showDebug:C,onToggle:L})}),e.jsxs(u,{noPadding:!0,children:[e.jsx(f,{listHeader:!0,icon:e.jsx(a,{className:"icon-sm"}),title:"Log Entries",actions:e.jsx("button",{onClick:()=>k(!w),className:r("transition-colors",w?"text-signal-critical hover:text-signal-critical/80":"text-accent-primary hover:text-accent-primary/80 animate-pulse-slow"),title:w?"Pause":"Resume",children:w?e.jsx(t,{className:"w-5 h-5"}):e.jsx(l,{className:"w-5 h-5"})})}),e.jsx("div",{className:"space-y-2 max-h-[calc(100vh-300px)] sm:max-h-[calc(100vh-250px)] overflow-y-auto p-4",children:N&&0===d.length?e.jsx(g,{count:10}):0===P.length?e.jsx("div",{className:"text-center py-12 text-text-muted",children:0===d.length?"No logs available":"No logs match selected filters"}):P.map((s,a)=>e.jsx(b,{log:s},`${s.timestamp}-${a}`))})]})]})}export{N as default};
import{r as s,j as e,F as a,bA as t,bB as l}from"./vendor-react-C341c8YC.js";import{n as r}from"./recharts-6XUQYgRA.js";import{au as i,av as n,d as o,aw as c,v as m,as as x,ax as d}from"./index-CPdqYR4z.js";import{u as p}from"./usePolling-CtRLadGa.js";import{P as h,b as j,a as u,L as g}from"./PageLayout-CcoYWyzO.js";import{C as f}from"./Card-BeZKc0xw.js";import"./vendor-core-WoOfkQwm.js";import"./deckgl-DTsmDcfs.js";const v=s.memo(function({log:s}){return e.jsx("div",{className:"p-3 rounded-2xl bg-subtle-fill hover:bg-subtle-fill-strong transition-colors",children:e.jsxs("div",{className:"flex items-baseline gap-3",children:[e.jsx("span",{className:r("type-data-sm w-14 shrink-0",d(s.level)),children:s.level}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"type-data-sm text-text-primary break-words whitespace-pre-wrap",children:s.message}),e.jsx("p",{className:"type-data-xs text-text-muted mt-1",children:new Date(s.timestamp).toLocaleString()})]})]})})});function b({showDebug:s,onToggle:a}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:r("type-data-sm",s?"text-accent-tertiary":"text-accent-primary"),children:s?"DEBUG":"INFO"}),e.jsx("button",{onClick:a,className:r("relative w-10 h-5 rounded-full transition-colors duration-200",s?"bg-accent-tertiary":"bg-accent-primary"),role:"switch","aria-checked":s,children:e.jsx("span",{className:r("absolute top-[2px] left-[2px] w-4 h-4 bg-white rounded-full shadow-sm transition-transform duration-200",s?"translate-x-5":"translate-x-0")})})]})}function N(){const d=i(),N=n(),w=o(),y=c(),k=m(),[C,D]=s.useState(!1),L=s.useCallback(()=>{D(s=>!s)},[]),P=C?d:d.filter(s=>"DEBUG"!==s.level);return p(y,x.logs,w),e.jsxs(h,{children:[e.jsx(j,{title:"System Logs",icon:e.jsx(a,{}),controls:e.jsx(b,{showDebug:C,onToggle:L})}),e.jsxs(u,{noPadding:!0,children:[e.jsx(f,{listHeader:!0,icon:e.jsx(a,{className:"icon-sm"}),title:"Log Entries",actions:e.jsx("button",{onClick:()=>k(!w),className:r("transition-colors",w?"text-signal-critical hover:text-signal-critical/80":"text-accent-primary hover:text-accent-primary/80 animate-pulse-slow"),title:w?"Pause":"Resume",children:w?e.jsx(t,{className:"w-5 h-5"}):e.jsx(l,{className:"w-5 h-5"})})}),e.jsx("div",{className:"space-y-2 max-h-[calc(100vh-300px)] sm:max-h-[calc(100vh-250px)] overflow-y-auto p-4",children:N&&0===d.length?e.jsx(g,{count:10}):0===P.length?e.jsx("div",{className:"text-center py-12 text-text-muted",children:0===d.length?"No logs available":"No logs match selected filters"}):P.map((s,a)=>e.jsx(v,{log:s},`${s.timestamp}-${a}`))})]})]})}export{N as default};
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{j as e,E as s}from"./vendor-react-LAbPDfrQ.js";import{a as t}from"./PageLayout-COD3p9tO.js";import{D as a}from"./DataBox-ChCyaBc1.js";import{aE as r}from"./index-UmM6aLcb.js";import{C as l}from"./Card-xXPckJMj.js";function c({nodeName:c,repeaterVersion:m,coreVersion:i,localHash:n,publicKey:d}){return e.jsxs(t,{children:[e.jsx(l,{icon:e.jsx(s,{}),title:"Node Information",largeTitle:!0}),e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4",children:[e.jsxs("div",{className:"min-w-0 col-span-2 sm:col-span-1",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Node Name"}),e.jsx("p",{className:"type-body text-text-primary mt-0.5 sm:mt-1 truncate",title:c,children:c})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Repeater"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${m}`,children:["v",m]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Core"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${i}`,children:["v",i]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Console"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${r}`,children:["v",r]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Local Hash"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:n?e.jsx(a,{copy:!0,size:"compact",children:n}):e.jsx("span",{className:"type-data-sm text-text-secondary",children:"N/A"})})]})]}),d&&e.jsxs("div",{className:"mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-border-subtle",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Public Key"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:e.jsx(a,{copy:!0,size:"responsive",children:d})})]})]})}export{c as N};
import{j as e,E as s}from"./vendor-react-C341c8YC.js";import{a as t}from"./PageLayout-CcoYWyzO.js";import{D as a}from"./DataBox-CRX76VsB.js";import{ay as r}from"./index-CPdqYR4z.js";import{C as l}from"./Card-BeZKc0xw.js";function c({nodeName:c,repeaterVersion:m,coreVersion:i,localHash:n,publicKey:d}){return e.jsxs(t,{children:[e.jsx(l,{icon:e.jsx(s,{}),title:"Node Information",largeTitle:!0}),e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4",children:[e.jsxs("div",{className:"min-w-0 col-span-2 sm:col-span-1",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Node Name"}),e.jsx("p",{className:"type-body text-text-primary mt-0.5 sm:mt-1 truncate",title:c,children:c})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Repeater"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${m}`,children:["v",m]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Core"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${i}`,children:["v",i]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Console"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${r}`,children:["v",r]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Local Hash"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:n?e.jsx(a,{copy:!0,size:"compact",children:n}):e.jsx("span",{className:"type-data-sm text-text-secondary",children:"N/A"})})]})]}),d&&e.jsxs("div",{className:"mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-border-subtle",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Public Key"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:e.jsx(a,{copy:!0,size:"responsive",children:d})})]})]})}export{c as N};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{j as s}from"./vendor-react-LAbPDfrQ.js";import{c as e}from"./recharts-D38YBQhj.js";import"./index-UmM6aLcb.js";const a=[45,72,33,58,80,42,65,28,55,75,38,62];function l({className:a,style:l}){return s.jsx("div",{className:e("animate-pulse bg-white/[0.06] rounded",a),style:l})}function c(){return s.jsx("div",{className:"p-3 rounded-lg border border-border-subtle bg-bg-subtle",children:s.jsxs("div",{className:"flex items-start gap-3",children:[s.jsx(l,{className:"w-14 h-6 rounded shrink-0"}),s.jsxs("div",{className:"flex-1 min-w-0 space-y-2",children:[s.jsx(l,{className:"h-4 w-full"}),s.jsx(l,{className:"h-4 w-3/4"}),s.jsx(l,{className:"h-3 w-32 mt-1"})]})]})})}function r({count:e=8}){return s.jsx("div",{className:"space-y-2",children:Array.from({length:e}).map((e,a)=>s.jsx(c,{},a))})}function i(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx(l,{className:"h-8 w-20"}),s.jsxs("div",{className:"flex-1 flex flex-col justify-end gap-2",children:[s.jsx(l,{className:"h-3 w-full"}),s.jsx(l,{className:"h-3 w-3/4"})]})]})}function n(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx("div",{className:"flex-1 flex items-end gap-1",children:a.slice(0,8).map((e,a)=>s.jsx(l,{className:"flex-1",style:{height:`${e}%`}},a))})]})}function t({rows:e=5}){return s.jsxs("div",{className:"flex flex-col h-full","aria-hidden":"true",children:[s.jsx("div",{className:"pb-3 border-b border-border-subtle",children:s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]})}),s.jsx("div",{className:"flex-1 pt-3 flex flex-col gap-3",children:Array.from({length:e}).map((e,a)=>s.jsx(l,{className:"h-6 w-full"},a))})]})}function d({children:a,className:l}){return s.jsx("div",{className:e("section-gap",l),children:a})}function x({title:e,icon:a,controls:l,subtitle:c}){return s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-3",children:[s.jsxs("h1",{className:"type-title text-text-primary flex items-center gap-2 sm:gap-3 h-9 min-w-0",children:[a&&s.jsx("span",{className:"w-5 h-5 sm:w-6 sm:h-6 text-icon-page-title flex-shrink-0",children:a}),s.jsx("span",{className:"truncate",children:e})]}),l&&s.jsx("div",{className:"flex items-center gap-2 sm:gap-3 h-9 flex-shrink-0",children:l})]}),c&&s.jsx("div",{children:c})]})}const m={sm:"card-sm",md:"card-md",lg:"card-lg",hero:"card-hero",auto:"card-auto"};function h({children:a,size:l,compact:c,noPadding:r,className:d,style:x,onClick:h,isLoaded:o=!0,skeletonType:f="card"}){return s.jsxs("div",{className:e("glass-card h-full flex flex-col relative",!r&&(c?"card-padding-sm":"card-padding"),l&&m[l],d),style:x,onClick:h,children:[a,!o&&(()=>{switch(f){case"chart":return s.jsx(n,{});case"list":return s.jsx(t,{});default:return s.jsx(i,{})}})()]})}export{i as C,r as L,d as P,l as S,h as a,x as b};
import{j as s}from"./vendor-react-C341c8YC.js";import{n as e}from"./recharts-6XUQYgRA.js";import"./index-CPdqYR4z.js";const a=[45,72,33,58,80,42,65,28,55,75,38,62];function l({className:a,style:l}){return s.jsx("div",{className:e("animate-pulse bg-white/[0.06] rounded",a),style:l})}function c(){return s.jsx("div",{className:"p-3 rounded-lg border border-border-subtle bg-bg-subtle",children:s.jsxs("div",{className:"flex items-start gap-3",children:[s.jsx(l,{className:"w-14 h-6 rounded shrink-0"}),s.jsxs("div",{className:"flex-1 min-w-0 space-y-2",children:[s.jsx(l,{className:"h-4 w-full"}),s.jsx(l,{className:"h-4 w-3/4"}),s.jsx(l,{className:"h-3 w-32 mt-1"})]})]})})}function r({count:e=8}){return s.jsx("div",{className:"space-y-2",children:Array.from({length:e}).map((e,a)=>s.jsx(c,{},a))})}function i(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx(l,{className:"h-8 w-20"}),s.jsxs("div",{className:"flex-1 flex flex-col justify-end gap-2",children:[s.jsx(l,{className:"h-3 w-full"}),s.jsx(l,{className:"h-3 w-3/4"})]})]})}function n(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx("div",{className:"flex-1 flex items-end gap-1",children:a.slice(0,8).map((e,a)=>s.jsx(l,{className:"flex-1",style:{height:`${e}%`}},a))})]})}function t({rows:e=5}){return s.jsxs("div",{className:"flex flex-col h-full","aria-hidden":"true",children:[s.jsx("div",{className:"pb-3 border-b border-border-subtle",children:s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]})}),s.jsx("div",{className:"flex-1 pt-3 flex flex-col gap-3",children:Array.from({length:e}).map((e,a)=>s.jsx(l,{className:"h-6 w-full"},a))})]})}function d({children:a,className:l}){return s.jsx("div",{className:e("section-gap",l),children:a})}function x({title:e,icon:a,controls:l,subtitle:c}){return s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-3",children:[s.jsxs("h1",{className:"type-title text-text-primary flex items-center gap-2 sm:gap-3 h-9 min-w-0",children:[a&&s.jsx("span",{className:"w-5 h-5 sm:w-6 sm:h-6 text-icon-page-title flex-shrink-0",children:a}),s.jsx("span",{className:"truncate",children:e})]}),l&&s.jsx("div",{className:"flex items-center gap-2 sm:gap-3 h-9 flex-shrink-0",children:l})]}),c&&s.jsx("div",{children:c})]})}const m={sm:"card-sm",md:"card-md",lg:"card-lg",hero:"card-hero",auto:"card-auto"};function h({children:a,size:l,compact:c,noPadding:r,className:d,style:x,onClick:h,isLoaded:o=!0,skeletonType:f="card"}){return s.jsxs("div",{className:e("glass-card h-full flex flex-col relative",!r&&(c?"card-padding-sm":"card-padding"),l&&m[l],d),style:x,onClick:h,children:[a,!o&&(()=>{switch(f){case"chart":return s.jsx(n,{});case"list":return s.jsx(t,{});default:return s.jsx(i,{})}})()]})}export{i as C,r as L,d as P,l as S,h as a,x as b};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{r as e,j as o}from"./vendor-react-LAbPDfrQ.js";const t=e.memo(function({ranges:e,selectedIndex:t,onSelect:a,isPending:l}){return o.jsx("div",{className:"toggle-group flex-shrink-0 overflow-x-auto "+(l?"opacity-70":""),children:e.map((e,l)=>o.jsx("button",{onClick:()=>a(l),className:"toggle-group-item "+(t===l?"active":""),children:e.label},e.label))})});export{t as T};
import{r as e,j as o}from"./vendor-react-C341c8YC.js";const t=e.memo(function({ranges:e,selectedIndex:t,onSelect:a,isPending:l}){return o.jsx("div",{className:"toggle-group flex-shrink-0 overflow-x-auto "+(l?"opacity-70":""),children:e.map((e,l)=>o.jsx("button",{onClick:()=>a(l),className:"toggle-group-item "+(t===l?"active":""),children:e.label},e.label))})});export{t as T};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
import{n as t,aP as e}from"./index-CPdqYR4z.js";function n(t){if(Array.isArray(t))return t;if("string"==typeof t&&t.startsWith("["))try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}return[]}function o(o,r,s){const a=new Map;for(const e of r){const n=t(e);a.has(n)||a.set(n,e)}const c=new Map,i=new Map;for(const t of o){const o=t.route??t.route_type;if(!e(o))continue;const r=n(t.original_path);if(0===r.length)continue;const f=r.map(t=>t.toUpperCase());if(!t.transmitted&&f.length>=2){const t=f[f.length-2];if(t){const e=a.get(t);e&&i.set(e,(i.get(e)??0)+1)}}if(f.includes(s))for(const t of f){if(t===s)continue;const e=a.get(t);e&&c.set(e,(c.get(e)??0)+1)}}let f=0,u=0;for(const t of r)f=Math.max(f,c.get(t)??0),u=Math.max(u,i.get(t)??0);const h=new Map;let g=0,l=0,p=0;for(const t of r){const e=c.get(t)??0,n=i.get(t)??0,o=f>0?Math.round(e/f*100):0,r=u>0?Math.round(n/u*100):0,s=o+r;h.set(t,{hash:t,listenerCount:e,loudCount:n,listenerScore:o,loudScore:r,blendedScore:s}),g=Math.max(g,o),l=Math.max(l,r),p=Math.max(p,s)}return{scores:h,maxListenerScore:g,maxLoudScore:l,maxBlendedScore:p}}const r={YELLOW:"#FFB224",GREEN:"#46A758",RED:"#E5484D",GRAY:"#505050"};export{r as L,o as c};
-1
View File
@@ -1 +0,0 @@
import{k as t,aL as e}from"./index-UmM6aLcb.js";function o(t){if(Array.isArray(t))return t;if("string"==typeof t&&t.startsWith("["))try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}return[]}function n(n,r,s){const a=new Map;for(const e of r){const o=t(e);a.has(o)||a.set(o,e)}const c=new Map,i=new Map;for(const t of n){const n=t.route??t.route_type;if(!e(n))continue;const r=o(t.original_path);if(0===r.length)continue;const f=r.map(t=>t.toUpperCase());if(!t.transmitted&&f.length>=2){const t=f[f.length-2];if(t){const e=a.get(t);e&&i.set(e,(i.get(e)??0)+1)}}if(f.includes(s))for(const t of f){if(t===s)continue;const e=a.get(t);e&&c.set(e,(c.get(e)??0)+1)}}let f=0,u=0;for(const t of r)f=Math.max(f,c.get(t)??0),u=Math.max(u,i.get(t)??0);const h=new Map;let g=0,l=0,p=0;for(const t of r){const e=c.get(t)??0,o=i.get(t)??0,n=f>0?Math.round(e/f*100):0,r=u>0?Math.round(o/u*100):0,s=n+r;h.set(t,{hash:t,listenerCount:e,loudCount:o,listenerScore:n,loudScore:r,blendedScore:s}),g=Math.max(g,n),l=Math.max(l,r),p=Math.max(p,s)}return{scores:h,maxListenerScore:g,maxLoudScore:l,maxBlendedScore:p}}const r={YELLOW:"#FFB224",GREEN:"#46A758",RED:"#E5484D",GRAY:"#505050"};export{r as L,n as c};
@@ -1 +1 @@
import{ay as t}from"./index-UmM6aLcb.js";async function e(e,r=10){return t("/api/ping_neighbor",{method:"POST",body:JSON.stringify({target_id:e,timeout:r})})}const r=["Chat Node","Repeater","Room Server","Hybrid Node","Unknown"];async function s(s,o=10){if(o<1||o>60)return{success:!1,error:"Timeout must be 1-60 seconds"};let n;const a=s.match(/^(0x)?([0-9a-fA-F]{1,2})$/);if(a)n=`0x${a[2].padStart(2,"0")}`;else{const e=await async function(e){const s=e.toLowerCase();for(const o of r)try{const e=await t(`/api/adverts_by_contact_type?contact_type=${encodeURIComponent(o)}&hours=168`),r=e.success&&e.data?e.data:e,n=(Array.isArray(r)?r:[]).find(t=>t.node_name&&t.node_name.toLowerCase()===s);if(n&&n.pubkey)return`0x${n.pubkey.substring(0,2)}`}catch{continue}return null}(s);if(!e)return{success:!1,error:`Node '${s}' not found`};n=e}const c=await e(n,o);if(!c.success||!c.data)return{success:!1,error:c.error||"Ping failed"};const i=(u=c.data).rtt_ms>500||u.rssi<-120?"Poor":u.rtt_ms>250||u.rssi<-100?"Fair":u.rtt_ms>100||u.rssi<-80?"Good":"Excellent";var u;return{success:!0,data:{...c.data,quality:i}}}export{s as a,e as p};
import{aF as t}from"./index-CPdqYR4z.js";async function e(e,r=10){return t("/api/ping_neighbor",{method:"POST",body:JSON.stringify({target_id:e,timeout:r})})}const r=["Chat Node","Repeater","Room Server","Hybrid Node","Unknown"];async function s(s,o=10){if(o<1||o>60)return{success:!1,error:"Timeout must be 1-60 seconds"};let n;const a=s.match(/^(0x)?([0-9a-fA-F]{1,2})$/);if(a)n=`0x${a[2].padStart(2,"0")}`;else{const e=await async function(e){const s=e.toLowerCase();for(const o of r)try{const e=await t(`/api/adverts_by_contact_type?contact_type=${encodeURIComponent(o)}&hours=168`),r=e.success&&e.data?e.data:e,n=(Array.isArray(r)?r:[]).find(t=>t.node_name&&t.node_name.toLowerCase()===s);if(n&&n.pubkey)return`0x${n.pubkey.substring(0,2)}`}catch{continue}return null}(s);if(!e)return{success:!1,error:`Node '${s}' not found`};n=e}const c=await e(n,o);if(!c.success||!c.data)return{success:!1,error:c.error||"Ping failed"};const i=(u=c.data).rtt_ms>500||u.rssi<-120?"Poor":u.rtt_ms>250||u.rssi<-100?"Fair":u.rtt_ms>100||u.rssi<-80?"Good":"Excellent";var u;return{success:!0,data:{...c.data,quality:i}}}export{s as a,e as p};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
import{r}from"./vendor-react-LAbPDfrQ.js";function e(e,t,n=!0,c=!1){const u=r.useRef(e);r.useEffect(()=>{u.current=e},[e]),r.useEffect(()=>{if(!n)return;c||u.current();const r=setInterval(()=>{u.current()},t);return()=>clearInterval(r)},[t,n,c])}export{e as u};
import{r}from"./vendor-react-C341c8YC.js";function e(e,t,n=!0,c=!1){const u=r.useRef(e);r.useEffect(()=>{u.current=e},[e]),r.useEffect(()=>{if(!n)return;c||u.current();const r=setInterval(()=>{u.current()},t);return()=>clearInterval(r)},[t,n,c])}export{e as u};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
@@ -39,10 +39,10 @@
--font-data: 'JetBrains Mono', 'SF Mono', Monaco, monospace;
}
</style>
<script type="module" crossorigin src="/assets/index-UmM6aLcb.js"></script>
<script type="module" crossorigin src="/assets/index-CPdqYR4z.js"></script>
<link rel="modulepreload" crossorigin href="/assets/vendor-core-WoOfkQwm.js">
<link rel="modulepreload" crossorigin href="/assets/vendor-react-LAbPDfrQ.js">
<link rel="stylesheet" crossorigin href="/assets/index-BbajDJDJ.css">
<link rel="modulepreload" crossorigin href="/assets/vendor-react-C341c8YC.js">
<link rel="stylesheet" crossorigin href="/assets/index-CIefRaAd.css">
</head>
<body>
<div id="root"></div>
+2 -4
View File
@@ -1,6 +1,6 @@
{
"name": "pymc_console",
"version": "0.9.193",
"version": "0.9.194",
"description": "Vite + React Dashboard for pyMC_Repeater",
"private": true,
"type": "module",
@@ -14,6 +14,7 @@
"lint": "eslint"
},
"dependencies": {
"@cosmograph/react": "^2.0.1",
"@deck.gl/aggregation-layers": "^9.2.5",
"@deck.gl/core": "^9.2.5",
"@deck.gl/geo-layers": "^9.2.5",
@@ -30,14 +31,12 @@
"@fontsource/rubik-mono-one": "^5.2.8",
"@fontsource/source-code-pro": "^5.2.7",
"@headlessui/react": "^2.2.9",
"@types/leaflet": "^1.9.21",
"@types/three": "^0.182.0",
"axios": "^1.13.2",
"clsx": "^2.1.1",
"d3-contour": "^4.0.2",
"d3-geo": "^3.1.1",
"h3-js": "^4.4.0",
"leaflet": "^1.9.4",
"lucide-react": "^0.559.0",
"maplibre-gl": "^5.15.0",
"motion": "^12.29.0",
@@ -45,7 +44,6 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-is": "^19.2.3",
"react-leaflet": "^4.2.1",
"react-map-gl": "^8.1.0",
"react-router-dom": "^7.1.1",
"recharts": "^3.5.1",