@optifye/dashboard-core 4.2.7 → 4.2.8
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/dist/index.d.mts +77 -21
- package/dist/index.d.ts +77 -21
- package/dist/index.js +531 -366
- package/dist/index.mjs +528 -366
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6,8 +6,8 @@ import { toZonedTime, formatInTimeZone } from 'date-fns-tz';
|
|
|
6
6
|
import { subDays, format, parseISO, isValid, isFuture, isToday } from 'date-fns';
|
|
7
7
|
import mixpanel from 'mixpanel-browser';
|
|
8
8
|
import { REALTIME_SUBSCRIBE_STATES, createClient } from '@supabase/supabase-js';
|
|
9
|
-
import useSWR from 'swr';
|
|
10
9
|
import Hls2 from 'hls.js';
|
|
10
|
+
import useSWR from 'swr';
|
|
11
11
|
import { noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds, memo as memo$1 } from 'motion-utils';
|
|
12
12
|
import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
|
|
13
13
|
import { ResponsiveContainer, BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, ReferenceLine, Bar, Cell, LabelList, PieChart, Pie, Legend, LineChart as LineChart$1, Line } from 'recharts';
|
|
@@ -125,6 +125,12 @@ var DEFAULT_ANALYTICS_CONFIG = {
|
|
|
125
125
|
var DEFAULT_AUTH_CONFIG = {
|
|
126
126
|
// Defaults related to auth providers, redirects etc.
|
|
127
127
|
};
|
|
128
|
+
var DEFAULT_VIDEO_CONFIG = {
|
|
129
|
+
canvasConfig: {
|
|
130
|
+
fps: 30,
|
|
131
|
+
useRAF: true
|
|
132
|
+
}
|
|
133
|
+
};
|
|
128
134
|
var LINE_1_UUID = "910a224b-0abc-459a-babb-4c899824cfe7";
|
|
129
135
|
var DEFAULT_CONFIG = {
|
|
130
136
|
apiBaseUrl: void 0,
|
|
@@ -138,7 +144,8 @@ var DEFAULT_CONFIG = {
|
|
|
138
144
|
// Add entity config here
|
|
139
145
|
shiftConfig: DEFAULT_SHIFT_CONFIG,
|
|
140
146
|
workspaceConfig: DEFAULT_WORKSPACE_CONFIG,
|
|
141
|
-
endpoints: DEFAULT_ENDPOINTS_CONFIG
|
|
147
|
+
endpoints: DEFAULT_ENDPOINTS_CONFIG,
|
|
148
|
+
videoConfig: DEFAULT_VIDEO_CONFIG
|
|
142
149
|
};
|
|
143
150
|
|
|
144
151
|
// src/lib/utils/config.ts
|
|
@@ -270,6 +277,10 @@ function useCustomConfig() {
|
|
|
270
277
|
const { customConfig } = useDashboardConfig();
|
|
271
278
|
return customConfig ?? {};
|
|
272
279
|
}
|
|
280
|
+
function useVideoConfig() {
|
|
281
|
+
const { videoConfig } = useDashboardConfig();
|
|
282
|
+
return videoConfig ?? DEFAULT_VIDEO_CONFIG;
|
|
283
|
+
}
|
|
273
284
|
|
|
274
285
|
// src/lib/internal/supabaseClientInstance.ts
|
|
275
286
|
var supabaseInstance = null;
|
|
@@ -4218,6 +4229,351 @@ var useWorkspaceOperators = (workspaceId, options) => {
|
|
|
4218
4229
|
refetch: fetchData
|
|
4219
4230
|
};
|
|
4220
4231
|
};
|
|
4232
|
+
|
|
4233
|
+
// src/lib/utils/dashboardReload.ts
|
|
4234
|
+
var createThrottledReload = (interval = 5e3) => {
|
|
4235
|
+
let last = 0;
|
|
4236
|
+
let queued = false;
|
|
4237
|
+
const doReload = () => {
|
|
4238
|
+
if (typeof window !== "undefined") {
|
|
4239
|
+
window.location.reload();
|
|
4240
|
+
}
|
|
4241
|
+
};
|
|
4242
|
+
return () => {
|
|
4243
|
+
const now2 = Date.now();
|
|
4244
|
+
if (now2 - last >= interval) {
|
|
4245
|
+
last = now2;
|
|
4246
|
+
doReload();
|
|
4247
|
+
} else if (!queued) {
|
|
4248
|
+
queued = true;
|
|
4249
|
+
setTimeout(() => {
|
|
4250
|
+
queued = false;
|
|
4251
|
+
last = Date.now();
|
|
4252
|
+
doReload();
|
|
4253
|
+
}, interval - (now2 - last));
|
|
4254
|
+
}
|
|
4255
|
+
};
|
|
4256
|
+
};
|
|
4257
|
+
var throttledReloadDashboard = createThrottledReload(5e3);
|
|
4258
|
+
|
|
4259
|
+
// src/lib/hooks/useHlsStream.ts
|
|
4260
|
+
var HLS_CONFIG = {
|
|
4261
|
+
maxBufferLength: 8,
|
|
4262
|
+
maxMaxBufferLength: 15,
|
|
4263
|
+
lowLatencyMode: false,
|
|
4264
|
+
enableWorker: true,
|
|
4265
|
+
// Retry + timeout tuned for quick recovery
|
|
4266
|
+
manifestLoadingMaxRetry: 4,
|
|
4267
|
+
levelLoadingMaxRetry: 3,
|
|
4268
|
+
fragLoadingMaxRetry: 4,
|
|
4269
|
+
manifestLoadingRetryDelay: 500,
|
|
4270
|
+
levelLoadingRetryDelay: 500,
|
|
4271
|
+
fragLoadingRetryDelay: 500,
|
|
4272
|
+
manifestLoadingTimeOut: 1e4,
|
|
4273
|
+
levelLoadingTimeOut: 8e3,
|
|
4274
|
+
fragLoadingTimeOut: 1e4,
|
|
4275
|
+
liveSyncDurationCount: 2
|
|
4276
|
+
// Follow live edge aggressively
|
|
4277
|
+
};
|
|
4278
|
+
function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
4279
|
+
const [restartKey, setRestartKey] = useState(0);
|
|
4280
|
+
const hlsRef = useRef(null);
|
|
4281
|
+
const stallCheckIntervalRef = useRef(null);
|
|
4282
|
+
const noProgressTimerRef = useRef(null);
|
|
4283
|
+
const lastTimeUpdateRef = useRef(0);
|
|
4284
|
+
const softRestartCountRef = useRef(0);
|
|
4285
|
+
const isNativeHlsRef = useRef(false);
|
|
4286
|
+
const waitingTimerRef = useRef(null);
|
|
4287
|
+
const cleanup = () => {
|
|
4288
|
+
if (stallCheckIntervalRef.current) {
|
|
4289
|
+
clearInterval(stallCheckIntervalRef.current);
|
|
4290
|
+
stallCheckIntervalRef.current = null;
|
|
4291
|
+
}
|
|
4292
|
+
if (noProgressTimerRef.current) {
|
|
4293
|
+
clearTimeout(noProgressTimerRef.current);
|
|
4294
|
+
noProgressTimerRef.current = null;
|
|
4295
|
+
}
|
|
4296
|
+
if (waitingTimerRef.current) {
|
|
4297
|
+
clearTimeout(waitingTimerRef.current);
|
|
4298
|
+
waitingTimerRef.current = null;
|
|
4299
|
+
}
|
|
4300
|
+
if (hlsRef.current) {
|
|
4301
|
+
hlsRef.current.destroy();
|
|
4302
|
+
hlsRef.current = null;
|
|
4303
|
+
}
|
|
4304
|
+
const video = videoRef.current;
|
|
4305
|
+
if (video) {
|
|
4306
|
+
video.pause();
|
|
4307
|
+
video.removeAttribute("src");
|
|
4308
|
+
video.load();
|
|
4309
|
+
video.removeEventListener("waiting", handleWaiting);
|
|
4310
|
+
video.removeEventListener("timeupdate", handleTimeUpdate);
|
|
4311
|
+
video.removeEventListener("error", handleNativeError);
|
|
4312
|
+
}
|
|
4313
|
+
lastTimeUpdateRef.current = 0;
|
|
4314
|
+
softRestartCountRef.current = 0;
|
|
4315
|
+
};
|
|
4316
|
+
const seekToLiveEdge = () => {
|
|
4317
|
+
const hls = hlsRef.current;
|
|
4318
|
+
const video = videoRef.current;
|
|
4319
|
+
if (!hls || !video) return;
|
|
4320
|
+
if (hls.liveSyncPosition !== null && hls.liveSyncPosition !== void 0) {
|
|
4321
|
+
video.currentTime = hls.liveSyncPosition;
|
|
4322
|
+
} else if (hls.levels?.[hls.currentLevel]?.details) {
|
|
4323
|
+
const levelDetails = hls.levels[hls.currentLevel].details;
|
|
4324
|
+
if (levelDetails && levelDetails.edge !== void 0) {
|
|
4325
|
+
video.currentTime = Math.max(0, levelDetails.edge - 5);
|
|
4326
|
+
}
|
|
4327
|
+
}
|
|
4328
|
+
};
|
|
4329
|
+
const softRestart = (reason) => {
|
|
4330
|
+
console.warn(`[HLS] Soft restart: ${reason}`);
|
|
4331
|
+
const hls = hlsRef.current;
|
|
4332
|
+
if (!hls) return;
|
|
4333
|
+
try {
|
|
4334
|
+
hls.stopLoad();
|
|
4335
|
+
hls.startLoad(-1);
|
|
4336
|
+
seekToLiveEdge();
|
|
4337
|
+
softRestartCountRef.current++;
|
|
4338
|
+
if (softRestartCountRef.current >= 5) {
|
|
4339
|
+
hardRestart(`${reason} (escalated after ${softRestartCountRef.current} soft restarts)`);
|
|
4340
|
+
}
|
|
4341
|
+
} catch (error) {
|
|
4342
|
+
console.error("[HLS] Soft restart failed:", error);
|
|
4343
|
+
hardRestart(`${reason} (soft restart error)`);
|
|
4344
|
+
}
|
|
4345
|
+
};
|
|
4346
|
+
const hardRestart = (reason) => {
|
|
4347
|
+
console.warn(`[HLS] Hard restart: ${reason}`);
|
|
4348
|
+
cleanup();
|
|
4349
|
+
setRestartKey((k) => k + 1);
|
|
4350
|
+
softRestartCountRef.current = 0;
|
|
4351
|
+
if (reason.includes("hard restart") || reason.includes("native video error")) {
|
|
4352
|
+
if (onFatalError) {
|
|
4353
|
+
onFatalError();
|
|
4354
|
+
} else {
|
|
4355
|
+
throttledReloadDashboard();
|
|
4356
|
+
}
|
|
4357
|
+
}
|
|
4358
|
+
};
|
|
4359
|
+
const handleWaiting = () => {
|
|
4360
|
+
if (isNativeHlsRef.current) return;
|
|
4361
|
+
console.log("[HLS] Video waiting (buffer underrun)");
|
|
4362
|
+
if (waitingTimerRef.current) {
|
|
4363
|
+
clearTimeout(waitingTimerRef.current);
|
|
4364
|
+
}
|
|
4365
|
+
waitingTimerRef.current = setTimeout(() => {
|
|
4366
|
+
const video = videoRef.current;
|
|
4367
|
+
if (video && video.readyState < 3) {
|
|
4368
|
+
softRestart("waiting timeout");
|
|
4369
|
+
}
|
|
4370
|
+
}, 1e4);
|
|
4371
|
+
};
|
|
4372
|
+
const handleTimeUpdate = () => {
|
|
4373
|
+
const video = videoRef.current;
|
|
4374
|
+
if (!video) return;
|
|
4375
|
+
lastTimeUpdateRef.current = video.currentTime;
|
|
4376
|
+
if (waitingTimerRef.current) {
|
|
4377
|
+
clearTimeout(waitingTimerRef.current);
|
|
4378
|
+
waitingTimerRef.current = null;
|
|
4379
|
+
}
|
|
4380
|
+
};
|
|
4381
|
+
const handleNativeError = () => {
|
|
4382
|
+
console.error("[HLS] Native video error");
|
|
4383
|
+
hardRestart("native video error");
|
|
4384
|
+
};
|
|
4385
|
+
const startStallDetection = () => {
|
|
4386
|
+
if (isNativeHlsRef.current) return;
|
|
4387
|
+
stallCheckIntervalRef.current = setInterval(() => {
|
|
4388
|
+
const video = videoRef.current;
|
|
4389
|
+
if (!video || video.paused || video.ended) return;
|
|
4390
|
+
const currentTime = video.currentTime;
|
|
4391
|
+
const lastTime = lastTimeUpdateRef.current;
|
|
4392
|
+
if (Math.abs(currentTime - lastTime) < 0.1 && video.readyState >= 2) {
|
|
4393
|
+
console.warn("[HLS] Playback stall detected");
|
|
4394
|
+
if (!noProgressTimerRef.current) {
|
|
4395
|
+
noProgressTimerRef.current = setTimeout(() => {
|
|
4396
|
+
softRestart("playback stall");
|
|
4397
|
+
noProgressTimerRef.current = null;
|
|
4398
|
+
}, 8e3);
|
|
4399
|
+
}
|
|
4400
|
+
} else {
|
|
4401
|
+
if (noProgressTimerRef.current) {
|
|
4402
|
+
clearTimeout(noProgressTimerRef.current);
|
|
4403
|
+
noProgressTimerRef.current = null;
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4406
|
+
}, 7e3);
|
|
4407
|
+
};
|
|
4408
|
+
useEffect(() => {
|
|
4409
|
+
if (!src || !shouldPlay) {
|
|
4410
|
+
cleanup();
|
|
4411
|
+
return;
|
|
4412
|
+
}
|
|
4413
|
+
const video = videoRef.current;
|
|
4414
|
+
if (!video) return;
|
|
4415
|
+
isNativeHlsRef.current = video.canPlayType("application/vnd.apple.mpegurl") === "probably";
|
|
4416
|
+
if (Hls2.isSupported() && !isNativeHlsRef.current) {
|
|
4417
|
+
const hls = new Hls2(HLS_CONFIG);
|
|
4418
|
+
hlsRef.current = hls;
|
|
4419
|
+
hls.attachMedia(video);
|
|
4420
|
+
hls.loadSource(src);
|
|
4421
|
+
hls.on(Hls2.Events.ERROR, (_, data) => {
|
|
4422
|
+
if (!data.fatal) return;
|
|
4423
|
+
console.error("[HLS] Fatal error:", data.type, data.details);
|
|
4424
|
+
if (data.response?.code === 404) {
|
|
4425
|
+
hardRestart("404 hard restart");
|
|
4426
|
+
return;
|
|
4427
|
+
}
|
|
4428
|
+
switch (data.type) {
|
|
4429
|
+
case Hls2.ErrorTypes.NETWORK_ERROR:
|
|
4430
|
+
case Hls2.ErrorTypes.MEDIA_ERROR:
|
|
4431
|
+
softRestart(`${data.type}: ${data.details}`);
|
|
4432
|
+
break;
|
|
4433
|
+
default:
|
|
4434
|
+
hardRestart(`Fatal ${data.type}: ${data.details}`);
|
|
4435
|
+
break;
|
|
4436
|
+
}
|
|
4437
|
+
});
|
|
4438
|
+
hls.on(Hls2.Events.MANIFEST_PARSED, () => {
|
|
4439
|
+
video.play().catch((err) => {
|
|
4440
|
+
console.error("[HLS] Play failed:", err);
|
|
4441
|
+
});
|
|
4442
|
+
});
|
|
4443
|
+
video.addEventListener("waiting", handleWaiting);
|
|
4444
|
+
video.addEventListener("timeupdate", handleTimeUpdate);
|
|
4445
|
+
startStallDetection();
|
|
4446
|
+
} else if (isNativeHlsRef.current) {
|
|
4447
|
+
console.log("[HLS] Using native HLS");
|
|
4448
|
+
video.src = src;
|
|
4449
|
+
video.addEventListener("error", handleNativeError);
|
|
4450
|
+
video.play().catch((err) => {
|
|
4451
|
+
console.error("[HLS] Native play failed:", err);
|
|
4452
|
+
});
|
|
4453
|
+
} else {
|
|
4454
|
+
console.error("[HLS] HLS not supported");
|
|
4455
|
+
}
|
|
4456
|
+
return cleanup;
|
|
4457
|
+
}, [src, shouldPlay, restartKey, onFatalError]);
|
|
4458
|
+
return {
|
|
4459
|
+
restartKey,
|
|
4460
|
+
isNativeHls: isNativeHlsRef.current
|
|
4461
|
+
};
|
|
4462
|
+
}
|
|
4463
|
+
function useHlsStreamWithCropping(videoRef, canvasRef, options) {
|
|
4464
|
+
const { src, shouldPlay, cropping, canvasFps = 30, useRAF = true, onFatalError } = options;
|
|
4465
|
+
const animationFrameRef = useRef(null);
|
|
4466
|
+
const intervalRef = useRef(null);
|
|
4467
|
+
const isDrawingRef = useRef(false);
|
|
4468
|
+
const hlsState = useHlsStream(videoRef, { src, shouldPlay, onFatalError });
|
|
4469
|
+
const calculateCropRect = useCallback((video, cropping2) => {
|
|
4470
|
+
const videoWidth = video.videoWidth;
|
|
4471
|
+
const videoHeight = video.videoHeight;
|
|
4472
|
+
const sx = cropping2.x / 100 * videoWidth;
|
|
4473
|
+
const sy = cropping2.y / 100 * videoHeight;
|
|
4474
|
+
const sw = cropping2.width / 100 * videoWidth;
|
|
4475
|
+
const sh = cropping2.height / 100 * videoHeight;
|
|
4476
|
+
return { sx, sy, sw, sh };
|
|
4477
|
+
}, []);
|
|
4478
|
+
const drawFrame = useCallback(() => {
|
|
4479
|
+
const video = videoRef.current;
|
|
4480
|
+
const canvas = canvasRef.current;
|
|
4481
|
+
if (!video || !canvas || !cropping) return;
|
|
4482
|
+
const ctx = canvas.getContext("2d");
|
|
4483
|
+
if (!ctx) return;
|
|
4484
|
+
if (video.readyState < 2) return;
|
|
4485
|
+
try {
|
|
4486
|
+
const videoWidth = video.videoWidth;
|
|
4487
|
+
const videoHeight = video.videoHeight;
|
|
4488
|
+
if (!videoWidth || !videoHeight) return;
|
|
4489
|
+
const { sx, sy, sw, sh } = calculateCropRect(video, cropping);
|
|
4490
|
+
const canvasContainer = canvas.parentElement;
|
|
4491
|
+
if (canvasContainer) {
|
|
4492
|
+
const containerWidth = canvasContainer.clientWidth;
|
|
4493
|
+
const containerHeight = canvasContainer.clientHeight;
|
|
4494
|
+
if (canvas.width !== containerWidth || canvas.height !== containerHeight) {
|
|
4495
|
+
canvas.width = containerWidth;
|
|
4496
|
+
canvas.height = containerHeight;
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
4500
|
+
ctx.drawImage(
|
|
4501
|
+
video,
|
|
4502
|
+
sx,
|
|
4503
|
+
sy,
|
|
4504
|
+
sw,
|
|
4505
|
+
sh,
|
|
4506
|
+
// Source rectangle (cropped portion)
|
|
4507
|
+
0,
|
|
4508
|
+
0,
|
|
4509
|
+
canvas.width,
|
|
4510
|
+
canvas.height
|
|
4511
|
+
// Destination rectangle (full canvas)
|
|
4512
|
+
);
|
|
4513
|
+
} catch (err) {
|
|
4514
|
+
console.warn("Canvas drawing error:", err);
|
|
4515
|
+
}
|
|
4516
|
+
}, [videoRef, canvasRef, cropping, calculateCropRect]);
|
|
4517
|
+
const startCanvasRendering = useCallback(() => {
|
|
4518
|
+
if (isDrawingRef.current) return;
|
|
4519
|
+
isDrawingRef.current = true;
|
|
4520
|
+
if (useRAF) {
|
|
4521
|
+
const animate = () => {
|
|
4522
|
+
drawFrame();
|
|
4523
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
4524
|
+
};
|
|
4525
|
+
animate();
|
|
4526
|
+
} else {
|
|
4527
|
+
const frameInterval = 1e3 / canvasFps;
|
|
4528
|
+
intervalRef.current = setInterval(drawFrame, frameInterval);
|
|
4529
|
+
}
|
|
4530
|
+
}, [drawFrame, canvasFps, useRAF]);
|
|
4531
|
+
const stopCanvasRendering = useCallback(() => {
|
|
4532
|
+
isDrawingRef.current = false;
|
|
4533
|
+
if (animationFrameRef.current) {
|
|
4534
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
4535
|
+
animationFrameRef.current = null;
|
|
4536
|
+
}
|
|
4537
|
+
if (intervalRef.current) {
|
|
4538
|
+
clearInterval(intervalRef.current);
|
|
4539
|
+
intervalRef.current = null;
|
|
4540
|
+
}
|
|
4541
|
+
}, []);
|
|
4542
|
+
useEffect(() => {
|
|
4543
|
+
const video = videoRef.current;
|
|
4544
|
+
if (!video || !cropping || !shouldPlay) {
|
|
4545
|
+
stopCanvasRendering();
|
|
4546
|
+
return;
|
|
4547
|
+
}
|
|
4548
|
+
const handlePlay = () => {
|
|
4549
|
+
if (cropping) {
|
|
4550
|
+
startCanvasRendering();
|
|
4551
|
+
}
|
|
4552
|
+
};
|
|
4553
|
+
const handlePause = () => {
|
|
4554
|
+
stopCanvasRendering();
|
|
4555
|
+
};
|
|
4556
|
+
const handleEnded = () => {
|
|
4557
|
+
stopCanvasRendering();
|
|
4558
|
+
};
|
|
4559
|
+
video.addEventListener("play", handlePlay);
|
|
4560
|
+
video.addEventListener("pause", handlePause);
|
|
4561
|
+
video.addEventListener("ended", handleEnded);
|
|
4562
|
+
if (!video.paused && video.readyState >= 2) {
|
|
4563
|
+
startCanvasRendering();
|
|
4564
|
+
}
|
|
4565
|
+
return () => {
|
|
4566
|
+
stopCanvasRendering();
|
|
4567
|
+
video.removeEventListener("play", handlePlay);
|
|
4568
|
+
video.removeEventListener("pause", handlePause);
|
|
4569
|
+
video.removeEventListener("ended", handleEnded);
|
|
4570
|
+
};
|
|
4571
|
+
}, [videoRef, cropping, shouldPlay, startCanvasRendering, stopCanvasRendering]);
|
|
4572
|
+
return {
|
|
4573
|
+
...hlsState,
|
|
4574
|
+
isCanvasRendering: isDrawingRef.current
|
|
4575
|
+
};
|
|
4576
|
+
}
|
|
4221
4577
|
function useThreads() {
|
|
4222
4578
|
const supabase = _getSupabaseInstance();
|
|
4223
4579
|
const fetcher = async (key) => {
|
|
@@ -4875,349 +5231,118 @@ function useNavigation(customNavigate) {
|
|
|
4875
5231
|
};
|
|
4876
5232
|
attemptNavigation();
|
|
4877
5233
|
},
|
|
4878
|
-
[router, customNavigate]
|
|
4879
|
-
);
|
|
4880
|
-
return {
|
|
4881
|
-
pathname,
|
|
4882
|
-
query,
|
|
4883
|
-
isReady,
|
|
4884
|
-
activeLineId,
|
|
4885
|
-
activeWorkspaceId,
|
|
4886
|
-
isActive,
|
|
4887
|
-
isInSection,
|
|
4888
|
-
isLineView,
|
|
4889
|
-
isWorkspaceView,
|
|
4890
|
-
goToDashboard,
|
|
4891
|
-
goToWorkspace,
|
|
4892
|
-
goToLine,
|
|
4893
|
-
goToTargets,
|
|
4894
|
-
goToShifts,
|
|
4895
|
-
goToLeaderboard,
|
|
4896
|
-
goToFactoryView,
|
|
4897
|
-
goToProfile,
|
|
4898
|
-
navigate
|
|
4899
|
-
};
|
|
4900
|
-
}
|
|
4901
|
-
function useWorkspaceNavigation() {
|
|
4902
|
-
const { defaultTimezone } = useDateTimeConfig();
|
|
4903
|
-
const getWorkspaceNavigationParams3 = useCallback(
|
|
4904
|
-
(workspaceId, options) => {
|
|
4905
|
-
let dateToUse = options?.date;
|
|
4906
|
-
if (!dateToUse && options?.useCurrentDate) {
|
|
4907
|
-
dateToUse = getOperationalDate(defaultTimezone || "UTC");
|
|
4908
|
-
}
|
|
4909
|
-
return {
|
|
4910
|
-
workspaceId,
|
|
4911
|
-
date: dateToUse,
|
|
4912
|
-
shift: options?.shift,
|
|
4913
|
-
sourceType: options?.sourceType
|
|
4914
|
-
};
|
|
4915
|
-
},
|
|
4916
|
-
[defaultTimezone]
|
|
4917
|
-
);
|
|
4918
|
-
return {
|
|
4919
|
-
getWorkspaceNavigationParams: getWorkspaceNavigationParams3
|
|
4920
|
-
};
|
|
4921
|
-
}
|
|
4922
|
-
function useDateFormatter() {
|
|
4923
|
-
const { defaultTimezone, defaultLocale, dateFormatOptions, timeFormatOptions, dateTimeFormatOptions } = useDateTimeConfig();
|
|
4924
|
-
const formatDate = useCallback(
|
|
4925
|
-
(date, formatString) => {
|
|
4926
|
-
const dateObj = typeof date === "string" ? parseISO(date) : date;
|
|
4927
|
-
if (!isValid(dateObj)) return "Invalid Date";
|
|
4928
|
-
const tz = defaultTimezone || "UTC";
|
|
4929
|
-
if (formatString) {
|
|
4930
|
-
return formatInTimeZone(dateObj, tz, formatString);
|
|
4931
|
-
}
|
|
4932
|
-
const effectiveOptions = dateFormatOptions || { year: "numeric", month: "short", day: "numeric" };
|
|
4933
|
-
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
4934
|
-
},
|
|
4935
|
-
[defaultTimezone, defaultLocale, dateFormatOptions]
|
|
4936
|
-
);
|
|
4937
|
-
const formatTime2 = useCallback(
|
|
4938
|
-
(date, formatString) => {
|
|
4939
|
-
const dateObj = typeof date === "string" ? parseISO(date) : date;
|
|
4940
|
-
if (!isValid(dateObj)) return "Invalid Time";
|
|
4941
|
-
const tz = defaultTimezone || "UTC";
|
|
4942
|
-
if (formatString) {
|
|
4943
|
-
return formatInTimeZone(dateObj, tz, formatString);
|
|
4944
|
-
}
|
|
4945
|
-
const effectiveOptions = timeFormatOptions || { hour: "numeric", minute: "numeric" };
|
|
4946
|
-
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
4947
|
-
},
|
|
4948
|
-
[defaultTimezone, defaultLocale, timeFormatOptions]
|
|
4949
|
-
);
|
|
4950
|
-
const formatDateTime = useCallback(
|
|
4951
|
-
(date, formatString) => {
|
|
4952
|
-
const dateObj = typeof date === "string" ? parseISO(date) : date;
|
|
4953
|
-
if (!isValid(dateObj)) return "Invalid Date/Time";
|
|
4954
|
-
const tz = defaultTimezone || "UTC";
|
|
4955
|
-
if (formatString) {
|
|
4956
|
-
return formatInTimeZone(dateObj, tz, formatString);
|
|
4957
|
-
}
|
|
4958
|
-
const effectiveOptions = dateTimeFormatOptions || { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "numeric" };
|
|
4959
|
-
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
4960
|
-
},
|
|
4961
|
-
[defaultTimezone, defaultLocale, dateTimeFormatOptions]
|
|
4962
|
-
);
|
|
4963
|
-
const getNow = useCallback(() => {
|
|
4964
|
-
return /* @__PURE__ */ new Date();
|
|
4965
|
-
}, []);
|
|
4966
|
-
return {
|
|
4967
|
-
formatDate,
|
|
4968
|
-
formatTime: formatTime2,
|
|
4969
|
-
formatDateTime,
|
|
4970
|
-
getNow,
|
|
4971
|
-
timezone: defaultTimezone || "UTC",
|
|
4972
|
-
locale: defaultLocale || "en-US"
|
|
4973
|
-
};
|
|
4974
|
-
}
|
|
4975
|
-
var useFormatNumber = () => {
|
|
4976
|
-
const { defaultLocale } = useDateTimeConfig();
|
|
4977
|
-
const formatNumber = useCallback(
|
|
4978
|
-
(value, options) => {
|
|
4979
|
-
try {
|
|
4980
|
-
return new Intl.NumberFormat(defaultLocale || "en-US", options).format(value);
|
|
4981
|
-
} catch (error) {
|
|
4982
|
-
console.error("Error formatting number:", error);
|
|
4983
|
-
return String(value);
|
|
4984
|
-
}
|
|
4985
|
-
},
|
|
4986
|
-
[defaultLocale]
|
|
4987
|
-
);
|
|
4988
|
-
return { formatNumber };
|
|
4989
|
-
};
|
|
4990
|
-
|
|
4991
|
-
// src/lib/utils/dashboardReload.ts
|
|
4992
|
-
var createThrottledReload = (interval = 5e3) => {
|
|
4993
|
-
let last = 0;
|
|
4994
|
-
let queued = false;
|
|
4995
|
-
const doReload = () => {
|
|
4996
|
-
if (typeof window !== "undefined") {
|
|
4997
|
-
window.location.reload();
|
|
4998
|
-
}
|
|
4999
|
-
};
|
|
5000
|
-
return () => {
|
|
5001
|
-
const now2 = Date.now();
|
|
5002
|
-
if (now2 - last >= interval) {
|
|
5003
|
-
last = now2;
|
|
5004
|
-
doReload();
|
|
5005
|
-
} else if (!queued) {
|
|
5006
|
-
queued = true;
|
|
5007
|
-
setTimeout(() => {
|
|
5008
|
-
queued = false;
|
|
5009
|
-
last = Date.now();
|
|
5010
|
-
doReload();
|
|
5011
|
-
}, interval - (now2 - last));
|
|
5012
|
-
}
|
|
5013
|
-
};
|
|
5014
|
-
};
|
|
5015
|
-
var throttledReloadDashboard = createThrottledReload(5e3);
|
|
5016
|
-
|
|
5017
|
-
// src/lib/hooks/useHlsStream.ts
|
|
5018
|
-
var HLS_CONFIG = {
|
|
5019
|
-
maxBufferLength: 8,
|
|
5020
|
-
maxMaxBufferLength: 15,
|
|
5021
|
-
lowLatencyMode: false,
|
|
5022
|
-
enableWorker: true,
|
|
5023
|
-
// Retry + timeout tuned for quick recovery
|
|
5024
|
-
manifestLoadingMaxRetry: 4,
|
|
5025
|
-
levelLoadingMaxRetry: 3,
|
|
5026
|
-
fragLoadingMaxRetry: 4,
|
|
5027
|
-
manifestLoadingRetryDelay: 500,
|
|
5028
|
-
levelLoadingRetryDelay: 500,
|
|
5029
|
-
fragLoadingRetryDelay: 500,
|
|
5030
|
-
manifestLoadingTimeOut: 1e4,
|
|
5031
|
-
levelLoadingTimeOut: 8e3,
|
|
5032
|
-
fragLoadingTimeOut: 1e4,
|
|
5033
|
-
liveSyncDurationCount: 2
|
|
5034
|
-
// Follow live edge aggressively
|
|
5035
|
-
};
|
|
5036
|
-
function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
5037
|
-
const [restartKey, setRestartKey] = useState(0);
|
|
5038
|
-
const hlsRef = useRef(null);
|
|
5039
|
-
const stallCheckIntervalRef = useRef(null);
|
|
5040
|
-
const noProgressTimerRef = useRef(null);
|
|
5041
|
-
const lastTimeUpdateRef = useRef(0);
|
|
5042
|
-
const softRestartCountRef = useRef(0);
|
|
5043
|
-
const isNativeHlsRef = useRef(false);
|
|
5044
|
-
const waitingTimerRef = useRef(null);
|
|
5045
|
-
const cleanup = () => {
|
|
5046
|
-
if (stallCheckIntervalRef.current) {
|
|
5047
|
-
clearInterval(stallCheckIntervalRef.current);
|
|
5048
|
-
stallCheckIntervalRef.current = null;
|
|
5049
|
-
}
|
|
5050
|
-
if (noProgressTimerRef.current) {
|
|
5051
|
-
clearTimeout(noProgressTimerRef.current);
|
|
5052
|
-
noProgressTimerRef.current = null;
|
|
5053
|
-
}
|
|
5054
|
-
if (waitingTimerRef.current) {
|
|
5055
|
-
clearTimeout(waitingTimerRef.current);
|
|
5056
|
-
waitingTimerRef.current = null;
|
|
5057
|
-
}
|
|
5058
|
-
if (hlsRef.current) {
|
|
5059
|
-
hlsRef.current.destroy();
|
|
5060
|
-
hlsRef.current = null;
|
|
5061
|
-
}
|
|
5062
|
-
const video = videoRef.current;
|
|
5063
|
-
if (video) {
|
|
5064
|
-
video.pause();
|
|
5065
|
-
video.removeAttribute("src");
|
|
5066
|
-
video.load();
|
|
5067
|
-
video.removeEventListener("waiting", handleWaiting);
|
|
5068
|
-
video.removeEventListener("timeupdate", handleTimeUpdate);
|
|
5069
|
-
video.removeEventListener("error", handleNativeError);
|
|
5070
|
-
}
|
|
5071
|
-
lastTimeUpdateRef.current = 0;
|
|
5072
|
-
softRestartCountRef.current = 0;
|
|
5073
|
-
};
|
|
5074
|
-
const seekToLiveEdge = () => {
|
|
5075
|
-
const hls = hlsRef.current;
|
|
5076
|
-
const video = videoRef.current;
|
|
5077
|
-
if (!hls || !video) return;
|
|
5078
|
-
if (hls.liveSyncPosition !== null && hls.liveSyncPosition !== void 0) {
|
|
5079
|
-
video.currentTime = hls.liveSyncPosition;
|
|
5080
|
-
} else if (hls.levels?.[hls.currentLevel]?.details) {
|
|
5081
|
-
const levelDetails = hls.levels[hls.currentLevel].details;
|
|
5082
|
-
if (levelDetails && levelDetails.edge !== void 0) {
|
|
5083
|
-
video.currentTime = Math.max(0, levelDetails.edge - 5);
|
|
5084
|
-
}
|
|
5085
|
-
}
|
|
5234
|
+
[router, customNavigate]
|
|
5235
|
+
);
|
|
5236
|
+
return {
|
|
5237
|
+
pathname,
|
|
5238
|
+
query,
|
|
5239
|
+
isReady,
|
|
5240
|
+
activeLineId,
|
|
5241
|
+
activeWorkspaceId,
|
|
5242
|
+
isActive,
|
|
5243
|
+
isInSection,
|
|
5244
|
+
isLineView,
|
|
5245
|
+
isWorkspaceView,
|
|
5246
|
+
goToDashboard,
|
|
5247
|
+
goToWorkspace,
|
|
5248
|
+
goToLine,
|
|
5249
|
+
goToTargets,
|
|
5250
|
+
goToShifts,
|
|
5251
|
+
goToLeaderboard,
|
|
5252
|
+
goToFactoryView,
|
|
5253
|
+
goToProfile,
|
|
5254
|
+
navigate
|
|
5086
5255
|
};
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
softRestartCountRef.current++;
|
|
5096
|
-
if (softRestartCountRef.current >= 5) {
|
|
5097
|
-
hardRestart(`${reason} (escalated after ${softRestartCountRef.current} soft restarts)`);
|
|
5256
|
+
}
|
|
5257
|
+
function useWorkspaceNavigation() {
|
|
5258
|
+
const { defaultTimezone } = useDateTimeConfig();
|
|
5259
|
+
const getWorkspaceNavigationParams3 = useCallback(
|
|
5260
|
+
(workspaceId, options) => {
|
|
5261
|
+
let dateToUse = options?.date;
|
|
5262
|
+
if (!dateToUse && options?.useCurrentDate) {
|
|
5263
|
+
dateToUse = getOperationalDate(defaultTimezone || "UTC");
|
|
5098
5264
|
}
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5265
|
+
return {
|
|
5266
|
+
workspaceId,
|
|
5267
|
+
date: dateToUse,
|
|
5268
|
+
shift: options?.shift,
|
|
5269
|
+
sourceType: options?.sourceType
|
|
5270
|
+
};
|
|
5271
|
+
},
|
|
5272
|
+
[defaultTimezone]
|
|
5273
|
+
);
|
|
5274
|
+
return {
|
|
5275
|
+
getWorkspaceNavigationParams: getWorkspaceNavigationParams3
|
|
5103
5276
|
};
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
if (
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5277
|
+
}
|
|
5278
|
+
function useDateFormatter() {
|
|
5279
|
+
const { defaultTimezone, defaultLocale, dateFormatOptions, timeFormatOptions, dateTimeFormatOptions } = useDateTimeConfig();
|
|
5280
|
+
const formatDate = useCallback(
|
|
5281
|
+
(date, formatString) => {
|
|
5282
|
+
const dateObj = typeof date === "string" ? parseISO(date) : date;
|
|
5283
|
+
if (!isValid(dateObj)) return "Invalid Date";
|
|
5284
|
+
const tz = defaultTimezone || "UTC";
|
|
5285
|
+
if (formatString) {
|
|
5286
|
+
return formatInTimeZone(dateObj, tz, formatString);
|
|
5114
5287
|
}
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
const
|
|
5125
|
-
if (
|
|
5126
|
-
|
|
5288
|
+
const effectiveOptions = dateFormatOptions || { year: "numeric", month: "short", day: "numeric" };
|
|
5289
|
+
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
5290
|
+
},
|
|
5291
|
+
[defaultTimezone, defaultLocale, dateFormatOptions]
|
|
5292
|
+
);
|
|
5293
|
+
const formatTime2 = useCallback(
|
|
5294
|
+
(date, formatString) => {
|
|
5295
|
+
const dateObj = typeof date === "string" ? parseISO(date) : date;
|
|
5296
|
+
if (!isValid(dateObj)) return "Invalid Time";
|
|
5297
|
+
const tz = defaultTimezone || "UTC";
|
|
5298
|
+
if (formatString) {
|
|
5299
|
+
return formatInTimeZone(dateObj, tz, formatString);
|
|
5127
5300
|
}
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
console.error("[HLS] Native video error");
|
|
5141
|
-
hardRestart("native video error");
|
|
5142
|
-
};
|
|
5143
|
-
const startStallDetection = () => {
|
|
5144
|
-
if (isNativeHlsRef.current) return;
|
|
5145
|
-
stallCheckIntervalRef.current = setInterval(() => {
|
|
5146
|
-
const video = videoRef.current;
|
|
5147
|
-
if (!video || video.paused || video.ended) return;
|
|
5148
|
-
const currentTime = video.currentTime;
|
|
5149
|
-
const lastTime = lastTimeUpdateRef.current;
|
|
5150
|
-
if (Math.abs(currentTime - lastTime) < 0.1 && video.readyState >= 2) {
|
|
5151
|
-
console.warn("[HLS] Playback stall detected");
|
|
5152
|
-
if (!noProgressTimerRef.current) {
|
|
5153
|
-
noProgressTimerRef.current = setTimeout(() => {
|
|
5154
|
-
softRestart("playback stall");
|
|
5155
|
-
noProgressTimerRef.current = null;
|
|
5156
|
-
}, 8e3);
|
|
5157
|
-
}
|
|
5158
|
-
} else {
|
|
5159
|
-
if (noProgressTimerRef.current) {
|
|
5160
|
-
clearTimeout(noProgressTimerRef.current);
|
|
5161
|
-
noProgressTimerRef.current = null;
|
|
5162
|
-
}
|
|
5301
|
+
const effectiveOptions = timeFormatOptions || { hour: "numeric", minute: "numeric" };
|
|
5302
|
+
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
5303
|
+
},
|
|
5304
|
+
[defaultTimezone, defaultLocale, timeFormatOptions]
|
|
5305
|
+
);
|
|
5306
|
+
const formatDateTime = useCallback(
|
|
5307
|
+
(date, formatString) => {
|
|
5308
|
+
const dateObj = typeof date === "string" ? parseISO(date) : date;
|
|
5309
|
+
if (!isValid(dateObj)) return "Invalid Date/Time";
|
|
5310
|
+
const tz = defaultTimezone || "UTC";
|
|
5311
|
+
if (formatString) {
|
|
5312
|
+
return formatInTimeZone(dateObj, tz, formatString);
|
|
5163
5313
|
}
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
if (!video) return;
|
|
5173
|
-
isNativeHlsRef.current = video.canPlayType("application/vnd.apple.mpegurl") === "probably";
|
|
5174
|
-
if (Hls2.isSupported() && !isNativeHlsRef.current) {
|
|
5175
|
-
const hls = new Hls2(HLS_CONFIG);
|
|
5176
|
-
hlsRef.current = hls;
|
|
5177
|
-
hls.attachMedia(video);
|
|
5178
|
-
hls.loadSource(src);
|
|
5179
|
-
hls.on(Hls2.Events.ERROR, (_, data) => {
|
|
5180
|
-
if (!data.fatal) return;
|
|
5181
|
-
console.error("[HLS] Fatal error:", data.type, data.details);
|
|
5182
|
-
if (data.response?.code === 404) {
|
|
5183
|
-
hardRestart("404 hard restart");
|
|
5184
|
-
return;
|
|
5185
|
-
}
|
|
5186
|
-
switch (data.type) {
|
|
5187
|
-
case Hls2.ErrorTypes.NETWORK_ERROR:
|
|
5188
|
-
case Hls2.ErrorTypes.MEDIA_ERROR:
|
|
5189
|
-
softRestart(`${data.type}: ${data.details}`);
|
|
5190
|
-
break;
|
|
5191
|
-
default:
|
|
5192
|
-
hardRestart(`Fatal ${data.type}: ${data.details}`);
|
|
5193
|
-
break;
|
|
5194
|
-
}
|
|
5195
|
-
});
|
|
5196
|
-
hls.on(Hls2.Events.MANIFEST_PARSED, () => {
|
|
5197
|
-
video.play().catch((err) => {
|
|
5198
|
-
console.error("[HLS] Play failed:", err);
|
|
5199
|
-
});
|
|
5200
|
-
});
|
|
5201
|
-
video.addEventListener("waiting", handleWaiting);
|
|
5202
|
-
video.addEventListener("timeupdate", handleTimeUpdate);
|
|
5203
|
-
startStallDetection();
|
|
5204
|
-
} else if (isNativeHlsRef.current) {
|
|
5205
|
-
console.log("[HLS] Using native HLS");
|
|
5206
|
-
video.src = src;
|
|
5207
|
-
video.addEventListener("error", handleNativeError);
|
|
5208
|
-
video.play().catch((err) => {
|
|
5209
|
-
console.error("[HLS] Native play failed:", err);
|
|
5210
|
-
});
|
|
5211
|
-
} else {
|
|
5212
|
-
console.error("[HLS] HLS not supported");
|
|
5213
|
-
}
|
|
5214
|
-
return cleanup;
|
|
5215
|
-
}, [src, shouldPlay, restartKey, onFatalError]);
|
|
5314
|
+
const effectiveOptions = dateTimeFormatOptions || { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "numeric" };
|
|
5315
|
+
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
5316
|
+
},
|
|
5317
|
+
[defaultTimezone, defaultLocale, dateTimeFormatOptions]
|
|
5318
|
+
);
|
|
5319
|
+
const getNow = useCallback(() => {
|
|
5320
|
+
return /* @__PURE__ */ new Date();
|
|
5321
|
+
}, []);
|
|
5216
5322
|
return {
|
|
5217
|
-
|
|
5218
|
-
|
|
5323
|
+
formatDate,
|
|
5324
|
+
formatTime: formatTime2,
|
|
5325
|
+
formatDateTime,
|
|
5326
|
+
getNow,
|
|
5327
|
+
timezone: defaultTimezone || "UTC",
|
|
5328
|
+
locale: defaultLocale || "en-US"
|
|
5219
5329
|
};
|
|
5220
5330
|
}
|
|
5331
|
+
var useFormatNumber = () => {
|
|
5332
|
+
const { defaultLocale } = useDateTimeConfig();
|
|
5333
|
+
const formatNumber = useCallback(
|
|
5334
|
+
(value, options) => {
|
|
5335
|
+
try {
|
|
5336
|
+
return new Intl.NumberFormat(defaultLocale || "en-US", options).format(value);
|
|
5337
|
+
} catch (error) {
|
|
5338
|
+
console.error("Error formatting number:", error);
|
|
5339
|
+
return String(value);
|
|
5340
|
+
}
|
|
5341
|
+
},
|
|
5342
|
+
[defaultLocale]
|
|
5343
|
+
);
|
|
5344
|
+
return { formatNumber };
|
|
5345
|
+
};
|
|
5221
5346
|
|
|
5222
5347
|
// src/lib/utils/api.ts
|
|
5223
5348
|
var apiUtils = {
|
|
@@ -17159,15 +17284,15 @@ var HourlyOutputChart = ({
|
|
|
17159
17284
|
renderLegend()
|
|
17160
17285
|
] });
|
|
17161
17286
|
};
|
|
17162
|
-
|
|
17163
|
-
|
|
17164
|
-
|
|
17165
|
-
|
|
17166
|
-
|
|
17167
|
-
|
|
17168
|
-
|
|
17169
|
-
}
|
|
17170
|
-
|
|
17287
|
+
function getTrendArrowAndColor(trend) {
|
|
17288
|
+
if (trend > 0) {
|
|
17289
|
+
return { arrow: "\u2191", color: "text-green-400" };
|
|
17290
|
+
} else if (trend < 0) {
|
|
17291
|
+
return { arrow: "\u2193", color: "text-red-400" };
|
|
17292
|
+
} else {
|
|
17293
|
+
return { arrow: "\u2192", color: "text-gray-400" };
|
|
17294
|
+
}
|
|
17295
|
+
}
|
|
17171
17296
|
var VideoCard = React14__default.memo(({
|
|
17172
17297
|
workspace,
|
|
17173
17298
|
hlsUrl,
|
|
@@ -17175,14 +17300,29 @@ var VideoCard = React14__default.memo(({
|
|
|
17175
17300
|
onClick,
|
|
17176
17301
|
onFatalError,
|
|
17177
17302
|
isVeryLowEfficiency = false,
|
|
17303
|
+
cropping,
|
|
17304
|
+
canvasFps = 30,
|
|
17305
|
+
useRAF = true,
|
|
17178
17306
|
className = ""
|
|
17179
17307
|
}) => {
|
|
17180
17308
|
const videoRef = useRef(null);
|
|
17181
|
-
|
|
17182
|
-
|
|
17183
|
-
|
|
17184
|
-
|
|
17185
|
-
|
|
17309
|
+
const canvasRef = useRef(null);
|
|
17310
|
+
if (cropping) {
|
|
17311
|
+
useHlsStreamWithCropping(videoRef, canvasRef, {
|
|
17312
|
+
src: hlsUrl,
|
|
17313
|
+
shouldPlay,
|
|
17314
|
+
cropping,
|
|
17315
|
+
canvasFps,
|
|
17316
|
+
useRAF,
|
|
17317
|
+
onFatalError: onFatalError ?? (() => throttledReloadDashboard())
|
|
17318
|
+
});
|
|
17319
|
+
} else {
|
|
17320
|
+
useHlsStream(videoRef, {
|
|
17321
|
+
src: hlsUrl,
|
|
17322
|
+
shouldPlay,
|
|
17323
|
+
onFatalError: onFatalError ?? (() => throttledReloadDashboard())
|
|
17324
|
+
});
|
|
17325
|
+
}
|
|
17186
17326
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
17187
17327
|
workspace.workspace_uuid || workspace.workspace_name;
|
|
17188
17328
|
const getEfficiencyOverlayColor = (efficiency) => {
|
|
@@ -17237,17 +17377,26 @@ var VideoCard = React14__default.memo(({
|
|
|
17237
17377
|
/* @__PURE__ */ jsx(Camera, { className: "w-6 h-6 text-gray-500" }),
|
|
17238
17378
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500 mt-1", children: "Loading..." })
|
|
17239
17379
|
] }) }),
|
|
17240
|
-
/* @__PURE__ */
|
|
17241
|
-
|
|
17242
|
-
|
|
17243
|
-
|
|
17244
|
-
|
|
17245
|
-
|
|
17246
|
-
|
|
17247
|
-
|
|
17248
|
-
|
|
17249
|
-
|
|
17250
|
-
|
|
17380
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute inset-0 z-10", children: [
|
|
17381
|
+
/* @__PURE__ */ jsx(
|
|
17382
|
+
"video",
|
|
17383
|
+
{
|
|
17384
|
+
ref: videoRef,
|
|
17385
|
+
className: `h-full w-full object-cover ${cropping ? "hidden" : ""}`,
|
|
17386
|
+
playsInline: true,
|
|
17387
|
+
muted: true,
|
|
17388
|
+
disablePictureInPicture: true,
|
|
17389
|
+
controlsList: "nodownload noplaybackrate"
|
|
17390
|
+
}
|
|
17391
|
+
),
|
|
17392
|
+
cropping && /* @__PURE__ */ jsx(
|
|
17393
|
+
"canvas",
|
|
17394
|
+
{
|
|
17395
|
+
ref: canvasRef,
|
|
17396
|
+
className: "h-full w-full object-cover"
|
|
17397
|
+
}
|
|
17398
|
+
)
|
|
17399
|
+
] }),
|
|
17251
17400
|
/* @__PURE__ */ jsx("div", { className: `absolute inset-0 z-20 pointer-events-none ${efficiencyOverlayClass}` }),
|
|
17252
17401
|
/* @__PURE__ */ jsxs("div", { className: "absolute top-2 right-2 z-30 bg-black/70 backdrop-blur-sm rounded px-2 py-0.5 text-white text-xs font-semibold border border-white/10", children: [
|
|
17253
17402
|
Math.round(workspace.efficiency),
|
|
@@ -17283,7 +17432,7 @@ var VideoCard = React14__default.memo(({
|
|
|
17283
17432
|
}
|
|
17284
17433
|
);
|
|
17285
17434
|
}, (prevProps, nextProps) => {
|
|
17286
|
-
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay;
|
|
17435
|
+
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay && prevProps.cropping?.x === nextProps.cropping?.x && prevProps.cropping?.y === nextProps.cropping?.y && prevProps.cropping?.width === nextProps.cropping?.width && prevProps.cropping?.height === nextProps.cropping?.height;
|
|
17287
17436
|
});
|
|
17288
17437
|
VideoCard.displayName = "VideoCard";
|
|
17289
17438
|
var DEFAULT_WORKSPACE_HLS_URLS = {
|
|
@@ -17311,6 +17460,8 @@ var VideoGridView = React14__default.memo(({
|
|
|
17311
17460
|
const observerRef = useRef(null);
|
|
17312
17461
|
const [gridCols, setGridCols] = useState(4);
|
|
17313
17462
|
const [visibleWorkspaces, setVisibleWorkspaces] = useState(/* @__PURE__ */ new Set());
|
|
17463
|
+
const videoConfig = useVideoConfig();
|
|
17464
|
+
const { cropping, canvasConfig } = videoConfig;
|
|
17314
17465
|
const mergedVideoSources = {
|
|
17315
17466
|
defaultHlsUrl: videoSources.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17316
17467
|
workspaceHlsUrls: { ...DEFAULT_WORKSPACE_HLS_URLS, ...videoSources.workspaceHlsUrls }
|
|
@@ -17319,6 +17470,13 @@ var VideoGridView = React14__default.memo(({
|
|
|
17319
17470
|
const wsName = workspaceName.toUpperCase();
|
|
17320
17471
|
return mergedVideoSources.workspaceHlsUrls[wsName] || mergedVideoSources.defaultHlsUrl;
|
|
17321
17472
|
}, [mergedVideoSources]);
|
|
17473
|
+
const getWorkspaceCropping = useCallback((workspaceName) => {
|
|
17474
|
+
if (!cropping) return void 0;
|
|
17475
|
+
if (cropping.workspaceOverrides?.[workspaceName]) {
|
|
17476
|
+
return cropping.workspaceOverrides[workspaceName];
|
|
17477
|
+
}
|
|
17478
|
+
return cropping.default;
|
|
17479
|
+
}, [cropping]);
|
|
17322
17480
|
const veryLowEfficiencyWorkspaces = useMemo(() => {
|
|
17323
17481
|
return new Set(
|
|
17324
17482
|
workspaces.filter((w) => w.efficiency < 50 && w.efficiency >= 10).map((w) => w.workspace_name)
|
|
@@ -17457,6 +17615,7 @@ var VideoGridView = React14__default.memo(({
|
|
|
17457
17615
|
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
17458
17616
|
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
17459
17617
|
const isVeryLowEfficiency = veryLowEfficiencyWorkspaces.has(workspace.workspace_name);
|
|
17618
|
+
const workspaceCropping = getWorkspaceCropping(workspace.workspace_name);
|
|
17460
17619
|
return /* @__PURE__ */ jsx(
|
|
17461
17620
|
"div",
|
|
17462
17621
|
{
|
|
@@ -17471,7 +17630,10 @@ var VideoGridView = React14__default.memo(({
|
|
|
17471
17630
|
shouldPlay: isVisible,
|
|
17472
17631
|
onClick: () => handleWorkspaceClick(workspace),
|
|
17473
17632
|
onFatalError: throttledReloadDashboard,
|
|
17474
|
-
isVeryLowEfficiency
|
|
17633
|
+
isVeryLowEfficiency,
|
|
17634
|
+
cropping: workspaceCropping,
|
|
17635
|
+
canvasFps: canvasConfig?.fps,
|
|
17636
|
+
useRAF: canvasConfig?.useRAF
|
|
17475
17637
|
}
|
|
17476
17638
|
)
|
|
17477
17639
|
},
|
|
@@ -22298,12 +22460,12 @@ var getEfficiencyColor = (efficiency) => {
|
|
|
22298
22460
|
return "bg-[#E34329]/90 hover:bg-[#E34329]/95";
|
|
22299
22461
|
}
|
|
22300
22462
|
};
|
|
22301
|
-
var
|
|
22463
|
+
var TREND_STYLES = {
|
|
22302
22464
|
0: { arrow: "\u2193", color: "text-red-500 font-bold text-shadow" },
|
|
22303
22465
|
1: { arrow: "=", color: "text-gray-500 font-bold text-shadow" },
|
|
22304
22466
|
2: { arrow: "\u2191", color: "text-green-500 font-bold text-shadow" }
|
|
22305
22467
|
};
|
|
22306
|
-
var getTrendArrowAndColor2 = (trend) =>
|
|
22468
|
+
var getTrendArrowAndColor2 = (trend) => TREND_STYLES[trend] || { arrow: "", color: "" };
|
|
22307
22469
|
var ARROW_POSITIONS = {
|
|
22308
22470
|
top: "-bottom-6",
|
|
22309
22471
|
"middle-top": "-bottom-6",
|
|
@@ -30744,4 +30906,4 @@ var S3Service = class {
|
|
|
30744
30906
|
}
|
|
30745
30907
|
};
|
|
30746
30908
|
|
|
30747
|
-
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GridComponentsPlaceholder, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, ProfileView_default as ProfileView, RegistryProvider, S3Service, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
|
|
30909
|
+
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GridComponentsPlaceholder, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, ProfileView_default as ProfileView, RegistryProvider, S3Service, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
|