@mindexec/cli 0.2.27 → 0.2.29
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/package.json +1 -1
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-core.js +140 -88
- package/wwwroot/_content/MindExecution.Shared/js/mind-map-css3d-manager.js +104 -12
- package/wwwroot/index.html +1 -1
- package/wwwroot/service-worker-assets.js +4 -4
- package/wwwroot/service-worker.js +1 -1
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
const DEBUG = false;
|
|
6
6
|
const FPS_DEBUG = false;
|
|
7
7
|
const FRAME_PERF_DEBUG = false;
|
|
8
|
-
const MINDMAP_CORE_BUILD_ID = '20260613-cursor-
|
|
8
|
+
const MINDMAP_CORE_BUILD_ID = '20260613-dom-cursor-v207';
|
|
9
9
|
const CanvasPhase = Object.freeze({
|
|
10
10
|
Booting: 'booting',
|
|
11
11
|
BoardFileLoading: 'board-file-loading',
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
const PASSIVE_OVERLAY_INTERACTIVE_DENSE_VISIBLE_THRESHOLD = 40;
|
|
84
84
|
const PASSIVE_OVERLAY_IDLE_DELAY_MS = 500;
|
|
85
85
|
const PASSIVE_OVERLAY_PAN_IDLE_DELAY_MS = 500;
|
|
86
|
-
const
|
|
86
|
+
const CURSOR_DOM_BLINK_DURATION_MS = 1000;
|
|
87
87
|
const HOME_CAMERA_NORMAL_MID_Z = 8250;
|
|
88
88
|
const HOME_DENSE_CLUSTER_MIN_CELL_SIZE = 1200;
|
|
89
89
|
const HOME_DENSE_CLUSTER_MAX_CELL_SIZE = 3600;
|
|
@@ -235,6 +235,111 @@
|
|
|
235
235
|
});
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
+
let cursorDomStyleInstalled = false;
|
|
239
|
+
|
|
240
|
+
function ensureCursorDomStyle() {
|
|
241
|
+
if (cursorDomStyleInstalled || typeof document === 'undefined') {
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (document.getElementById('mind-map-cursor-dom-style')) {
|
|
246
|
+
cursorDomStyleInstalled = true;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const style = document.createElement('style');
|
|
251
|
+
style.id = 'mind-map-cursor-dom-style';
|
|
252
|
+
style.textContent = `
|
|
253
|
+
@keyframes mindMapCursorDomBlink {
|
|
254
|
+
0%, 49% { opacity: 1; }
|
|
255
|
+
50%, 100% { opacity: 0; }
|
|
256
|
+
}
|
|
257
|
+
.mind-map-cursor-dom {
|
|
258
|
+
position: absolute;
|
|
259
|
+
left: 0;
|
|
260
|
+
top: 0;
|
|
261
|
+
width: 20px;
|
|
262
|
+
height: 20px;
|
|
263
|
+
box-sizing: border-box;
|
|
264
|
+
border-top: 4px solid #000;
|
|
265
|
+
border-left: 4px solid #000;
|
|
266
|
+
pointer-events: none;
|
|
267
|
+
z-index: 2147483000;
|
|
268
|
+
animation: mindMapCursorDomBlink ${CURSOR_DOM_BLINK_DURATION_MS}ms steps(1, end) infinite;
|
|
269
|
+
will-change: transform;
|
|
270
|
+
contain: layout style paint;
|
|
271
|
+
}
|
|
272
|
+
`;
|
|
273
|
+
document.head?.appendChild(style);
|
|
274
|
+
cursorDomStyleInstalled = true;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function ensureCursorDomElement(module) {
|
|
278
|
+
if (!module?.container || typeof document === 'undefined') {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
ensureCursorDomStyle();
|
|
283
|
+
|
|
284
|
+
if (module.cursorDomElement?.isConnected) {
|
|
285
|
+
return module.cursorDomElement;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const element = document.createElement('div');
|
|
289
|
+
element.className = 'mind-map-cursor-dom';
|
|
290
|
+
element.setAttribute('aria-hidden', 'true');
|
|
291
|
+
module.container.appendChild(element);
|
|
292
|
+
module.cursorDomElement = element;
|
|
293
|
+
module._lastCursorDomPositionKey = '';
|
|
294
|
+
return element;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function updateCursorDomElement(module) {
|
|
298
|
+
if (!module?.container || !module.camera || !module.cursorPosition) {
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const element = ensureCursorDomElement(module);
|
|
303
|
+
if (!element) {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const width = Math.max(1, Number(module.container.clientWidth || 0));
|
|
308
|
+
const height = Math.max(1, Number(module.container.clientHeight || 0));
|
|
309
|
+
const camera = module.camera;
|
|
310
|
+
const cursor = module.cursorPosition;
|
|
311
|
+
const vfov = (camera.fov * Math.PI) / 180;
|
|
312
|
+
const viewHeight = 2 * Math.tan(vfov / 2) * camera.position.z;
|
|
313
|
+
const viewWidth = viewHeight * camera.aspect;
|
|
314
|
+
const ndcX = ((cursor.x - camera.position.x) * 2) / viewWidth;
|
|
315
|
+
const ndcY = ((cursor.y - camera.position.y) * 2) / viewHeight;
|
|
316
|
+
const x = ((ndcX + 1) / 2) * width;
|
|
317
|
+
const y = ((1 - ndcY) / 2) * height;
|
|
318
|
+
const visible = ndcX >= -1.1 && ndcX <= 1.1 && ndcY >= -1.1 && ndcY <= 1.1;
|
|
319
|
+
const positionKey = `${visible ? 1 : 0}|${Math.round(x)}|${Math.round(y)}|${width}|${height}`;
|
|
320
|
+
|
|
321
|
+
if (positionKey === module._lastCursorDomPositionKey) {
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
module._lastCursorDomPositionKey = positionKey;
|
|
326
|
+
element.style.display = visible ? 'block' : 'none';
|
|
327
|
+
if (visible) {
|
|
328
|
+
element.style.transform = `translate3d(${x.toFixed(2)}px, ${y.toFixed(2)}px, 0)`;
|
|
329
|
+
}
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function removeCursorDomElement(module) {
|
|
334
|
+
if (module?.cursorDomElement) {
|
|
335
|
+
module.cursorDomElement.remove();
|
|
336
|
+
module.cursorDomElement = null;
|
|
337
|
+
}
|
|
338
|
+
if (module) {
|
|
339
|
+
module._lastCursorDomPositionKey = '';
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
238
343
|
function shouldYieldWorkSlice(sliceStartedAt, processedCount, budgetMs, minItems, maxItems) {
|
|
239
344
|
if (processedCount < minItems) {
|
|
240
345
|
return false;
|
|
@@ -2498,8 +2603,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
2498
2603
|
this.cursorMesh = null;
|
|
2499
2604
|
this.cursorMaterial = null;
|
|
2500
2605
|
this.cursorLineMaterial = null;
|
|
2501
|
-
this.
|
|
2502
|
-
this.
|
|
2606
|
+
this.cursorDomElement = null;
|
|
2607
|
+
this._lastCursorDomPositionKey = '';
|
|
2503
2608
|
this._viewStatePersistTimer = null;
|
|
2504
2609
|
this._pendingViewStateSnapshot = null;
|
|
2505
2610
|
this._pendingViewStateKey = null;
|
|
@@ -3006,6 +3111,8 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
3006
3111
|
this.container = target;
|
|
3007
3112
|
this.dotNetHelper = helper;
|
|
3008
3113
|
window.dotNetHelper = helper; // Expose globally for NativeDropHandler access
|
|
3114
|
+
ensureCursorDomElement(this);
|
|
3115
|
+
updateCursorDomElement(this);
|
|
3009
3116
|
if (this.useTextOverlayV2 && window.MindMapTextOverlayV2?.init) {
|
|
3010
3117
|
window.MindMapTextOverlayV2.init(this);
|
|
3011
3118
|
}
|
|
@@ -3081,19 +3188,19 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
3081
3188
|
const thickness = 4; // Cursor thickness
|
|
3082
3189
|
|
|
3083
3190
|
// Mesh material (background / thickness)
|
|
3084
|
-
this.cursorMaterial = new THREE.MeshBasicMaterial({
|
|
3085
|
-
color:
|
|
3086
|
-
transparent: true,
|
|
3087
|
-
opacity: 1.0,
|
|
3088
|
-
depthTest: false
|
|
3089
|
-
});
|
|
3090
|
-
|
|
3091
|
-
// Line material (centerline)
|
|
3092
|
-
this.cursorLineMaterial = new THREE.LineBasicMaterial({
|
|
3093
|
-
color:
|
|
3094
|
-
transparent: false,
|
|
3095
|
-
opacity: 1,
|
|
3096
|
-
depthTest: false
|
|
3191
|
+
this.cursorMaterial = new THREE.MeshBasicMaterial({
|
|
3192
|
+
color: 0x000000,
|
|
3193
|
+
transparent: true,
|
|
3194
|
+
opacity: 1.0,
|
|
3195
|
+
depthTest: false
|
|
3196
|
+
});
|
|
3197
|
+
|
|
3198
|
+
// Line material (centerline)
|
|
3199
|
+
this.cursorLineMaterial = new THREE.LineBasicMaterial({
|
|
3200
|
+
color: 0x000000,
|
|
3201
|
+
transparent: false,
|
|
3202
|
+
opacity: 1,
|
|
3203
|
+
depthTest: false
|
|
3097
3204
|
});
|
|
3098
3205
|
|
|
3099
3206
|
// Mesh geometry (vertical/horizontal bars)
|
|
@@ -3120,9 +3227,10 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
3120
3227
|
line.position.z = 0; // [Fix] Z=0 for parallax elimination
|
|
3121
3228
|
line.renderOrder = 9999;
|
|
3122
3229
|
this.cursorMesh.add(line);
|
|
3123
|
-
|
|
3124
|
-
this.cursorMesh.position.set(0, 0, 0); // [Fix] Z=0 for parallax elimination
|
|
3125
|
-
this.cursorMesh.renderOrder = 9999;
|
|
3230
|
+
|
|
3231
|
+
this.cursorMesh.position.set(0, 0, 0); // [Fix] Z=0 for parallax elimination
|
|
3232
|
+
this.cursorMesh.renderOrder = 9999;
|
|
3233
|
+
this.cursorMesh.visible = false;
|
|
3126
3234
|
this.scene.add(this.cursorMesh);
|
|
3127
3235
|
|
|
3128
3236
|
if (this.updateCursorPosition) {
|
|
@@ -3229,7 +3337,10 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
3229
3337
|
}
|
|
3230
3338
|
|
|
3231
3339
|
// 4. [중요] 강제 리사이즈 호출 (초기화 시점의 0x0 사이즈 보정)
|
|
3232
|
-
|
|
3340
|
+
ensureCursorDomElement(this);
|
|
3341
|
+
updateCursorDomElement(this);
|
|
3342
|
+
|
|
3343
|
+
setTimeout(() => {
|
|
3233
3344
|
if (this && this.onWindowResize) {
|
|
3234
3345
|
console.log("[Init] Forcing resize to fix 0 height issue");
|
|
3235
3346
|
this.onWindowResize();
|
|
@@ -5062,41 +5173,9 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
5062
5173
|
allowAnimation: shouldAnimateImageStatusTextures
|
|
5063
5174
|
});
|
|
5064
5175
|
|
|
5065
|
-
// 5. Cursor
|
|
5176
|
+
// 5. Cursor DOM position
|
|
5066
5177
|
// ----------------------------------------------------------------
|
|
5067
|
-
|
|
5068
|
-
let cursorBlinkWakeDelayMs = Number.POSITIVE_INFINITY;
|
|
5069
|
-
const hasCursorBlinkTarget = !!(this.cursorMesh && this.cursorMaterial);
|
|
5070
|
-
if (hasCursorBlinkTarget) {
|
|
5071
|
-
if (this.cursorMesh.visible !== (this._cursorBlinkVisible === true)) {
|
|
5072
|
-
this.cursorMesh.visible = this._cursorBlinkVisible === true;
|
|
5073
|
-
cursorAnimatedThisFrame = true;
|
|
5074
|
-
}
|
|
5075
|
-
|
|
5076
|
-
const previousBlinkAt = Number(this._lastCursorBlinkAt || 0);
|
|
5077
|
-
if (!Number.isFinite(previousBlinkAt) || previousBlinkAt <= 0) {
|
|
5078
|
-
this._lastCursorBlinkAt = frameStart;
|
|
5079
|
-
this._cursorBlinkVisible = true;
|
|
5080
|
-
if (this.cursorMesh.visible !== true) {
|
|
5081
|
-
this.cursorMesh.visible = true;
|
|
5082
|
-
cursorAnimatedThisFrame = true;
|
|
5083
|
-
}
|
|
5084
|
-
} else {
|
|
5085
|
-
const elapsedBlinkMs = Math.max(0, frameStart - previousBlinkAt);
|
|
5086
|
-
if (elapsedBlinkMs >= CURSOR_BLINK_INTERVAL_MS) {
|
|
5087
|
-
const elapsedBlinkSteps = Math.max(1, Math.floor(elapsedBlinkMs / CURSOR_BLINK_INTERVAL_MS));
|
|
5088
|
-
if ((elapsedBlinkSteps % 2) === 1) {
|
|
5089
|
-
this._cursorBlinkVisible = this._cursorBlinkVisible !== true;
|
|
5090
|
-
}
|
|
5091
|
-
this._lastCursorBlinkAt = previousBlinkAt + (elapsedBlinkSteps * CURSOR_BLINK_INTERVAL_MS);
|
|
5092
|
-
this.cursorMesh.visible = this._cursorBlinkVisible === true;
|
|
5093
|
-
cursorAnimatedThisFrame = true;
|
|
5094
|
-
}
|
|
5095
|
-
}
|
|
5096
|
-
|
|
5097
|
-
const nextBlinkInMs = CURSOR_BLINK_INTERVAL_MS - Math.max(0, frameStart - Number(this._lastCursorBlinkAt || frameStart));
|
|
5098
|
-
cursorBlinkWakeDelayMs = Math.max(1, Math.min(CURSOR_BLINK_INTERVAL_MS, Math.ceil(nextBlinkInMs)));
|
|
5099
|
-
}
|
|
5178
|
+
updateCursorDomElement(this);
|
|
5100
5179
|
|
|
5101
5180
|
// 6. Theme Animation
|
|
5102
5181
|
// ----------------------------------------------------------------
|
|
@@ -5145,21 +5224,13 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
5145
5224
|
// 7. Render
|
|
5146
5225
|
// ----------------------------------------------------------------
|
|
5147
5226
|
_profileSection('css3dSync');
|
|
5148
|
-
const hasContinuousThemeAnimationFrame =
|
|
5149
|
-
allowContinuousThemeAnimationThisFrame === true &&
|
|
5150
|
-
(
|
|
5151
|
-
shouldForceGpuParticleAnimation === true ||
|
|
5152
|
-
(isThemeAnimationEnabled === true && isContinuousTheme === true)
|
|
5153
|
-
);
|
|
5154
5227
|
const shouldRenderWebglFrame =
|
|
5155
5228
|
isWebglRenderEnabled &&
|
|
5156
5229
|
(
|
|
5157
5230
|
isBoardLoading === true ||
|
|
5158
5231
|
shouldUpdate === true ||
|
|
5159
5232
|
isInteractiveFrame === true ||
|
|
5160
|
-
themeAnimatedThisFrame === true
|
|
5161
|
-
cursorAnimatedThisFrame === true ||
|
|
5162
|
-
hasContinuousThemeAnimationFrame === true
|
|
5233
|
+
themeAnimatedThisFrame === true
|
|
5163
5234
|
);
|
|
5164
5235
|
if (shouldRenderWebglFrame) {
|
|
5165
5236
|
this.renderer.render(this.scene, this.camera);
|
|
@@ -5488,38 +5559,17 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
5488
5559
|
isInteractiveFrame !== true &&
|
|
5489
5560
|
shouldUpdate !== true &&
|
|
5490
5561
|
themeAnimatedThisFrame !== true &&
|
|
5491
|
-
cursorAnimatedThisFrame !== true &&
|
|
5492
5562
|
shouldRenderWebglFrame !== true &&
|
|
5493
5563
|
shouldRenderCss3dFrame !== true &&
|
|
5494
5564
|
shouldSyncTextOverlays !== true &&
|
|
5495
5565
|
hasPendingAnimationWakeWork !== true;
|
|
5496
5566
|
if (shouldParkIdleAnimationLoop) {
|
|
5497
|
-
if (hasCursorBlinkTarget) {
|
|
5498
|
-
nextAnimationLoopDelayMs = cursorBlinkWakeDelayMs;
|
|
5499
|
-
this._lastAnimationLoopDelayMs = nextAnimationLoopDelayMs;
|
|
5500
|
-
this._animationLoopExecuting = false;
|
|
5501
|
-
this._scheduleAnimationLoop(loop, nextAnimationLoopDelayMs);
|
|
5502
|
-
return;
|
|
5503
|
-
}
|
|
5504
|
-
|
|
5505
5567
|
this._lastAnimationLoopDelayMs = -1;
|
|
5506
5568
|
this._animationLoopExecuting = false;
|
|
5507
5569
|
return;
|
|
5508
5570
|
}
|
|
5509
5571
|
|
|
5510
|
-
|
|
5511
|
-
cursorAnimatedThisFrame === true &&
|
|
5512
|
-
shouldCaptureFramePerf !== true &&
|
|
5513
|
-
isBoardLoading !== true &&
|
|
5514
|
-
isInteractiveFrame !== true &&
|
|
5515
|
-
shouldUpdate !== true &&
|
|
5516
|
-
themeAnimatedThisFrame !== true &&
|
|
5517
|
-
hasContinuousThemeAnimationFrame !== true &&
|
|
5518
|
-
shouldRenderCss3dFrame !== true &&
|
|
5519
|
-
shouldSyncTextOverlays !== true &&
|
|
5520
|
-
hasPendingAnimationWakeWork !== true &&
|
|
5521
|
-
hasCursorBlinkTarget === true;
|
|
5522
|
-
nextAnimationLoopDelayMs = shouldDelayAfterCursorOnlyFrame ? cursorBlinkWakeDelayMs : 0;
|
|
5572
|
+
nextAnimationLoopDelayMs = 0;
|
|
5523
5573
|
this._lastAnimationLoopDelayMs = nextAnimationLoopDelayMs;
|
|
5524
5574
|
this._animationLoopExecuting = false;
|
|
5525
5575
|
this._scheduleAnimationLoop(loop, nextAnimationLoopDelayMs);
|
|
@@ -5658,8 +5708,9 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
5658
5708
|
|
|
5659
5709
|
this.cursorPosition.set(snappedX, snappedY, 0);
|
|
5660
5710
|
if (this.cursorMesh) {
|
|
5661
|
-
this.cursorMesh.position.set(snappedX, snappedY, 0); // [Fix] Z=0 for parallax elimination
|
|
5662
|
-
}
|
|
5711
|
+
this.cursorMesh.position.set(snappedX, snappedY, 0); // [Fix] Z=0 for parallax elimination
|
|
5712
|
+
}
|
|
5713
|
+
updateCursorDomElement(this);
|
|
5663
5714
|
|
|
5664
5715
|
if (moveCamera) {
|
|
5665
5716
|
let targetCenterX = snappedX;
|
|
@@ -5788,6 +5839,7 @@ ${summaryLines.map(line => `<div>${escapeNodeFrameDebugHtml(line)}</div>`).join(
|
|
|
5788
5839
|
cleanupAndDispose() {
|
|
5789
5840
|
if (!this.container) return;
|
|
5790
5841
|
this.pauseAnimationLoop();
|
|
5842
|
+
removeCursorDomElement(this);
|
|
5791
5843
|
if (this._viewStatePersistTimer) {
|
|
5792
5844
|
clearTimeout(this._viewStatePersistTimer);
|
|
5793
5845
|
this._viewStatePersistTimer = null;
|
|
@@ -12208,6 +12208,83 @@
|
|
|
12208
12208
|
return item;
|
|
12209
12209
|
}
|
|
12210
12210
|
|
|
12211
|
+
function createRemoteFleetStatusRail(items) {
|
|
12212
|
+
const rail = document.createElement('aside');
|
|
12213
|
+
rail.dataset.remoteFleetStatusRail = 'true';
|
|
12214
|
+
rail.style.cssText = `
|
|
12215
|
+
flex: 0 0 auto;
|
|
12216
|
+
align-self: flex-start;
|
|
12217
|
+
display: flex;
|
|
12218
|
+
flex-direction: column;
|
|
12219
|
+
gap: 3px;
|
|
12220
|
+
min-width: 132px;
|
|
12221
|
+
max-width: min(100%, 176px);
|
|
12222
|
+
padding: 5px 6px;
|
|
12223
|
+
border-radius: 7px;
|
|
12224
|
+
border: 1px solid rgba(148, 163, 184, 0.22);
|
|
12225
|
+
background: rgba(255, 255, 255, 0.70);
|
|
12226
|
+
`;
|
|
12227
|
+
|
|
12228
|
+
(items || []).forEach(item => {
|
|
12229
|
+
const tone = String(item?.tone || 'default');
|
|
12230
|
+
const row = document.createElement('div');
|
|
12231
|
+
row.dataset.remoteFleetStatusItem = item?.key || '';
|
|
12232
|
+
row.style.cssText = `
|
|
12233
|
+
display: grid;
|
|
12234
|
+
grid-template-columns: 7px minmax(0, 1fr) auto;
|
|
12235
|
+
align-items: center;
|
|
12236
|
+
gap: 5px;
|
|
12237
|
+
min-height: 16px;
|
|
12238
|
+
min-width: 0;
|
|
12239
|
+
`;
|
|
12240
|
+
|
|
12241
|
+
const dot = document.createElement('span');
|
|
12242
|
+
dot.style.cssText = `
|
|
12243
|
+
width: 7px;
|
|
12244
|
+
height: 7px;
|
|
12245
|
+
border-radius: 999px;
|
|
12246
|
+
background: ${tone === 'online' ? '#10b981' : tone === 'warn' ? '#f59e0b' : '#94a3b8'};
|
|
12247
|
+
box-shadow: ${tone === 'online' ? '0 0 0 3px rgba(16, 185, 129, 0.12)' : 'none'};
|
|
12248
|
+
`;
|
|
12249
|
+
|
|
12250
|
+
const labelEl = document.createElement('span');
|
|
12251
|
+
labelEl.textContent = item?.label || '';
|
|
12252
|
+
labelEl.style.cssText = `
|
|
12253
|
+
color: #64748b;
|
|
12254
|
+
font-size: 9px;
|
|
12255
|
+
font-weight: 850;
|
|
12256
|
+
line-height: 1;
|
|
12257
|
+
letter-spacing: 0;
|
|
12258
|
+
overflow: hidden;
|
|
12259
|
+
text-overflow: ellipsis;
|
|
12260
|
+
white-space: nowrap;
|
|
12261
|
+
text-transform: uppercase;
|
|
12262
|
+
`;
|
|
12263
|
+
|
|
12264
|
+
const valueEl = document.createElement('strong');
|
|
12265
|
+
valueEl.textContent = item?.value || '';
|
|
12266
|
+
valueEl.title = `${labelEl.textContent} ${valueEl.textContent}`.trim();
|
|
12267
|
+
valueEl.style.cssText = `
|
|
12268
|
+
color: ${tone === 'online' ? '#047857' : '#0f172a'};
|
|
12269
|
+
font-size: 10px;
|
|
12270
|
+
font-weight: 950;
|
|
12271
|
+
line-height: 1;
|
|
12272
|
+
letter-spacing: 0;
|
|
12273
|
+
max-width: 76px;
|
|
12274
|
+
overflow: hidden;
|
|
12275
|
+
text-overflow: ellipsis;
|
|
12276
|
+
white-space: nowrap;
|
|
12277
|
+
`;
|
|
12278
|
+
|
|
12279
|
+
row.appendChild(dot);
|
|
12280
|
+
row.appendChild(labelEl);
|
|
12281
|
+
row.appendChild(valueEl);
|
|
12282
|
+
rail.appendChild(row);
|
|
12283
|
+
});
|
|
12284
|
+
|
|
12285
|
+
return rail;
|
|
12286
|
+
}
|
|
12287
|
+
|
|
12211
12288
|
function createRemoteFleetButton(label, title, action) {
|
|
12212
12289
|
const button = document.createElement('button');
|
|
12213
12290
|
button.type = 'button';
|
|
@@ -13306,18 +13383,32 @@
|
|
|
13306
13383
|
}
|
|
13307
13384
|
attachRemoteFleetTitleActions(bodyView, hostButton, stopHostButton, hostTargetState);
|
|
13308
13385
|
|
|
13309
|
-
const
|
|
13310
|
-
|
|
13311
|
-
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13317
|
-
|
|
13318
|
-
|
|
13319
|
-
|
|
13320
|
-
|
|
13386
|
+
const statusRail = createRemoteFleetStatusRail([
|
|
13387
|
+
{
|
|
13388
|
+
key: 'hub',
|
|
13389
|
+
label: 'Hub',
|
|
13390
|
+
value: hubStatus === 'online' ? 'Online' : 'Offline',
|
|
13391
|
+
tone: hubStatus === 'online' ? 'online' : 'default'
|
|
13392
|
+
},
|
|
13393
|
+
{
|
|
13394
|
+
key: 'connected',
|
|
13395
|
+
label: 'Connected',
|
|
13396
|
+
value: `${Number.isFinite(connected) ? connected : 0}/${Number.isFinite(total) ? total : devices.length}`,
|
|
13397
|
+
tone: connected > 0 ? 'online' : 'default'
|
|
13398
|
+
},
|
|
13399
|
+
{
|
|
13400
|
+
key: 'task',
|
|
13401
|
+
label: 'Task',
|
|
13402
|
+
value: String(taskCapableCount),
|
|
13403
|
+
tone: taskCapableCount > 0 ? 'online' : 'default'
|
|
13404
|
+
},
|
|
13405
|
+
{
|
|
13406
|
+
key: 'ai',
|
|
13407
|
+
label: 'AI',
|
|
13408
|
+
value: String(aiCapableCount),
|
|
13409
|
+
tone: aiCapableCount > 0 ? 'online' : 'default'
|
|
13410
|
+
}
|
|
13411
|
+
]);
|
|
13321
13412
|
|
|
13322
13413
|
const filterRow = document.createElement('div');
|
|
13323
13414
|
filterRow.style.cssText = `
|
|
@@ -14238,6 +14329,7 @@
|
|
|
14238
14329
|
monitorWorkspace.appendChild(createSelectedDevicePanel(selectedDevice));
|
|
14239
14330
|
}
|
|
14240
14331
|
bodyView.appendChild(monitorWorkspace);
|
|
14332
|
+
bodyView.appendChild(statusRail);
|
|
14241
14333
|
|
|
14242
14334
|
const setTaskFeedback = (message, tone = 'info') => {
|
|
14243
14335
|
taskFeedback.textContent = message || '';
|
package/wwwroot/index.html
CHANGED
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
const base = '_content/MindExecution.Shared/js/';
|
|
561
|
-
const scriptVersion = '20260613-
|
|
561
|
+
const scriptVersion = '20260613-remote-status-rail-v495';
|
|
562
562
|
const scriptUrl = (script) => `${base}${script}?v=${scriptVersion}`;
|
|
563
563
|
console.log(`[Script Loader] Shared JS version: ${scriptVersion}`);
|
|
564
564
|
const criticalScripts = [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
self.assetsManifest = {
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "RMyUd5ec",
|
|
3
3
|
"assets": [
|
|
4
4
|
{
|
|
5
5
|
"hash": "sha256-+CSYMcqLNTsq3VnH11jgYyOCCdxvHzL74CBmo4sCmMU=",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"url": "_content/MindExecution.Shared/js/marked.min.js"
|
|
79
79
|
},
|
|
80
80
|
{
|
|
81
|
-
"hash": "sha256-
|
|
81
|
+
"hash": "sha256-UeeqiZXN9Iv1e/DRq1gyWRCbQUwzduNrpf5aSQido00=",
|
|
82
82
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js"
|
|
83
83
|
},
|
|
84
84
|
{
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"url": "_content/MindExecution.Shared/js/mind-map-core.js.backup"
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
"hash": "sha256-
|
|
89
|
+
"hash": "sha256-S8H0KuKhx8Fhbt07w1LBGxnBjT4km99JHDxzrHVFVho=",
|
|
90
90
|
"url": "_content/MindExecution.Shared/js/mind-map-css3d-manager.js"
|
|
91
91
|
},
|
|
92
92
|
{
|
|
@@ -834,7 +834,7 @@
|
|
|
834
834
|
"url": "image-manifest.json"
|
|
835
835
|
},
|
|
836
836
|
{
|
|
837
|
-
"hash": "sha256-
|
|
837
|
+
"hash": "sha256-t14gn/m71KgCPH/qD7JKdV9e5WD4DsQVpId/vGYdorE=",
|
|
838
838
|
"url": "index.html"
|
|
839
839
|
},
|
|
840
840
|
{
|