@kwirthmagnify/kwirth-plugin-status 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/front.js +41 -5
- package/package.json +1 -1
package/front.js
CHANGED
|
@@ -172,8 +172,13 @@
|
|
|
172
172
|
return filas();
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
|
-
var
|
|
175
|
+
var VELOCIDAD_INICIAL = 20;
|
|
176
|
+
var StatusDiagram = ({ inventory, active, autoRefresh }) => {
|
|
176
177
|
const theme = (0, import_material2.useTheme)();
|
|
178
|
+
const vueltas = import_react2.default.useRef({ inventario: inventory, n: 0 });
|
|
179
|
+
if (vueltas.current.inventario !== inventory) vueltas.current = { inventario: inventory, n: vueltas.current.n + 1 };
|
|
180
|
+
const frenada = `statusFrenada${vueltas.current.n % 2}`;
|
|
181
|
+
const nodosPintados = import_react2.default.useRef(/* @__PURE__ */ new Map());
|
|
177
182
|
const [posiciones, setPosiciones] = import_react2.default.useState(void 0);
|
|
178
183
|
const [seleccionado, setSeleccionado] = import_react2.default.useState(void 0);
|
|
179
184
|
const colores = {
|
|
@@ -201,7 +206,12 @@
|
|
|
201
206
|
...productores.map((p) => ({
|
|
202
207
|
id: p.id,
|
|
203
208
|
position: { x: 0, y: 0 },
|
|
204
|
-
|
|
209
|
+
/*
|
|
210
|
+
SOLO lo que se pinta (o lo que usa el layout). Aquí llegaron a ir los suscriptores y la
|
|
211
|
+
salud sin que nadie los leyera, y como el nodo se rehace cuando cambia su data (ver
|
|
212
|
+
'colocados'), un contador que variaba entre fotos hacía parpadear nodos idénticos.
|
|
213
|
+
*/
|
|
214
|
+
data: { label: p.displayName, esProductor: true },
|
|
205
215
|
// Con el grafo en vertical, la arista tiene que salir por ABAJO y entrar por ARRIBA; si
|
|
206
216
|
// no, React Flow las saca por los lados y los cables dan un rodeo absurdo.
|
|
207
217
|
sourcePosition: import_react3.Position.Bottom,
|
|
@@ -286,7 +296,15 @@
|
|
|
286
296
|
if (!posiciones) {
|
|
287
297
|
return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { p: 3 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", color: "text.secondary" }, "Laying out the graph\u2026"));
|
|
288
298
|
}
|
|
289
|
-
const colocados = nodos.map((n) =>
|
|
299
|
+
const colocados = nodos.map((n) => {
|
|
300
|
+
const position = posiciones[n.id] ?? { x: 0, y: 0 };
|
|
301
|
+
const firma = JSON.stringify([n.data, n.style, position]);
|
|
302
|
+
const previo = nodosPintados.current.get(n.id);
|
|
303
|
+
if (previo?.firma === firma) return previo.nodo;
|
|
304
|
+
const nodo = { ...n, position };
|
|
305
|
+
nodosPintados.current.set(n.id, { firma, nodo });
|
|
306
|
+
return nodo;
|
|
307
|
+
});
|
|
290
308
|
return /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { sx: { height: "100%", display: "flex", flexDirection: "column", minHeight: 0 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", spacing: 1, alignItems: "center", sx: { mb: 1 } }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "caption", color: "text.secondary" }, "A line means ", /* @__PURE__ */ import_react2.default.createElement("b", null, "an active subscription"), ". A ", /* @__PURE__ */ import_react2.default.createElement("b", null, "moving line"), " means its producer is delivering right now \u2014 but not how much goes to each consumer: that is measured per component, not per line.", " ", "Click a node to highlight what it is connected to; click the background to clear.")), (anonimos > 0 || canalesSueltos > 0) && /* @__PURE__ */ import_react2.default.createElement(import_material2.Stack, { direction: "row", spacing: 1, sx: { mb: 1 } }, anonimos > 0 && /* @__PURE__ */ import_react2.default.createElement(
|
|
291
309
|
import_material2.Chip,
|
|
292
310
|
{
|
|
@@ -309,7 +327,25 @@
|
|
|
309
327
|
},
|
|
310
328
|
"& .react-flow__controls-button:hover": { background: theme.palette.action.hover },
|
|
311
329
|
"& .react-flow__controls-button svg": { fill: theme.palette.text.primary },
|
|
312
|
-
"& .react-flow__attribution": { display: "none" }
|
|
330
|
+
"& .react-flow__attribution": { display: "none" },
|
|
331
|
+
/*
|
|
332
|
+
Con auto-refresco, la línea viva arranca a la velocidad de serie y va FRENANDO hasta
|
|
333
|
+
pararse justo cuando llega la siguiente foto: lo que se ha visto moverse es lo que
|
|
334
|
+
pasó en ese intervalo, y la línea no sigue diciendo "ahora" cuando el dato ya es viejo.
|
|
335
|
+
En manual no hay intervalo que agotar, así que se queda la animación continua de serie.
|
|
336
|
+
|
|
337
|
+
El recorrido sale de la curva: con ease-out cuadrática la velocidad inicial es 2·D/T,
|
|
338
|
+
así que D = VELOCIDAD_INICIAL·T/2 arranca igual que la de serie, sin tirón.
|
|
339
|
+
*/
|
|
340
|
+
...autoRefresh > 0 ? {
|
|
341
|
+
[`@keyframes ${frenada}`]: {
|
|
342
|
+
from: { strokeDashoffset: VELOCIDAD_INICIAL * autoRefresh / 2 },
|
|
343
|
+
to: { strokeDashoffset: 0 }
|
|
344
|
+
},
|
|
345
|
+
"& .react-flow__edge.animated path": {
|
|
346
|
+
animation: `${frenada} ${autoRefresh}s cubic-bezier(0.5, 1, 0.89, 1) 1 forwards`
|
|
347
|
+
}
|
|
348
|
+
} : {}
|
|
313
349
|
} }, /* @__PURE__ */ import_react2.default.createElement(
|
|
314
350
|
import_react3.ReactFlow,
|
|
315
351
|
{
|
|
@@ -480,7 +516,7 @@
|
|
|
480
516
|
/* @__PURE__ */ import_react4.default.createElement(import_material3.MenuItem, { value: 15 }, "Every 15s"),
|
|
481
517
|
/* @__PURE__ */ import_react4.default.createElement(import_material3.MenuItem, { value: 30 }, "Every 30s"),
|
|
482
518
|
/* @__PURE__ */ import_react4.default.createElement(import_material3.MenuItem, { value: 60 }, "Every minute")
|
|
483
|
-
), /* @__PURE__ */ import_react4.default.createElement(import_material3.Tooltip, { title: "Take a new snapshot" }, /* @__PURE__ */ import_react4.default.createElement(import_material3.IconButton, { size: "small", onClick: refresh }, /* @__PURE__ */ import_react4.default.createElement(import_icons.Refresh, { fontSize: "small" })))), /* @__PURE__ */ import_react4.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1 } }, "Snapshot taken at ", new Date(inventory.takenAt).toLocaleTimeString(), data.autoRefresh ? ` \u2014 refreshing every ${data.autoRefresh}s while this tab is open` : " \u2014 it does not refresh on its own", ".", " ", "Delivered counts since each component started; the rate is measured against your previous snapshot."), /* @__PURE__ */ import_react4.default.createElement(import_material3.Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", overflowY: vista === "table" ? "auto" : "hidden", overflowX: "hidden", width: "100%", flexGrow: 1, height: `calc(100vh - ${boxTop}px - 35px)` } }, vista === "graph" && /* @__PURE__ */ import_react4.default.createElement(StatusDiagram, { inventory, active: activos }), vista === "table" && /* @__PURE__ */ import_react4.default.createElement(import_material3.Table, { size: "small", stickyHeader: true }, /* @__PURE__ */ import_react4.default.createElement(import_material3.TableHead, null, /* @__PURE__ */ import_react4.default.createElement(import_material3.TableRow, null, /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "Kind"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "Name"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "State"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, { align: "right" }, "Consumers"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, { align: "right" }, "Delivered"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "Why"))), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableBody, null, componentes.map(fila)))), data.signals.length > 0 && /* @__PURE__ */ import_react4.default.createElement(import_material3.Box, { sx: { mt: 1 } }, data.signals.map((s, i) => /* @__PURE__ */ import_react4.default.createElement(import_material3.Typography, { key: i, variant: "caption", color: "error", display: "block" }, s))));
|
|
519
|
+
), /* @__PURE__ */ import_react4.default.createElement(import_material3.Tooltip, { title: "Take a new snapshot" }, /* @__PURE__ */ import_react4.default.createElement(import_material3.IconButton, { size: "small", onClick: refresh }, /* @__PURE__ */ import_react4.default.createElement(import_icons.Refresh, { fontSize: "small" })))), /* @__PURE__ */ import_react4.default.createElement(import_material3.Typography, { variant: "caption", color: "text.secondary", sx: { mb: 1 } }, "Snapshot taken at ", new Date(inventory.takenAt).toLocaleTimeString(), data.autoRefresh ? ` \u2014 refreshing every ${data.autoRefresh}s while this tab is open` : " \u2014 it does not refresh on its own", ".", " ", "Delivered counts since each component started; the rate is measured against your previous snapshot."), /* @__PURE__ */ import_react4.default.createElement(import_material3.Box, { ref: boxRef, sx: { display: "flex", flexDirection: "column", overflowY: vista === "table" ? "auto" : "hidden", overflowX: "hidden", width: "100%", flexGrow: 1, height: `calc(100vh - ${boxTop}px - 35px)` } }, vista === "graph" && /* @__PURE__ */ import_react4.default.createElement(StatusDiagram, { inventory, active: activos, autoRefresh: data.autoRefresh }), vista === "table" && /* @__PURE__ */ import_react4.default.createElement(import_material3.Table, { size: "small", stickyHeader: true }, /* @__PURE__ */ import_react4.default.createElement(import_material3.TableHead, null, /* @__PURE__ */ import_react4.default.createElement(import_material3.TableRow, null, /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "Kind"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "Name"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "State"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, { align: "right" }, "Consumers"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, { align: "right" }, "Delivered"), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableCell, null, "Why"))), /* @__PURE__ */ import_react4.default.createElement(import_material3.TableBody, null, componentes.map(fila)))), data.signals.length > 0 && /* @__PURE__ */ import_react4.default.createElement(import_material3.Box, { sx: { mt: 1 } }, data.signals.map((s, i) => /* @__PURE__ */ import_react4.default.createElement(import_material3.Typography, { key: i, variant: "caption", color: "error", display: "block" }, s))));
|
|
484
520
|
};
|
|
485
521
|
|
|
486
522
|
// src/front/StatusChannel.ts
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"id": "status",
|
|
5
5
|
"name": "@kwirthmagnify/kwirth-plugin-status",
|
|
6
6
|
"displayName": "Kwirth Status",
|
|
7
|
-
"version": "0.2.
|
|
7
|
+
"version": "0.2.5",
|
|
8
8
|
"description": "A look inside Kwirth: what is installed, how it is doing and who consumes what",
|
|
9
9
|
"icon": "<svg viewBox='0 0 24 24'><g fill='none' stroke='currentColor' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><rect x='2.6' y='4.6' width='18.8' height='14.8' rx='2.2'/><path d='M6 12h2.6l1.5-3.4 2.6 6.8 1.5-3.4H18'/></g></svg>",
|
|
10
10
|
"requiresRestart": false,
|