@optifye/dashboard-core 6.0.8 → 6.1.0
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 +29 -43
- package/dist/index.d.ts +29 -43
- package/dist/index.js +469 -136
- package/dist/index.mjs +469 -138
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5016,34 +5016,6 @@ var useWorkspaceOperators = (workspaceId, options) => {
|
|
|
5016
5016
|
refetch: fetchData
|
|
5017
5017
|
};
|
|
5018
5018
|
};
|
|
5019
|
-
|
|
5020
|
-
// src/lib/utils/dashboardReload.ts
|
|
5021
|
-
var createThrottledReload = (interval = 5e3) => {
|
|
5022
|
-
let last = 0;
|
|
5023
|
-
let queued = false;
|
|
5024
|
-
const doReload = () => {
|
|
5025
|
-
if (typeof window !== "undefined") {
|
|
5026
|
-
window.location.reload();
|
|
5027
|
-
}
|
|
5028
|
-
};
|
|
5029
|
-
return () => {
|
|
5030
|
-
const now2 = Date.now();
|
|
5031
|
-
if (now2 - last >= interval) {
|
|
5032
|
-
last = now2;
|
|
5033
|
-
doReload();
|
|
5034
|
-
} else if (!queued) {
|
|
5035
|
-
queued = true;
|
|
5036
|
-
setTimeout(() => {
|
|
5037
|
-
queued = false;
|
|
5038
|
-
last = Date.now();
|
|
5039
|
-
doReload();
|
|
5040
|
-
}, interval - (now2 - last));
|
|
5041
|
-
}
|
|
5042
|
-
};
|
|
5043
|
-
};
|
|
5044
|
-
var throttledReloadDashboard = createThrottledReload(5e3);
|
|
5045
|
-
|
|
5046
|
-
// src/lib/hooks/useHlsStream.ts
|
|
5047
5019
|
var HLS_CONFIG = {
|
|
5048
5020
|
maxBufferLength: 8,
|
|
5049
5021
|
maxMaxBufferLength: 15,
|
|
@@ -5062,7 +5034,35 @@ var HLS_CONFIG = {
|
|
|
5062
5034
|
liveSyncDurationCount: 2
|
|
5063
5035
|
// Follow live edge aggressively
|
|
5064
5036
|
};
|
|
5037
|
+
var failedUrls = /* @__PURE__ */ new Map();
|
|
5038
|
+
var MAX_FAILURES_PER_URL = 3;
|
|
5039
|
+
var FAILURE_EXPIRY_MS = 5 * 60 * 1e3;
|
|
5040
|
+
function resetFailedUrl(url) {
|
|
5041
|
+
if (failedUrls.has(url)) {
|
|
5042
|
+
console.log(`[HLS] Manually resetting failed URL: ${url}`);
|
|
5043
|
+
failedUrls.delete(url);
|
|
5044
|
+
}
|
|
5045
|
+
}
|
|
5046
|
+
function isUrlPermanentlyFailed(url) {
|
|
5047
|
+
const failure = failedUrls.get(url);
|
|
5048
|
+
return failure?.permanentlyFailed || false;
|
|
5049
|
+
}
|
|
5065
5050
|
function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
5051
|
+
const urlFailure = failedUrls.get(src);
|
|
5052
|
+
const isPermanentlyFailed = urlFailure?.permanentlyFailed || false;
|
|
5053
|
+
const cleanupFailedUrls = () => {
|
|
5054
|
+
const now2 = Date.now();
|
|
5055
|
+
const expiredUrls = [];
|
|
5056
|
+
failedUrls.forEach((failure, url) => {
|
|
5057
|
+
if (now2 - failure.timestamp > FAILURE_EXPIRY_MS) {
|
|
5058
|
+
expiredUrls.push(url);
|
|
5059
|
+
}
|
|
5060
|
+
});
|
|
5061
|
+
expiredUrls.forEach((url) => {
|
|
5062
|
+
console.log(`[HLS] Removing expired failure entry for: ${url}`);
|
|
5063
|
+
failedUrls.delete(url);
|
|
5064
|
+
});
|
|
5065
|
+
};
|
|
5066
5066
|
const [restartKey, setRestartKey] = React19.useState(0);
|
|
5067
5067
|
const hlsRef = React19.useRef(null);
|
|
5068
5068
|
const stallCheckIntervalRef = React19.useRef(null);
|
|
@@ -5132,14 +5132,33 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
|
5132
5132
|
};
|
|
5133
5133
|
const hardRestart = (reason) => {
|
|
5134
5134
|
console.warn(`[HLS] Hard restart: ${reason}`);
|
|
5135
|
+
cleanupFailedUrls();
|
|
5136
|
+
const failure = failedUrls.get(src);
|
|
5137
|
+
const failureCount = failure ? failure.count : 0;
|
|
5138
|
+
if (failureCount >= MAX_FAILURES_PER_URL) {
|
|
5139
|
+
console.error(`[HLS] URL has failed ${failureCount} times. Marking as permanently failed: ${src}`);
|
|
5140
|
+
failedUrls.set(src, {
|
|
5141
|
+
count: failureCount,
|
|
5142
|
+
timestamp: Date.now(),
|
|
5143
|
+
permanentlyFailed: true
|
|
5144
|
+
});
|
|
5145
|
+
cleanup();
|
|
5146
|
+
if (onFatalError) {
|
|
5147
|
+
onFatalError();
|
|
5148
|
+
}
|
|
5149
|
+
return;
|
|
5150
|
+
}
|
|
5151
|
+
failedUrls.set(src, {
|
|
5152
|
+
count: failureCount + 1,
|
|
5153
|
+
timestamp: Date.now(),
|
|
5154
|
+
permanentlyFailed: false
|
|
5155
|
+
});
|
|
5135
5156
|
cleanup();
|
|
5136
5157
|
setRestartKey((k) => k + 1);
|
|
5137
5158
|
softRestartCountRef.current = 0;
|
|
5138
|
-
if (reason.includes("hard restart")
|
|
5159
|
+
if (reason.includes("404 hard restart")) {
|
|
5139
5160
|
if (onFatalError) {
|
|
5140
5161
|
onFatalError();
|
|
5141
|
-
} else {
|
|
5142
|
-
throttledReloadDashboard();
|
|
5143
5162
|
}
|
|
5144
5163
|
}
|
|
5145
5164
|
};
|
|
@@ -5193,6 +5212,13 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
|
5193
5212
|
}, 7e3);
|
|
5194
5213
|
};
|
|
5195
5214
|
React19.useEffect(() => {
|
|
5215
|
+
if (isPermanentlyFailed) {
|
|
5216
|
+
console.warn(`[HLS] URL is permanently failed, not attempting to load: ${src}`);
|
|
5217
|
+
if (onFatalError) {
|
|
5218
|
+
onFatalError();
|
|
5219
|
+
}
|
|
5220
|
+
return;
|
|
5221
|
+
}
|
|
5196
5222
|
if (!src || !shouldPlay) {
|
|
5197
5223
|
cleanup();
|
|
5198
5224
|
return;
|
|
@@ -5223,6 +5249,10 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
|
5223
5249
|
}
|
|
5224
5250
|
});
|
|
5225
5251
|
hls.on(Hls2__default.default.Events.MANIFEST_PARSED, () => {
|
|
5252
|
+
if (failedUrls.has(src)) {
|
|
5253
|
+
console.log(`[HLS] Stream loaded successfully, resetting failure count for: ${src}`);
|
|
5254
|
+
failedUrls.delete(src);
|
|
5255
|
+
}
|
|
5226
5256
|
video.play().catch((err) => {
|
|
5227
5257
|
console.error("[HLS] Play failed:", err);
|
|
5228
5258
|
});
|
|
@@ -5241,7 +5271,7 @@ function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
|
5241
5271
|
console.error("[HLS] HLS not supported");
|
|
5242
5272
|
}
|
|
5243
5273
|
return cleanup;
|
|
5244
|
-
}, [src, shouldPlay, restartKey, onFatalError]);
|
|
5274
|
+
}, [src, shouldPlay, restartKey, onFatalError, isPermanentlyFailed]);
|
|
5245
5275
|
return {
|
|
5246
5276
|
restartKey,
|
|
5247
5277
|
isNativeHls: isNativeHlsRef.current
|
|
@@ -6346,7 +6376,7 @@ function useNavigation(customNavigate) {
|
|
|
6346
6376
|
}
|
|
6347
6377
|
function useWorkspaceNavigation() {
|
|
6348
6378
|
const { defaultTimezone } = useDateTimeConfig();
|
|
6349
|
-
const
|
|
6379
|
+
const getWorkspaceNavigationParams2 = React19.useCallback(
|
|
6350
6380
|
(workspaceId, options) => {
|
|
6351
6381
|
let dateToUse = options?.date;
|
|
6352
6382
|
if (!dateToUse && options?.useCurrentDate) {
|
|
@@ -6362,7 +6392,7 @@ function useWorkspaceNavigation() {
|
|
|
6362
6392
|
[defaultTimezone]
|
|
6363
6393
|
);
|
|
6364
6394
|
return {
|
|
6365
|
-
getWorkspaceNavigationParams:
|
|
6395
|
+
getWorkspaceNavigationParams: getWorkspaceNavigationParams2
|
|
6366
6396
|
};
|
|
6367
6397
|
}
|
|
6368
6398
|
function useDateFormatter() {
|
|
@@ -9060,9 +9090,15 @@ var getStoredWorkspaceMappings = () => {
|
|
|
9060
9090
|
var getDefaultTabForWorkspace = (workspaceId, displayName) => {
|
|
9061
9091
|
return "overview";
|
|
9062
9092
|
};
|
|
9063
|
-
var getWorkspaceNavigationParams = (workspaceId, displayName) => {
|
|
9093
|
+
var getWorkspaceNavigationParams = (workspaceId, displayName, lineId) => {
|
|
9064
9094
|
const defaultTab = getDefaultTabForWorkspace();
|
|
9065
|
-
|
|
9095
|
+
const params = new URLSearchParams();
|
|
9096
|
+
params.set("displayName", displayName);
|
|
9097
|
+
params.set("defaultTab", defaultTab);
|
|
9098
|
+
if (lineId) {
|
|
9099
|
+
params.set("lineId", lineId);
|
|
9100
|
+
}
|
|
9101
|
+
return `?${params.toString()}`;
|
|
9066
9102
|
};
|
|
9067
9103
|
|
|
9068
9104
|
// src/lib/utils/videoPreloader.ts
|
|
@@ -9383,6 +9419,115 @@ var clearS3VideoCache = () => {
|
|
|
9383
9419
|
var preloadS3VideoUrl = s3VideoPreloader.preloadVideo;
|
|
9384
9420
|
var preloadS3VideosUrl = s3VideoPreloader.preloadVideos;
|
|
9385
9421
|
|
|
9422
|
+
// src/lib/utils/dashboardReload.ts
|
|
9423
|
+
var reloadAttempts = [];
|
|
9424
|
+
var createThrottledReload = (interval = 5e3, maxReloads = 3) => {
|
|
9425
|
+
const circuitBreakerWindow = 1e4;
|
|
9426
|
+
const circuitBreakerThreshold = 5;
|
|
9427
|
+
let last = 0;
|
|
9428
|
+
let queued = false;
|
|
9429
|
+
let reloadCount = 0;
|
|
9430
|
+
let firstReloadTime = 0;
|
|
9431
|
+
const resetWindow = 6e4;
|
|
9432
|
+
const doReload = () => {
|
|
9433
|
+
if (typeof window !== "undefined") {
|
|
9434
|
+
const now2 = Date.now();
|
|
9435
|
+
reloadAttempts.push(now2);
|
|
9436
|
+
const cutoff = now2 - circuitBreakerWindow;
|
|
9437
|
+
const recentAttempts = reloadAttempts.filter((t) => t > cutoff);
|
|
9438
|
+
reloadAttempts.length = 0;
|
|
9439
|
+
reloadAttempts.push(...recentAttempts);
|
|
9440
|
+
if (recentAttempts.length >= circuitBreakerThreshold) {
|
|
9441
|
+
console.error(`[Dashboard Reload] Circuit breaker triggered! ${recentAttempts.length} reload attempts in ${circuitBreakerWindow}ms`);
|
|
9442
|
+
const errorDiv = document.createElement("div");
|
|
9443
|
+
errorDiv.id = "reload-circuit-breaker";
|
|
9444
|
+
errorDiv.style.cssText = `
|
|
9445
|
+
position: fixed;
|
|
9446
|
+
top: 20px;
|
|
9447
|
+
left: 50%;
|
|
9448
|
+
transform: translateX(-50%);
|
|
9449
|
+
background: #dc2626;
|
|
9450
|
+
color: white;
|
|
9451
|
+
padding: 20px 32px;
|
|
9452
|
+
border-radius: 12px;
|
|
9453
|
+
z-index: 99999;
|
|
9454
|
+
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3);
|
|
9455
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
9456
|
+
`;
|
|
9457
|
+
errorDiv.innerHTML = `
|
|
9458
|
+
<div style="display: flex; align-items: center; gap: 16px;">
|
|
9459
|
+
<svg width="24" height="24" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
9460
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
|
|
9461
|
+
</svg>
|
|
9462
|
+
<div>
|
|
9463
|
+
<div style="font-weight: 600; font-size: 16px; margin-bottom: 4px;">Too many reload attempts detected</div>
|
|
9464
|
+
<div style="font-size: 14px; opacity: 0.9;">Please check your network connection and refresh manually.</div>
|
|
9465
|
+
</div>
|
|
9466
|
+
</div>
|
|
9467
|
+
`;
|
|
9468
|
+
const existing = document.getElementById("reload-circuit-breaker");
|
|
9469
|
+
if (existing) existing.remove();
|
|
9470
|
+
document.body.appendChild(errorDiv);
|
|
9471
|
+
return;
|
|
9472
|
+
}
|
|
9473
|
+
if (now2 - firstReloadTime > resetWindow) {
|
|
9474
|
+
reloadCount = 0;
|
|
9475
|
+
firstReloadTime = now2;
|
|
9476
|
+
}
|
|
9477
|
+
if (reloadCount === 0) {
|
|
9478
|
+
firstReloadTime = now2;
|
|
9479
|
+
}
|
|
9480
|
+
reloadCount++;
|
|
9481
|
+
if (reloadCount > maxReloads) {
|
|
9482
|
+
console.error(`[Dashboard Reload] Maximum reload attempts (${maxReloads}) reached. Stopping to prevent infinite loop.`);
|
|
9483
|
+
const errorDiv = document.createElement("div");
|
|
9484
|
+
errorDiv.style.cssText = `
|
|
9485
|
+
position: fixed;
|
|
9486
|
+
top: 20px;
|
|
9487
|
+
left: 50%;
|
|
9488
|
+
transform: translateX(-50%);
|
|
9489
|
+
background: #ef4444;
|
|
9490
|
+
color: white;
|
|
9491
|
+
padding: 16px 24px;
|
|
9492
|
+
border-radius: 8px;
|
|
9493
|
+
z-index: 9999;
|
|
9494
|
+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
9495
|
+
`;
|
|
9496
|
+
errorDiv.innerHTML = `
|
|
9497
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
9498
|
+
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
9499
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
9500
|
+
</svg>
|
|
9501
|
+
<span>Stream connection failed. Please refresh the page manually.</span>
|
|
9502
|
+
</div>
|
|
9503
|
+
`;
|
|
9504
|
+
document.body.appendChild(errorDiv);
|
|
9505
|
+
setTimeout(() => {
|
|
9506
|
+
document.body.removeChild(errorDiv);
|
|
9507
|
+
}, 1e4);
|
|
9508
|
+
return;
|
|
9509
|
+
}
|
|
9510
|
+
console.warn(`[Dashboard Reload] Reloading dashboard (attempt ${reloadCount}/${maxReloads})`);
|
|
9511
|
+
window.location.reload();
|
|
9512
|
+
}
|
|
9513
|
+
};
|
|
9514
|
+
return () => {
|
|
9515
|
+
const now2 = Date.now();
|
|
9516
|
+
if (now2 - last >= interval) {
|
|
9517
|
+
last = now2;
|
|
9518
|
+
doReload();
|
|
9519
|
+
} else if (!queued) {
|
|
9520
|
+
queued = true;
|
|
9521
|
+
setTimeout(() => {
|
|
9522
|
+
queued = false;
|
|
9523
|
+
last = Date.now();
|
|
9524
|
+
doReload();
|
|
9525
|
+
}, interval - (now2 - last));
|
|
9526
|
+
}
|
|
9527
|
+
};
|
|
9528
|
+
};
|
|
9529
|
+
var throttledReloadDashboard = createThrottledReload(5e3, 3);
|
|
9530
|
+
|
|
9386
9531
|
// src/lib/utils/index.ts
|
|
9387
9532
|
var formatIdleTime = (idleTimeInSeconds) => {
|
|
9388
9533
|
if (!idleTimeInSeconds || idleTimeInSeconds <= 0) {
|
|
@@ -18666,7 +18811,10 @@ var VideoGridView = React19__namespace.default.memo(({
|
|
|
18666
18811
|
const containerRef = React19.useRef(null);
|
|
18667
18812
|
const observerRef = React19.useRef(null);
|
|
18668
18813
|
const [gridCols, setGridCols] = React19.useState(4);
|
|
18814
|
+
const [gridRows, setGridRows] = React19.useState(1);
|
|
18669
18815
|
const [visibleWorkspaces, setVisibleWorkspaces] = React19.useState(/* @__PURE__ */ new Set());
|
|
18816
|
+
const [cardDimensions, setCardDimensions] = React19.useState({ width: 0, height: 0 });
|
|
18817
|
+
const [failedStreams, setFailedStreams] = React19.useState(/* @__PURE__ */ new Set());
|
|
18670
18818
|
const videoConfig = useVideoConfig();
|
|
18671
18819
|
const { cropping, canvasConfig, hlsUrls } = videoConfig;
|
|
18672
18820
|
const mergedVideoSources = {
|
|
@@ -18727,35 +18875,51 @@ var VideoGridView = React19__namespace.default.memo(({
|
|
|
18727
18875
|
setGridCols(1);
|
|
18728
18876
|
return;
|
|
18729
18877
|
}
|
|
18730
|
-
|
|
18731
|
-
|
|
18878
|
+
const optimalLayouts = {
|
|
18879
|
+
1: 1,
|
|
18880
|
+
2: 2,
|
|
18881
|
+
3: 3,
|
|
18882
|
+
4: 2,
|
|
18883
|
+
5: 3,
|
|
18884
|
+
6: 3,
|
|
18885
|
+
7: 4,
|
|
18886
|
+
8: 4,
|
|
18887
|
+
9: 3,
|
|
18888
|
+
10: 5,
|
|
18889
|
+
11: 4,
|
|
18890
|
+
12: 4,
|
|
18891
|
+
13: 5,
|
|
18892
|
+
14: 5,
|
|
18893
|
+
15: 5,
|
|
18894
|
+
16: 4,
|
|
18895
|
+
17: 6,
|
|
18896
|
+
18: 6,
|
|
18897
|
+
19: 5,
|
|
18898
|
+
20: 5,
|
|
18899
|
+
21: 7,
|
|
18900
|
+
22: 6,
|
|
18901
|
+
23: 6,
|
|
18902
|
+
24: 6
|
|
18903
|
+
};
|
|
18904
|
+
let bestCols = optimalLayouts[count] || Math.ceil(Math.sqrt(count));
|
|
18905
|
+
const containerAspectRatio = containerWidth / containerHeight;
|
|
18732
18906
|
const targetAspectRatio = 16 / 9;
|
|
18733
18907
|
const gap = 8;
|
|
18734
|
-
|
|
18735
|
-
|
|
18736
|
-
|
|
18737
|
-
|
|
18738
|
-
|
|
18739
|
-
|
|
18740
|
-
|
|
18741
|
-
|
|
18742
|
-
const minCellHeight = selectedLine ? containerHeight < 600 ? 80 : 100 : containerHeight < 600 ? 60 : 80;
|
|
18743
|
-
if (cellWidth < minCellWidth || cellHeight < minCellHeight) continue;
|
|
18744
|
-
const totalUsedArea = cellWidth * cellHeight * count;
|
|
18745
|
-
const totalAvailableArea = containerWidth * containerHeight;
|
|
18746
|
-
const spaceUtilization = totalUsedArea / totalAvailableArea;
|
|
18747
|
-
const actualAspectRatio = cellWidth / cellHeight;
|
|
18748
|
-
const aspectRatioScore = 1 / (1 + Math.abs(actualAspectRatio - targetAspectRatio) * 0.3);
|
|
18749
|
-
const score = spaceUtilization * 0.9 + aspectRatioScore * 0.1;
|
|
18750
|
-
if (score > bestScore) {
|
|
18751
|
-
bestScore = score;
|
|
18752
|
-
bestCols = cols;
|
|
18753
|
-
}
|
|
18754
|
-
}
|
|
18755
|
-
if (bestScore === 0) {
|
|
18756
|
-
bestCols = Math.ceil(Math.sqrt(count));
|
|
18908
|
+
if (containerAspectRatio > targetAspectRatio * 1.5 && count > 6) {
|
|
18909
|
+
bestCols = Math.min(bestCols + 1, Math.ceil(count / 2));
|
|
18910
|
+
}
|
|
18911
|
+
const minCellWidth = selectedLine ? 150 : 100;
|
|
18912
|
+
const availableWidth = containerWidth - gap * (bestCols - 1);
|
|
18913
|
+
const cellWidth = availableWidth / bestCols;
|
|
18914
|
+
if (cellWidth < minCellWidth && bestCols > 1) {
|
|
18915
|
+
bestCols = Math.floor((containerWidth + gap) / (minCellWidth + gap));
|
|
18757
18916
|
}
|
|
18917
|
+
const rows = Math.ceil(count / bestCols);
|
|
18758
18918
|
setGridCols(bestCols);
|
|
18919
|
+
setGridRows(rows);
|
|
18920
|
+
const cardWidth = (containerWidth - gap * (bestCols - 1)) / bestCols;
|
|
18921
|
+
const cardHeight = (containerHeight - gap * (rows - 1)) / rows;
|
|
18922
|
+
setCardDimensions({ width: Math.floor(cardWidth), height: Math.floor(cardHeight) });
|
|
18759
18923
|
}, [filteredWorkspaces.length, selectedLine]);
|
|
18760
18924
|
React19.useEffect(() => {
|
|
18761
18925
|
calculateOptimalGrid();
|
|
@@ -18802,17 +18966,25 @@ var VideoGridView = React19__namespace.default.memo(({
|
|
|
18802
18966
|
action_count: workspace.action_count
|
|
18803
18967
|
});
|
|
18804
18968
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
18805
|
-
const navParams = getWorkspaceNavigationParams(workspaceId, displayName);
|
|
18969
|
+
const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id);
|
|
18806
18970
|
router$1.push(`/workspace/${workspaceId}${navParams}`);
|
|
18807
18971
|
}, [router$1]);
|
|
18972
|
+
const handleStreamError = React19.useCallback((workspaceId) => {
|
|
18973
|
+
console.error(`[VideoGridView] Stream failed for workspace: ${workspaceId}`);
|
|
18974
|
+
setFailedStreams((prev) => new Set(prev).add(workspaceId));
|
|
18975
|
+
trackCoreEvent("Video Stream Error", {
|
|
18976
|
+
workspace_id: workspaceId,
|
|
18977
|
+
view_type: "video_grid"
|
|
18978
|
+
});
|
|
18979
|
+
}, []);
|
|
18808
18980
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "h-full w-full p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18809
18981
|
"div",
|
|
18810
18982
|
{
|
|
18811
18983
|
className: "grid h-full w-full gap-2",
|
|
18812
18984
|
style: {
|
|
18813
18985
|
gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
|
|
18814
|
-
gridTemplateRows: `repeat(${
|
|
18815
|
-
|
|
18986
|
+
gridTemplateRows: `repeat(${gridRows}, 1fr)`,
|
|
18987
|
+
gridAutoFlow: "row"
|
|
18816
18988
|
},
|
|
18817
18989
|
children: filteredWorkspaces.sort((a, b) => {
|
|
18818
18990
|
if (a.line_id !== b.line_id) {
|
|
@@ -18835,23 +19007,22 @@ var VideoGridView = React19__namespace.default.memo(({
|
|
|
18835
19007
|
"div",
|
|
18836
19008
|
{
|
|
18837
19009
|
"data-workspace-id": workspaceId,
|
|
18838
|
-
className: "workspace-card relative
|
|
18839
|
-
|
|
18840
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19010
|
+
className: "workspace-card relative w-full h-full",
|
|
19011
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
18841
19012
|
VideoCard,
|
|
18842
19013
|
{
|
|
18843
19014
|
workspace,
|
|
18844
19015
|
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name, workspace.line_id),
|
|
18845
|
-
shouldPlay: isVisible,
|
|
19016
|
+
shouldPlay: isVisible && !failedStreams.has(workspaceId),
|
|
18846
19017
|
onClick: () => handleWorkspaceClick(workspace),
|
|
18847
|
-
onFatalError:
|
|
19018
|
+
onFatalError: () => handleStreamError(workspaceId),
|
|
18848
19019
|
isVeryLowEfficiency,
|
|
18849
19020
|
cropping: workspaceCropping,
|
|
18850
19021
|
canvasFps: canvasConfig?.fps,
|
|
18851
19022
|
useRAF: canvasConfig?.useRAF,
|
|
18852
19023
|
compact: !selectedLine
|
|
18853
19024
|
}
|
|
18854
|
-
)
|
|
19025
|
+
) })
|
|
18855
19026
|
},
|
|
18856
19027
|
workspaceId
|
|
18857
19028
|
);
|
|
@@ -24011,7 +24182,7 @@ var WorkspaceGridItem = React19__namespace.default.memo(({
|
|
|
24011
24182
|
e.preventDefault();
|
|
24012
24183
|
if (isInactive) return;
|
|
24013
24184
|
const displayName = getWorkspaceDisplayName(data.workspace_name, data.line_id);
|
|
24014
|
-
const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName);
|
|
24185
|
+
const navParams = getWorkspaceNavigationParams(data.workspace_id, displayName, data.line_id);
|
|
24015
24186
|
navigate(`/workspace/${data.workspace_id}${navParams}`, {
|
|
24016
24187
|
trackingEvent: {
|
|
24017
24188
|
name: "Workspace Detail Clicked",
|
|
@@ -28752,6 +28923,73 @@ function HomeView({
|
|
|
28752
28923
|
}
|
|
28753
28924
|
var AuthenticatedHomeView = withAuth(React19__namespace.default.memo(HomeView));
|
|
28754
28925
|
var HomeView_default = HomeView;
|
|
28926
|
+
function withWorkspaceDisplayNames(Component3, options = {}) {
|
|
28927
|
+
const {
|
|
28928
|
+
showLoading = true,
|
|
28929
|
+
loadingMessage = "Initializing workspace data...",
|
|
28930
|
+
initializeFor = "all"
|
|
28931
|
+
} = options;
|
|
28932
|
+
return function WithWorkspaceDisplayNamesWrapper(props) {
|
|
28933
|
+
const [isInitialized2, setIsInitialized] = React19.useState(false);
|
|
28934
|
+
const [error, setError] = React19.useState(null);
|
|
28935
|
+
React19.useEffect(() => {
|
|
28936
|
+
setIsInitialized(false);
|
|
28937
|
+
setError(null);
|
|
28938
|
+
const initializeDisplayNames = async () => {
|
|
28939
|
+
try {
|
|
28940
|
+
const { lineIds, selectedLineId, factoryViewId } = props;
|
|
28941
|
+
let lineIdArray = [];
|
|
28942
|
+
if (Array.isArray(lineIds)) {
|
|
28943
|
+
lineIdArray = lineIds;
|
|
28944
|
+
} else if (lineIds && typeof lineIds === "object") {
|
|
28945
|
+
lineIdArray = Object.values(lineIds).filter((id3) => !!id3);
|
|
28946
|
+
}
|
|
28947
|
+
if (initializeFor === "specific" && selectedLineId) {
|
|
28948
|
+
if (selectedLineId === factoryViewId && lineIdArray.length > 0) {
|
|
28949
|
+
await Promise.all(
|
|
28950
|
+
lineIdArray.map((lineId) => preInitializeWorkspaceDisplayNames(lineId))
|
|
28951
|
+
);
|
|
28952
|
+
} else {
|
|
28953
|
+
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
28954
|
+
}
|
|
28955
|
+
} else if (lineIdArray.length > 0) {
|
|
28956
|
+
await Promise.all(
|
|
28957
|
+
lineIdArray.map((lineId) => preInitializeWorkspaceDisplayNames(lineId))
|
|
28958
|
+
);
|
|
28959
|
+
} else {
|
|
28960
|
+
await preInitializeWorkspaceDisplayNames();
|
|
28961
|
+
}
|
|
28962
|
+
setIsInitialized(true);
|
|
28963
|
+
} catch (err) {
|
|
28964
|
+
console.error("Failed to initialize workspace display names:", err);
|
|
28965
|
+
setError(err);
|
|
28966
|
+
setIsInitialized(true);
|
|
28967
|
+
}
|
|
28968
|
+
};
|
|
28969
|
+
initializeDisplayNames();
|
|
28970
|
+
}, [
|
|
28971
|
+
Array.isArray(props.lineIds) ? props.lineIds.join(",") : JSON.stringify(props.lineIds),
|
|
28972
|
+
props.selectedLineId,
|
|
28973
|
+
props.factoryViewId,
|
|
28974
|
+
initializeFor
|
|
28975
|
+
]);
|
|
28976
|
+
if (!isInitialized2 && showLoading) {
|
|
28977
|
+
return /* @__PURE__ */ jsxRuntime.jsx(LoadingPage, { message: loadingMessage });
|
|
28978
|
+
}
|
|
28979
|
+
if (error && showLoading) {
|
|
28980
|
+
console.warn("Workspace display names initialization failed, proceeding anyway:", error);
|
|
28981
|
+
}
|
|
28982
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Component3, { ...props });
|
|
28983
|
+
};
|
|
28984
|
+
}
|
|
28985
|
+
var withAllWorkspaceDisplayNames = (Component3) => withWorkspaceDisplayNames(Component3, {
|
|
28986
|
+
initializeFor: "all",
|
|
28987
|
+
showLoading: true
|
|
28988
|
+
});
|
|
28989
|
+
var withSelectedLineDisplayNames = (Component3) => withWorkspaceDisplayNames(Component3, {
|
|
28990
|
+
initializeFor: "specific",
|
|
28991
|
+
showLoading: true
|
|
28992
|
+
});
|
|
28755
28993
|
|
|
28756
28994
|
// src/views/kpi-detail-view.types.ts
|
|
28757
28995
|
var pageVariants = {
|
|
@@ -28812,11 +29050,6 @@ var itemVariants = {
|
|
|
28812
29050
|
}
|
|
28813
29051
|
}
|
|
28814
29052
|
};
|
|
28815
|
-
|
|
28816
|
-
// src/lib/utils/navigation.ts
|
|
28817
|
-
function getWorkspaceNavigationParams2(workspaceUuid, displayName) {
|
|
28818
|
-
return `?name=${encodeURIComponent(displayName || "")}`;
|
|
28819
|
-
}
|
|
28820
29053
|
var formatLocalDate = (date) => {
|
|
28821
29054
|
const options = {
|
|
28822
29055
|
year: "numeric",
|
|
@@ -28932,7 +29165,7 @@ var BottomSection = React19.memo(({
|
|
|
28932
29165
|
}
|
|
28933
29166
|
const clickHandler = () => handleWorkspaceClick(ws, index);
|
|
28934
29167
|
const displayName = getWorkspaceDisplayName(ws.workspace_name, lineId);
|
|
28935
|
-
const navParams = wsUuid ?
|
|
29168
|
+
const navParams = wsUuid ? getWorkspaceNavigationParams(wsUuid, displayName, lineId) : "";
|
|
28936
29169
|
const dateShiftParams = urlDate ? `&date=${urlDate}&shift=${urlShift || "0"}` : "";
|
|
28937
29170
|
const returnToParam = `&returnTo=${encodeURIComponent(`/kpis/${lineInfo?.line_id}`)}`;
|
|
28938
29171
|
const fullUrl = `/workspace/${wsUuid}${navParams}${dateShiftParams}${returnToParam}`;
|
|
@@ -28966,7 +29199,7 @@ var BottomSection = React19.memo(({
|
|
|
28966
29199
|
sortedByEfficiency.map((ws, index) => {
|
|
28967
29200
|
const clickHandler = () => handleWorkspaceClick(ws, index);
|
|
28968
29201
|
const displayName = getWorkspaceDisplayName(ws.workspace_name, lineId);
|
|
28969
|
-
const navParams = ws.workspace_uuid ?
|
|
29202
|
+
const navParams = ws.workspace_uuid ? getWorkspaceNavigationParams(ws.workspace_uuid, displayName, lineId) : "";
|
|
28970
29203
|
const dateShiftParams = urlDate ? `&date=${urlDate}&shift=${urlShift || "0"}` : "";
|
|
28971
29204
|
const returnToParam = `&returnTo=${encodeURIComponent(`/kpis/${lineInfo?.line_id}`)}`;
|
|
28972
29205
|
const fullUrl = `/workspace/${ws.workspace_uuid}${navParams}${dateShiftParams}${returnToParam}`;
|
|
@@ -29581,7 +29814,8 @@ var KPIDetailView = ({
|
|
|
29581
29814
|
) }) })
|
|
29582
29815
|
] });
|
|
29583
29816
|
};
|
|
29584
|
-
var
|
|
29817
|
+
var KPIDetailViewWithDisplayNames = withSelectedLineDisplayNames(KPIDetailView);
|
|
29818
|
+
var KPIDetailView_default = KPIDetailViewWithDisplayNames;
|
|
29585
29819
|
var LineCard = ({ line, onClick }) => {
|
|
29586
29820
|
const { kpis, isLoading, error } = useLineKPIs({ lineId: line.id });
|
|
29587
29821
|
const isOnTrack = React19__namespace.default.useMemo(() => {
|
|
@@ -30071,7 +30305,7 @@ var LeaderboardDetailView = React19.memo(({
|
|
|
30071
30305
|
action_threshold: workspace.action_threshold
|
|
30072
30306
|
});
|
|
30073
30307
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
30074
|
-
const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName) : "";
|
|
30308
|
+
const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName, workspace.line_id) : "";
|
|
30075
30309
|
const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
|
|
30076
30310
|
if (onWorkspaceClick) {
|
|
30077
30311
|
onWorkspaceClick(workspace, rank);
|
|
@@ -30205,7 +30439,8 @@ var LeaderboardDetailView = React19.memo(({
|
|
|
30205
30439
|
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className && prevProps.onBackClick === nextProps.onBackClick && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick;
|
|
30206
30440
|
});
|
|
30207
30441
|
LeaderboardDetailView.displayName = "LeaderboardDetailView";
|
|
30208
|
-
var
|
|
30442
|
+
var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
|
|
30443
|
+
var LeaderboardDetailView_default = LeaderboardDetailViewWithDisplayNames;
|
|
30209
30444
|
function LoginView({
|
|
30210
30445
|
logoSrc = "/optifye-logo.png",
|
|
30211
30446
|
logoAlt = "Optifye",
|
|
@@ -32325,7 +32560,12 @@ var TargetsView = ({
|
|
|
32325
32560
|
}
|
|
32326
32561
|
}), {});
|
|
32327
32562
|
}, [lineIds]);
|
|
32328
|
-
const [
|
|
32563
|
+
const [allShiftsData, setAllShiftsData] = React19.useState({
|
|
32564
|
+
0: initialLineWorkspaces,
|
|
32565
|
+
// Day shift
|
|
32566
|
+
1: initialLineWorkspaces
|
|
32567
|
+
// Night shift (will be populated on first load)
|
|
32568
|
+
});
|
|
32329
32569
|
const [actionIds, setActionIds] = React19.useState(null);
|
|
32330
32570
|
const [savingLines, setSavingLines] = React19.useState(
|
|
32331
32571
|
() => lineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
|
|
@@ -32337,6 +32577,13 @@ var TargetsView = ({
|
|
|
32337
32577
|
const [isBulkConfigureOpen, setIsBulkConfigureOpen] = React19.useState(false);
|
|
32338
32578
|
const [selectedWorkspaces, setSelectedWorkspaces] = React19.useState([]);
|
|
32339
32579
|
const [selectedShift, setSelectedShift] = React19.useState(0);
|
|
32580
|
+
const lineWorkspaces = allShiftsData[selectedShift] || initialLineWorkspaces;
|
|
32581
|
+
const setLineWorkspaces = React19.useCallback((updater) => {
|
|
32582
|
+
setAllShiftsData((prev) => ({
|
|
32583
|
+
...prev,
|
|
32584
|
+
[selectedShift]: typeof updater === "function" ? updater(prev[selectedShift]) : updater
|
|
32585
|
+
}));
|
|
32586
|
+
}, [selectedShift]);
|
|
32340
32587
|
const supabase = useSupabase();
|
|
32341
32588
|
const auth = useAuth();
|
|
32342
32589
|
userId || auth?.user?.id;
|
|
@@ -32407,7 +32654,7 @@ var TargetsView = ({
|
|
|
32407
32654
|
};
|
|
32408
32655
|
fetchActions();
|
|
32409
32656
|
}, [supabase, companyId]);
|
|
32410
|
-
|
|
32657
|
+
React19.useCallback(async (shiftId) => {
|
|
32411
32658
|
try {
|
|
32412
32659
|
if (!supabase) return;
|
|
32413
32660
|
const currentDate = getOperationalDate();
|
|
@@ -32475,15 +32722,7 @@ var TargetsView = ({
|
|
|
32475
32722
|
shiftEndTime: endTime,
|
|
32476
32723
|
breaks,
|
|
32477
32724
|
shiftHours: Number(shiftHours),
|
|
32478
|
-
workspaces:
|
|
32479
|
-
...ws,
|
|
32480
|
-
targetPPH: ws.targetCycleTime !== "" ? calculatePPH(ws.targetCycleTime, breaks, Number(shiftHours)) : ws.targetPPH,
|
|
32481
|
-
targetDayOutput: calculateDayOutput(
|
|
32482
|
-
ws.targetCycleTime !== "" ? calculatePPH(ws.targetCycleTime, breaks, Number(shiftHours)) : ws.targetPPH,
|
|
32483
|
-
Number(shiftHours),
|
|
32484
|
-
breaks
|
|
32485
|
-
)
|
|
32486
|
-
}))
|
|
32725
|
+
workspaces: currentLineStateFromLoop?.workspaces || []
|
|
32487
32726
|
};
|
|
32488
32727
|
hasUpdates = true;
|
|
32489
32728
|
}
|
|
@@ -32497,7 +32736,71 @@ var TargetsView = ({
|
|
|
32497
32736
|
} catch (error) {
|
|
32498
32737
|
console.error("Error in fetchLineThresholds outer try-catch:", error);
|
|
32499
32738
|
}
|
|
32500
|
-
}, [selectedShift, supabase, lineIds, lineWorkspaces]);
|
|
32739
|
+
}, [selectedShift, supabase, lineIds, lineWorkspaces, allShiftsData]);
|
|
32740
|
+
const fetchAllShiftsData = React19.useCallback(async (currentWorkspaces) => {
|
|
32741
|
+
if (!supabase) return;
|
|
32742
|
+
const currentDate = getOperationalDate();
|
|
32743
|
+
const newAllShiftsData = {
|
|
32744
|
+
0: JSON.parse(JSON.stringify(currentWorkspaces)),
|
|
32745
|
+
// Deep clone for day shift
|
|
32746
|
+
1: JSON.parse(JSON.stringify(currentWorkspaces))
|
|
32747
|
+
// Deep clone for night shift
|
|
32748
|
+
};
|
|
32749
|
+
for (const shiftId of [0, 1]) {
|
|
32750
|
+
for (const lineId of lineIds) {
|
|
32751
|
+
try {
|
|
32752
|
+
const { data: operatingHours, error: hoursError } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", shiftId).maybeSingle();
|
|
32753
|
+
if (hoursError) {
|
|
32754
|
+
console.error(`Error fetching operating hours for line ${lineId}, shift ${shiftId}:`, hoursError);
|
|
32755
|
+
continue;
|
|
32756
|
+
}
|
|
32757
|
+
let breaks = [];
|
|
32758
|
+
if (operatingHours?.breaks) {
|
|
32759
|
+
if (Array.isArray(operatingHours.breaks)) {
|
|
32760
|
+
breaks = operatingHours.breaks.map((breakItem) => ({
|
|
32761
|
+
startTime: breakItem.start || breakItem.startTime || "00:00",
|
|
32762
|
+
endTime: breakItem.end || breakItem.endTime || "00:00",
|
|
32763
|
+
duration: breakItem.duration || calculateShiftHours2(breakItem.start || breakItem.startTime || "00:00", breakItem.end || breakItem.endTime || "00:00", []) * 60
|
|
32764
|
+
}));
|
|
32765
|
+
}
|
|
32766
|
+
}
|
|
32767
|
+
const startTime = operatingHours?.start_time || "08:00";
|
|
32768
|
+
const endTime = operatingHours?.end_time || "19:00";
|
|
32769
|
+
const shiftHours = calculateShiftHours2(startTime, endTime, breaks);
|
|
32770
|
+
const actionThresholds = await workspaceService.getActionThresholds(
|
|
32771
|
+
lineId,
|
|
32772
|
+
currentDate,
|
|
32773
|
+
shiftId
|
|
32774
|
+
);
|
|
32775
|
+
const existingLine = newAllShiftsData[shiftId][lineId];
|
|
32776
|
+
if (existingLine) {
|
|
32777
|
+
newAllShiftsData[shiftId][lineId] = {
|
|
32778
|
+
...existingLine,
|
|
32779
|
+
shiftStartTime: startTime,
|
|
32780
|
+
shiftEndTime: endTime,
|
|
32781
|
+
breaks,
|
|
32782
|
+
shiftHours: Number(shiftHours),
|
|
32783
|
+
workspaces: existingLine.workspaces.map((ws) => {
|
|
32784
|
+
const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
|
|
32785
|
+
if (threshold) {
|
|
32786
|
+
return {
|
|
32787
|
+
...ws,
|
|
32788
|
+
targetPPH: threshold.pph_threshold,
|
|
32789
|
+
targetCycleTime: threshold.ideal_cycle_time,
|
|
32790
|
+
targetDayOutput: threshold.total_day_output
|
|
32791
|
+
};
|
|
32792
|
+
}
|
|
32793
|
+
return ws;
|
|
32794
|
+
})
|
|
32795
|
+
};
|
|
32796
|
+
}
|
|
32797
|
+
} catch (error) {
|
|
32798
|
+
console.error(`Error fetching data for line ${lineId}, shift ${shiftId}:`, error);
|
|
32799
|
+
}
|
|
32800
|
+
}
|
|
32801
|
+
}
|
|
32802
|
+
setAllShiftsData(newAllShiftsData);
|
|
32803
|
+
}, [supabase, lineIds]);
|
|
32501
32804
|
const loadOperatingHours = React19.useCallback(async (lineId, shiftId) => {
|
|
32502
32805
|
try {
|
|
32503
32806
|
if (!supabase) return null;
|
|
@@ -32602,7 +32905,7 @@ var TargetsView = ({
|
|
|
32602
32905
|
(line) => line.workspaces && line.workspaces.length > 0
|
|
32603
32906
|
);
|
|
32604
32907
|
if (workspacesAlreadyLoadedForAnyLine) {
|
|
32605
|
-
|
|
32908
|
+
setIsLoading(false);
|
|
32606
32909
|
return;
|
|
32607
32910
|
}
|
|
32608
32911
|
const fetchWorkspacesAndThenThresholds = async () => {
|
|
@@ -32623,7 +32926,7 @@ var TargetsView = ({
|
|
|
32623
32926
|
}
|
|
32624
32927
|
try {
|
|
32625
32928
|
const fetchedLineWorkspacesData = await workspaceService.getWorkspaces(lineId);
|
|
32626
|
-
|
|
32929
|
+
let mappedWorkspaces = fetchedLineWorkspacesData.map((ws) => ({
|
|
32627
32930
|
id: ws.id,
|
|
32628
32931
|
name: ws.workspace_id,
|
|
32629
32932
|
targetPPH: ws.action_pph_threshold === null ? "" : ws.action_pph_threshold,
|
|
@@ -32632,6 +32935,29 @@ var TargetsView = ({
|
|
|
32632
32935
|
actionType: ws.action_id === actionIds.assembly ? "assembly" : ws.action_id === actionIds.packaging ? "packaging" : "assembly",
|
|
32633
32936
|
actionId: ws.action_id === actionIds.assembly ? actionIds.assembly : ws.action_id === actionIds.packaging ? actionIds.packaging : actionIds.assembly
|
|
32634
32937
|
})).sort((a, b) => a.name.localeCompare(b.name, void 0, { numeric: true }));
|
|
32938
|
+
const currentDate = getOperationalDate();
|
|
32939
|
+
try {
|
|
32940
|
+
const actionThresholds = await workspaceService.getActionThresholds(
|
|
32941
|
+
lineId,
|
|
32942
|
+
currentDate,
|
|
32943
|
+
selectedShift
|
|
32944
|
+
);
|
|
32945
|
+
mappedWorkspaces = mappedWorkspaces.map((ws) => {
|
|
32946
|
+
const threshold = actionThresholds.find((t) => t.workspace_id === ws.id);
|
|
32947
|
+
if (threshold) {
|
|
32948
|
+
return {
|
|
32949
|
+
...ws,
|
|
32950
|
+
targetPPH: threshold.pph_threshold,
|
|
32951
|
+
targetCycleTime: threshold.ideal_cycle_time,
|
|
32952
|
+
targetDayOutput: threshold.total_day_output
|
|
32953
|
+
};
|
|
32954
|
+
}
|
|
32955
|
+
return ws;
|
|
32956
|
+
});
|
|
32957
|
+
console.log(`Merged action thresholds for line ${lineId}, found ${actionThresholds.length} saved thresholds`);
|
|
32958
|
+
} catch (error) {
|
|
32959
|
+
console.error(`Error fetching action thresholds for line ${lineId}:`, error);
|
|
32960
|
+
}
|
|
32635
32961
|
if (JSON.stringify(mappedWorkspaces) !== JSON.stringify(newUpdatedLineWorkspaces[lineId].workspaces)) {
|
|
32636
32962
|
newUpdatedLineWorkspaces[lineId] = {
|
|
32637
32963
|
...newUpdatedLineWorkspaces[lineId],
|
|
@@ -32646,7 +32972,7 @@ var TargetsView = ({
|
|
|
32646
32972
|
if (workspacesHaveBeenUpdated) {
|
|
32647
32973
|
setLineWorkspaces(newUpdatedLineWorkspaces);
|
|
32648
32974
|
}
|
|
32649
|
-
await
|
|
32975
|
+
await fetchAllShiftsData(newUpdatedLineWorkspaces);
|
|
32650
32976
|
} catch (error) {
|
|
32651
32977
|
console.error("Error in fetchWorkspacesAndThenThresholds:", error);
|
|
32652
32978
|
sonner.toast.error("Failed to load workspace data");
|
|
@@ -32655,37 +32981,7 @@ var TargetsView = ({
|
|
|
32655
32981
|
}
|
|
32656
32982
|
};
|
|
32657
32983
|
fetchWorkspacesAndThenThresholds();
|
|
32658
|
-
}, [actionIds, supabase, lineIds
|
|
32659
|
-
React19.useEffect(() => {
|
|
32660
|
-
if (Object.keys(lineWorkspaces).length > 0) {
|
|
32661
|
-
const updatedLineWorkspaces = { ...lineWorkspaces };
|
|
32662
|
-
let hasChanges = false;
|
|
32663
|
-
Object.keys(updatedLineWorkspaces).forEach((lineId) => {
|
|
32664
|
-
const line = updatedLineWorkspaces[lineId];
|
|
32665
|
-
const shiftHours = calculateShiftHours2(line.shiftStartTime, line.shiftEndTime, line.breaks);
|
|
32666
|
-
if (shiftHours !== line.shiftHours) {
|
|
32667
|
-
hasChanges = true;
|
|
32668
|
-
updatedLineWorkspaces[lineId] = {
|
|
32669
|
-
...line,
|
|
32670
|
-
shiftHours,
|
|
32671
|
-
workspaces: line.workspaces.map((ws) => {
|
|
32672
|
-
const targetDayOutput = calculateDayOutput(ws.targetPPH, shiftHours, line.breaks);
|
|
32673
|
-
if (targetDayOutput !== ws.targetDayOutput) {
|
|
32674
|
-
return {
|
|
32675
|
-
...ws,
|
|
32676
|
-
targetDayOutput
|
|
32677
|
-
};
|
|
32678
|
-
}
|
|
32679
|
-
return ws;
|
|
32680
|
-
})
|
|
32681
|
-
};
|
|
32682
|
-
}
|
|
32683
|
-
});
|
|
32684
|
-
if (hasChanges) {
|
|
32685
|
-
setLineWorkspaces(updatedLineWorkspaces);
|
|
32686
|
-
}
|
|
32687
|
-
}
|
|
32688
|
-
}, [selectedShift]);
|
|
32984
|
+
}, [actionIds, supabase, lineIds]);
|
|
32689
32985
|
const toggleLineDropdown = React19.useCallback((lineId) => {
|
|
32690
32986
|
setLineWorkspaces((prev) => {
|
|
32691
32987
|
const newIsOpen = !prev[lineId].isOpen;
|
|
@@ -32769,6 +33065,16 @@ var TargetsView = ({
|
|
|
32769
33065
|
updates.targetDayOutput = calculateDayOutput(value, shiftHours, prev[lineId].breaks);
|
|
32770
33066
|
} else if (field === "targetDayOutput") {
|
|
32771
33067
|
updates.targetDayOutput = value;
|
|
33068
|
+
if (value !== "") {
|
|
33069
|
+
const breaks = prev[lineId].breaks;
|
|
33070
|
+
const totalBreakMinutes = breaks.reduce((total, b) => total + b.duration, 0);
|
|
33071
|
+
const totalBreakHours = totalBreakMinutes / 60;
|
|
33072
|
+
const realWorkHours = shiftHours - totalBreakHours;
|
|
33073
|
+
const calculatedPPH = Math.round(value / realWorkHours);
|
|
33074
|
+
updates.targetPPH = calculatedPPH;
|
|
33075
|
+
} else {
|
|
33076
|
+
updates.targetPPH = "";
|
|
33077
|
+
}
|
|
32772
33078
|
}
|
|
32773
33079
|
updates[field] = value;
|
|
32774
33080
|
return updates;
|
|
@@ -33030,8 +33336,9 @@ var TargetsView = ({
|
|
|
33030
33336
|
}
|
|
33031
33337
|
);
|
|
33032
33338
|
};
|
|
33033
|
-
var
|
|
33034
|
-
var
|
|
33339
|
+
var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
|
|
33340
|
+
var TargetsView_default = TargetsViewWithDisplayNames;
|
|
33341
|
+
var AuthenticatedTargetsView = withAuth(TargetsViewWithDisplayNames);
|
|
33035
33342
|
|
|
33036
33343
|
// src/views/workspace-detail-view.utils.ts
|
|
33037
33344
|
var formatISTDate2 = (date = /* @__PURE__ */ new Date(), options) => {
|
|
@@ -33047,8 +33354,8 @@ var formatISTDate2 = (date = /* @__PURE__ */ new Date(), options) => {
|
|
|
33047
33354
|
});
|
|
33048
33355
|
return formatter.format(date);
|
|
33049
33356
|
};
|
|
33050
|
-
var formatWorkspaceName3 = (name) => {
|
|
33051
|
-
return getWorkspaceDisplayName(name);
|
|
33357
|
+
var formatWorkspaceName3 = (name, lineId) => {
|
|
33358
|
+
return getWorkspaceDisplayName(name, lineId);
|
|
33052
33359
|
};
|
|
33053
33360
|
var getDaysDifference = (date) => {
|
|
33054
33361
|
const today = /* @__PURE__ */ new Date();
|
|
@@ -33085,9 +33392,11 @@ var WorkspaceDetailView = ({
|
|
|
33085
33392
|
fromMonthly = false,
|
|
33086
33393
|
sourceType,
|
|
33087
33394
|
displayName,
|
|
33395
|
+
lineId,
|
|
33088
33396
|
defaultTab,
|
|
33089
33397
|
returnUrl,
|
|
33090
33398
|
lineIds = { line1: "", line2: "" },
|
|
33399
|
+
selectedLineId,
|
|
33091
33400
|
onNavigate,
|
|
33092
33401
|
onTabChange,
|
|
33093
33402
|
onDateSelect,
|
|
@@ -33250,7 +33559,8 @@ var WorkspaceDetailView = ({
|
|
|
33250
33559
|
setSelectedMonth(newMonth);
|
|
33251
33560
|
setSelectedYear(newYear);
|
|
33252
33561
|
};
|
|
33253
|
-
const
|
|
33562
|
+
const effectiveLineId = lineId || selectedLineId;
|
|
33563
|
+
const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
|
|
33254
33564
|
const shouldShowCycleTimeChart = showCycleTimeChart ?? formattedWorkspaceName.startsWith("FINAL ASSY");
|
|
33255
33565
|
const handleBackNavigation = () => {
|
|
33256
33566
|
if (returnUrl) {
|
|
@@ -33262,13 +33572,23 @@ var WorkspaceDetailView = ({
|
|
|
33262
33572
|
if (date || shift) {
|
|
33263
33573
|
setActiveTab("monthly_history");
|
|
33264
33574
|
if (onNavigate) {
|
|
33265
|
-
|
|
33575
|
+
const params = new URLSearchParams();
|
|
33576
|
+
params.set("fromMonthly", "true");
|
|
33577
|
+
if (effectiveLineId) {
|
|
33578
|
+
params.set("lineId", effectiveLineId);
|
|
33579
|
+
}
|
|
33580
|
+
onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
|
|
33266
33581
|
}
|
|
33267
33582
|
} else {
|
|
33268
33583
|
if (previousView === "line_monthly_history") {
|
|
33269
33584
|
setActiveTab("monthly_history");
|
|
33270
33585
|
if (onNavigate) {
|
|
33271
|
-
|
|
33586
|
+
const params = new URLSearchParams();
|
|
33587
|
+
params.set("fromMonthly", "true");
|
|
33588
|
+
if (effectiveLineId) {
|
|
33589
|
+
params.set("lineId", effectiveLineId);
|
|
33590
|
+
}
|
|
33591
|
+
onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
|
|
33272
33592
|
}
|
|
33273
33593
|
} else {
|
|
33274
33594
|
if (onNavigate) {
|
|
@@ -33726,7 +34046,13 @@ var WorkspaceDetailView = ({
|
|
|
33726
34046
|
if (onDateSelect) {
|
|
33727
34047
|
onDateSelect(selectedDate, selectedShift);
|
|
33728
34048
|
} else if (onNavigate) {
|
|
33729
|
-
|
|
34049
|
+
const params = new URLSearchParams();
|
|
34050
|
+
params.set("date", selectedDate);
|
|
34051
|
+
params.set("shift", selectedShift === "day" ? "0" : "1");
|
|
34052
|
+
if (effectiveLineId) {
|
|
34053
|
+
params.set("lineId", effectiveLineId);
|
|
34054
|
+
}
|
|
34055
|
+
onNavigate(`/workspace/${workspaceId}?${params.toString()}`);
|
|
33730
34056
|
}
|
|
33731
34057
|
},
|
|
33732
34058
|
onMonthNavigate: (newMonth, newYear) => {
|
|
@@ -33753,7 +34079,12 @@ var WorkspaceDetailView = ({
|
|
|
33753
34079
|
}
|
|
33754
34080
|
);
|
|
33755
34081
|
};
|
|
33756
|
-
var
|
|
34082
|
+
var WorkspaceDetailViewWithDisplayNames = withSelectedLineDisplayNames(WorkspaceDetailView);
|
|
34083
|
+
var WorkspaceDetailViewFinal = (props) => {
|
|
34084
|
+
const componentKey = `${props.date || "live"}_${props.shift || "current"}`;
|
|
34085
|
+
return /* @__PURE__ */ jsxRuntime.jsx(WorkspaceDetailViewWithDisplayNames, { ...props }, componentKey);
|
|
34086
|
+
};
|
|
34087
|
+
var WrappedComponent = withAuth(WorkspaceDetailViewFinal);
|
|
33757
34088
|
var WorkspaceDetailView_default = WrappedComponent;
|
|
33758
34089
|
var SKUManagementView = () => {
|
|
33759
34090
|
const config = useDashboardConfig();
|
|
@@ -34327,6 +34658,7 @@ exports.identifyCoreUser = identifyCoreUser;
|
|
|
34327
34658
|
exports.initializeCoreMixpanel = initializeCoreMixpanel;
|
|
34328
34659
|
exports.isLegacyConfiguration = isLegacyConfiguration;
|
|
34329
34660
|
exports.isTransitionPeriod = isTransitionPeriod;
|
|
34661
|
+
exports.isUrlPermanentlyFailed = isUrlPermanentlyFailed;
|
|
34330
34662
|
exports.isValidFactoryViewConfiguration = isValidFactoryViewConfiguration;
|
|
34331
34663
|
exports.isValidLineInfoPayload = isValidLineInfoPayload;
|
|
34332
34664
|
exports.isValidWorkspaceDetailedMetricsPayload = isValidWorkspaceDetailedMetricsPayload;
|
|
@@ -34346,6 +34678,7 @@ exports.qualityService = qualityService;
|
|
|
34346
34678
|
exports.realtimeService = realtimeService;
|
|
34347
34679
|
exports.refreshWorkspaceDisplayNames = refreshWorkspaceDisplayNames;
|
|
34348
34680
|
exports.resetCoreMixpanel = resetCoreMixpanel;
|
|
34681
|
+
exports.resetFailedUrl = resetFailedUrl;
|
|
34349
34682
|
exports.resetSubscriptionManager = resetSubscriptionManager;
|
|
34350
34683
|
exports.s3VideoPreloader = s3VideoPreloader;
|
|
34351
34684
|
exports.skuService = skuService;
|