@optifye/dashboard-core 6.9.9 → 6.9.11
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.css +0 -4
- package/dist/index.js +253 -107
- package/dist/index.mjs +253 -107
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -5607,10 +5607,6 @@ input[type=range]:active::-moz-range-thumb {
|
|
|
5607
5607
|
font-size: 1.875rem;
|
|
5608
5608
|
line-height: 2.25rem;
|
|
5609
5609
|
}
|
|
5610
|
-
.lg\:text-4xl {
|
|
5611
|
-
font-size: 2.25rem;
|
|
5612
|
-
line-height: 2.5rem;
|
|
5613
|
-
}
|
|
5614
5610
|
.lg\:text-7xl {
|
|
5615
5611
|
font-size: 4.5rem;
|
|
5616
5612
|
line-height: 1;
|
package/dist/index.js
CHANGED
|
@@ -23099,7 +23099,7 @@ var OutputProgressChartComponent = ({
|
|
|
23099
23099
|
];
|
|
23100
23100
|
const COLORS = ["#00AB45", "#f3f4f6"];
|
|
23101
23101
|
const percentage = (currentOutput / targetOutput * 100).toFixed(1);
|
|
23102
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full aspect-square max-h-full", style: { maxWidth: "min(100%, 280px)" }, children: [
|
|
23102
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full aspect-square max-h-full", style: { maxWidth: "min(100%, 280px)", containerType: "inline-size" }, children: [
|
|
23103
23103
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.PieChart, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23104
23104
|
recharts.Pie,
|
|
23105
23105
|
{
|
|
@@ -23123,16 +23123,33 @@ var OutputProgressChartComponent = ({
|
|
|
23123
23123
|
))
|
|
23124
23124
|
}
|
|
23125
23125
|
) }) }),
|
|
23126
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
23127
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
23128
|
-
|
|
23129
|
-
|
|
23130
|
-
|
|
23131
|
-
|
|
23132
|
-
|
|
23133
|
-
|
|
23134
|
-
|
|
23135
|
-
|
|
23126
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", style: { width: "100%", padding: "0 10%" }, children: [
|
|
23127
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
23128
|
+
"div",
|
|
23129
|
+
{
|
|
23130
|
+
className: "font-bold text-gray-800",
|
|
23131
|
+
style: { fontSize: "clamp(1.25rem, 8cqw, 2.5rem)" },
|
|
23132
|
+
children: [
|
|
23133
|
+
percentage,
|
|
23134
|
+
"%"
|
|
23135
|
+
]
|
|
23136
|
+
}
|
|
23137
|
+
),
|
|
23138
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
23139
|
+
"div",
|
|
23140
|
+
{
|
|
23141
|
+
className: "text-gray-500",
|
|
23142
|
+
style: {
|
|
23143
|
+
fontSize: "clamp(0.7rem, 3.5cqw, 1rem)",
|
|
23144
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.5rem)"
|
|
23145
|
+
},
|
|
23146
|
+
children: [
|
|
23147
|
+
currentOutput,
|
|
23148
|
+
" / ",
|
|
23149
|
+
Math.round(targetOutput)
|
|
23150
|
+
]
|
|
23151
|
+
}
|
|
23152
|
+
)
|
|
23136
23153
|
] }) })
|
|
23137
23154
|
] }) });
|
|
23138
23155
|
};
|
|
@@ -23150,7 +23167,7 @@ var LargeOutputProgressChart = ({
|
|
|
23150
23167
|
];
|
|
23151
23168
|
const COLORS = ["#00AB45", "#f3f4f6"];
|
|
23152
23169
|
const percentage = (currentOutput / targetOutput * 100).toFixed(1);
|
|
23153
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full", style: { minHeight: "100px", minWidth: "100px" }, children: [
|
|
23170
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full", style: { minHeight: "100px", minWidth: "100px", containerType: "inline-size" }, children: [
|
|
23154
23171
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.PieChart, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23155
23172
|
recharts.Pie,
|
|
23156
23173
|
{
|
|
@@ -23174,16 +23191,40 @@ var LargeOutputProgressChart = ({
|
|
|
23174
23191
|
))
|
|
23175
23192
|
}
|
|
23176
23193
|
) }) }),
|
|
23177
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
23178
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23179
|
-
|
|
23180
|
-
|
|
23181
|
-
|
|
23182
|
-
|
|
23183
|
-
|
|
23184
|
-
|
|
23185
|
-
|
|
23186
|
-
|
|
23194
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", style: { width: "100%", padding: "0 10%" }, children: [
|
|
23195
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23196
|
+
"div",
|
|
23197
|
+
{
|
|
23198
|
+
className: "font-bold text-gray-900",
|
|
23199
|
+
style: { fontSize: "clamp(1.5rem, 10cqw, 3rem)" },
|
|
23200
|
+
children: currentOutput
|
|
23201
|
+
}
|
|
23202
|
+
),
|
|
23203
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
23204
|
+
"div",
|
|
23205
|
+
{
|
|
23206
|
+
className: "text-gray-500",
|
|
23207
|
+
style: { fontSize: "clamp(0.75rem, 3.5cqw, 1rem)" },
|
|
23208
|
+
children: [
|
|
23209
|
+
"of ",
|
|
23210
|
+
targetOutput
|
|
23211
|
+
]
|
|
23212
|
+
}
|
|
23213
|
+
),
|
|
23214
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
23215
|
+
"div",
|
|
23216
|
+
{
|
|
23217
|
+
className: "font-medium text-gray-600",
|
|
23218
|
+
style: {
|
|
23219
|
+
fontSize: "clamp(0.875rem, 4.5cqw, 1.25rem)",
|
|
23220
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.5rem)"
|
|
23221
|
+
},
|
|
23222
|
+
children: [
|
|
23223
|
+
percentage,
|
|
23224
|
+
"%"
|
|
23225
|
+
]
|
|
23226
|
+
}
|
|
23227
|
+
)
|
|
23187
23228
|
] }) })
|
|
23188
23229
|
] }) });
|
|
23189
23230
|
};
|
|
@@ -25277,7 +25318,7 @@ var GaugeChart = ({
|
|
|
25277
25318
|
};
|
|
25278
25319
|
const gaugeColor = getColor();
|
|
25279
25320
|
const targetAngle = target !== void 0 ? 180 - (target - min) / (max - min) * 180 : null;
|
|
25280
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative w-full h-full flex flex-col items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full max-w-[280px] aspect-square", style: { minHeight: "100px", minWidth: "100px" }, children: [
|
|
25321
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative w-full h-full flex flex-col items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full max-w-[280px] aspect-square", style: { minHeight: "100px", minWidth: "100px", containerType: "inline-size" }, children: [
|
|
25281
25322
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.PieChart, { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
25282
25323
|
recharts.Pie,
|
|
25283
25324
|
{
|
|
@@ -25310,17 +25351,44 @@ var GaugeChart = ({
|
|
|
25310
25351
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-1 -left-1.5 w-3 h-3 bg-gray-800 rounded-full" })
|
|
25311
25352
|
}
|
|
25312
25353
|
),
|
|
25313
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
25314
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
25315
|
-
|
|
25316
|
-
|
|
25317
|
-
|
|
25318
|
-
|
|
25319
|
-
|
|
25320
|
-
|
|
25321
|
-
|
|
25322
|
-
|
|
25323
|
-
|
|
25354
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", style: { width: "100%", padding: "0 10%" }, children: [
|
|
25355
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
25356
|
+
"div",
|
|
25357
|
+
{
|
|
25358
|
+
className: "font-bold text-gray-800",
|
|
25359
|
+
style: { fontSize: "clamp(1.25rem, 8cqw, 2rem)" },
|
|
25360
|
+
children: [
|
|
25361
|
+
value.toFixed(unit === "%" ? 1 : 0),
|
|
25362
|
+
unit
|
|
25363
|
+
]
|
|
25364
|
+
}
|
|
25365
|
+
),
|
|
25366
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25367
|
+
"div",
|
|
25368
|
+
{
|
|
25369
|
+
className: "text-gray-600 font-medium",
|
|
25370
|
+
style: {
|
|
25371
|
+
fontSize: "clamp(0.75rem, 3.5cqw, 1rem)",
|
|
25372
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.25rem)"
|
|
25373
|
+
},
|
|
25374
|
+
children: label
|
|
25375
|
+
}
|
|
25376
|
+
),
|
|
25377
|
+
target !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
25378
|
+
"div",
|
|
25379
|
+
{
|
|
25380
|
+
className: "text-gray-500",
|
|
25381
|
+
style: {
|
|
25382
|
+
fontSize: "clamp(0.7rem, 3cqw, 0.875rem)",
|
|
25383
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.25rem)"
|
|
25384
|
+
},
|
|
25385
|
+
children: [
|
|
25386
|
+
"Target: ",
|
|
25387
|
+
target,
|
|
25388
|
+
unit
|
|
25389
|
+
]
|
|
25390
|
+
}
|
|
25391
|
+
)
|
|
25324
25392
|
] }) }),
|
|
25325
25393
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-[15%] left-[15%] text-xs text-gray-500", children: [
|
|
25326
25394
|
min,
|
|
@@ -29214,6 +29282,31 @@ var BottlenecksContent = ({
|
|
|
29214
29282
|
const [categoryMetadata, setCategoryMetadata] = React23.useState([]);
|
|
29215
29283
|
const [currentMetadataIndex, setCurrentMetadataIndex] = React23.useState(0);
|
|
29216
29284
|
const [metadataCache, setMetadataCache] = React23.useState({});
|
|
29285
|
+
const invalidateMetadataCache = React23.useCallback((categories) => {
|
|
29286
|
+
setMetadataCache((prevCache) => {
|
|
29287
|
+
if (!prevCache || Object.keys(prevCache).length === 0) {
|
|
29288
|
+
return prevCache;
|
|
29289
|
+
}
|
|
29290
|
+
const targetCategories = categories ? (Array.isArray(categories) ? categories : [categories]).filter(Boolean) : null;
|
|
29291
|
+
let updatedCache = null;
|
|
29292
|
+
const shouldInvalidate = (key) => {
|
|
29293
|
+
if (!targetCategories || targetCategories.length === 0) {
|
|
29294
|
+
return true;
|
|
29295
|
+
}
|
|
29296
|
+
const [categoryId] = key.split("-");
|
|
29297
|
+
return targetCategories.includes(categoryId);
|
|
29298
|
+
};
|
|
29299
|
+
Object.keys(prevCache).forEach((cacheKey) => {
|
|
29300
|
+
if (shouldInvalidate(cacheKey)) {
|
|
29301
|
+
if (!updatedCache) {
|
|
29302
|
+
updatedCache = { ...prevCache };
|
|
29303
|
+
}
|
|
29304
|
+
delete updatedCache[cacheKey];
|
|
29305
|
+
}
|
|
29306
|
+
});
|
|
29307
|
+
return updatedCache || prevCache;
|
|
29308
|
+
});
|
|
29309
|
+
}, []);
|
|
29217
29310
|
const [triageClips, setTriageClips] = React23.useState([]);
|
|
29218
29311
|
const [isLoadingTriageClips, setIsLoadingTriageClips] = React23.useState(false);
|
|
29219
29312
|
const [isFullscreen, setIsFullscreen] = React23.useState(false);
|
|
@@ -29233,6 +29326,12 @@ var BottlenecksContent = ({
|
|
|
29233
29326
|
onNewClips: (notification) => {
|
|
29234
29327
|
console.log(`[BottlenecksContent] New clips detected:`, notification);
|
|
29235
29328
|
if (notification.clips.length > 0) {
|
|
29329
|
+
const categoryIds = notification.clips.map((clip) => clip.clip_type).filter(Boolean).map((value) => String(value));
|
|
29330
|
+
if (categoryIds.length > 0) {
|
|
29331
|
+
invalidateMetadataCache(categoryIds);
|
|
29332
|
+
} else {
|
|
29333
|
+
invalidateMetadataCache();
|
|
29334
|
+
}
|
|
29236
29335
|
fetchClipCounts();
|
|
29237
29336
|
}
|
|
29238
29337
|
}
|
|
@@ -29279,24 +29378,37 @@ var BottlenecksContent = ({
|
|
|
29279
29378
|
shift: shift || "0"
|
|
29280
29379
|
});
|
|
29281
29380
|
React23.useEffect(() => {
|
|
29282
|
-
if (clipTypes.length > 0
|
|
29283
|
-
const
|
|
29284
|
-
|
|
29285
|
-
|
|
29286
|
-
|
|
29287
|
-
|
|
29288
|
-
|
|
29289
|
-
|
|
29381
|
+
if (clipTypes.length > 0) {
|
|
29382
|
+
const currentFilterCount = initialFilter ? dynamicCounts[initialFilter] || 0 : 0;
|
|
29383
|
+
const hasAnyCounts = Object.values(dynamicCounts).some((c) => c > 0);
|
|
29384
|
+
const userHasNotNavigated = !initialFilter || activeFilterRef.current === initialFilter;
|
|
29385
|
+
const shouldRunSelection = !initialFilter || userHasNotNavigated && currentFilterCount === 0 && hasAnyCounts;
|
|
29386
|
+
if (shouldRunSelection) {
|
|
29387
|
+
let selectedType = null;
|
|
29388
|
+
if (clipTypes.length === 1) {
|
|
29389
|
+
selectedType = clipTypes[0];
|
|
29390
|
+
} else {
|
|
29391
|
+
const priorityOrder = ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
29392
|
+
for (const priorityType of priorityOrder) {
|
|
29393
|
+
const type = clipTypes.find((t) => t.type === priorityType && (dynamicCounts[t.type] || 0) > 0);
|
|
29394
|
+
if (type) {
|
|
29395
|
+
selectedType = type;
|
|
29396
|
+
break;
|
|
29397
|
+
}
|
|
29398
|
+
}
|
|
29399
|
+
if (!selectedType) {
|
|
29400
|
+
selectedType = clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0);
|
|
29401
|
+
}
|
|
29402
|
+
if (!selectedType) {
|
|
29403
|
+
selectedType = clipTypes[0];
|
|
29404
|
+
}
|
|
29405
|
+
}
|
|
29406
|
+
if (selectedType && selectedType.type !== initialFilter) {
|
|
29407
|
+
console.log(`[BottlenecksContent] Auto-selecting filter: ${selectedType.type} (count: ${dynamicCounts[selectedType.type] || 0})`);
|
|
29408
|
+
setInitialFilter(selectedType.type);
|
|
29409
|
+
setActiveFilter(selectedType.type);
|
|
29410
|
+
activeFilterRef.current = selectedType.type;
|
|
29290
29411
|
}
|
|
29291
|
-
}
|
|
29292
|
-
if (!selectedType) {
|
|
29293
|
-
selectedType = clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0);
|
|
29294
|
-
}
|
|
29295
|
-
const firstType = selectedType || clipTypes[0];
|
|
29296
|
-
if (firstType) {
|
|
29297
|
-
setInitialFilter(firstType.type);
|
|
29298
|
-
setActiveFilter(firstType.type);
|
|
29299
|
-
activeFilterRef.current = firstType.type;
|
|
29300
29412
|
}
|
|
29301
29413
|
}
|
|
29302
29414
|
}, [clipTypes, dynamicCounts, initialFilter]);
|
|
@@ -29348,7 +29460,7 @@ var BottlenecksContent = ({
|
|
|
29348
29460
|
} finally {
|
|
29349
29461
|
fetchInProgressRef.current.delete(operationKey);
|
|
29350
29462
|
}
|
|
29351
|
-
}, [workspaceId, date, s3ClipsService, effectiveShift, dashboardConfig, updateClipCounts]);
|
|
29463
|
+
}, [workspaceId, date, s3ClipsService, effectiveShift, dashboardConfig, updateClipCounts, timezone, totalOutput]);
|
|
29352
29464
|
const loadingCategoryRef = React23.useRef(null);
|
|
29353
29465
|
const loadFirstVideoForCategory = React23.useCallback(async (category) => {
|
|
29354
29466
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
@@ -29438,15 +29550,16 @@ var BottlenecksContent = ({
|
|
|
29438
29550
|
loadingCategoryRef.current = null;
|
|
29439
29551
|
fetchInProgressRef.current.delete(operationKey);
|
|
29440
29552
|
}
|
|
29441
|
-
}, [workspaceId, date, s3ClipsService, mergedCounts, effectiveShift]);
|
|
29553
|
+
}, [workspaceId, date, s3ClipsService, mergedCounts, effectiveShift, timezone]);
|
|
29442
29554
|
const handleRefreshClips = React23.useCallback(async () => {
|
|
29443
29555
|
console.log("[BottlenecksContent] Refreshing clips after new additions");
|
|
29444
29556
|
acknowledgeNewClips();
|
|
29557
|
+
invalidateMetadataCache();
|
|
29445
29558
|
await fetchClipCounts();
|
|
29446
29559
|
if (activeFilter && mergedCounts[activeFilter] > 0) {
|
|
29447
29560
|
await loadFirstVideoForCategory(activeFilter);
|
|
29448
29561
|
}
|
|
29449
|
-
}, [acknowledgeNewClips, fetchClipCounts, activeFilter, mergedCounts, loadFirstVideoForCategory]);
|
|
29562
|
+
}, [acknowledgeNewClips, fetchClipCounts, activeFilter, mergedCounts, loadFirstVideoForCategory, invalidateMetadataCache]);
|
|
29450
29563
|
React23.useEffect(() => {
|
|
29451
29564
|
if (s3ClipsService) {
|
|
29452
29565
|
fetchClipCounts();
|
|
@@ -29616,38 +29729,38 @@ var BottlenecksContent = ({
|
|
|
29616
29729
|
loadingTimeoutRef.current = null;
|
|
29617
29730
|
}
|
|
29618
29731
|
}, []);
|
|
29619
|
-
const loadCategoryMetadata = React23.useCallback(async (categoryId, autoLoadFirstVideo = false) => {
|
|
29732
|
+
const loadCategoryMetadata = React23.useCallback(async (categoryId, autoLoadFirstVideo = false, forceRefresh = false) => {
|
|
29620
29733
|
if (!workspaceId) {
|
|
29621
29734
|
return;
|
|
29622
29735
|
}
|
|
29623
|
-
const
|
|
29624
|
-
|
|
29625
|
-
|
|
29626
|
-
|
|
29627
|
-
|
|
29628
|
-
|
|
29629
|
-
|
|
29630
|
-
|
|
29631
|
-
|
|
29632
|
-
|
|
29633
|
-
|
|
29634
|
-
|
|
29635
|
-
|
|
29636
|
-
|
|
29637
|
-
|
|
29638
|
-
|
|
29639
|
-
|
|
29736
|
+
const resolvedDate = date || getOperationalDate(timezone);
|
|
29737
|
+
const cacheKey = `${categoryId}-${resolvedDate}-${effectiveShift}`;
|
|
29738
|
+
const cachedMetadata = !forceRefresh ? metadataCache[cacheKey] : void 0;
|
|
29739
|
+
try {
|
|
29740
|
+
if (cachedMetadata) {
|
|
29741
|
+
console.log(`[BottlenecksContent] Using cached metadata for ${categoryId}`);
|
|
29742
|
+
setCategoryMetadata(cachedMetadata);
|
|
29743
|
+
categoryMetadataRef.current = cachedMetadata;
|
|
29744
|
+
if (autoLoadFirstVideo && cachedMetadata.length > 0 && s3ClipsService) {
|
|
29745
|
+
const firstClipMeta = cachedMetadata[0];
|
|
29746
|
+
try {
|
|
29747
|
+
const video = await s3ClipsService.getClipById(firstClipMeta.clipId);
|
|
29748
|
+
if (video && isMountedRef.current) {
|
|
29749
|
+
setCurrentClipId(firstClipMeta.clipId);
|
|
29750
|
+
setAllVideos([video]);
|
|
29751
|
+
setCurrentIndex(0);
|
|
29752
|
+
setCurrentMetadataIndex(0);
|
|
29753
|
+
currentMetadataIndexRef.current = 0;
|
|
29754
|
+
console.log(`[BottlenecksContent] Auto-loaded first video from cache: ${video.id} (1/${cachedMetadata.length})`);
|
|
29755
|
+
}
|
|
29756
|
+
} catch (error2) {
|
|
29757
|
+
console.error(`[BottlenecksContent] Error loading first video from cache:`, error2);
|
|
29758
|
+
clearLoadingState();
|
|
29640
29759
|
}
|
|
29641
|
-
} catch (error2) {
|
|
29642
|
-
console.error(`[BottlenecksContent] Error loading first video from cache:`, error2);
|
|
29643
|
-
setIsCategoryLoading(false);
|
|
29644
|
-
clearLoadingState();
|
|
29645
29760
|
}
|
|
29761
|
+
return;
|
|
29646
29762
|
}
|
|
29647
|
-
|
|
29648
|
-
}
|
|
29649
|
-
try {
|
|
29650
|
-
console.log(`[BottlenecksContent] Loading metadata for category: ${categoryId}`);
|
|
29763
|
+
console.log(`[BottlenecksContent] Loading metadata for category: ${categoryId}${forceRefresh ? " (force refresh)" : ""}`);
|
|
29651
29764
|
const { createClient: createClient5 } = await import('@supabase/supabase-js');
|
|
29652
29765
|
const supabase = createClient5(
|
|
29653
29766
|
process.env.NEXT_PUBLIC_SUPABASE_URL || "",
|
|
@@ -29672,8 +29785,8 @@ var BottlenecksContent = ({
|
|
|
29672
29785
|
action: "percentile-clips",
|
|
29673
29786
|
percentileAction: percentileType,
|
|
29674
29787
|
workspaceId,
|
|
29675
|
-
startDate: `${
|
|
29676
|
-
endDate: `${
|
|
29788
|
+
startDate: `${resolvedDate}T00:00:00Z`,
|
|
29789
|
+
endDate: `${resolvedDate}T23:59:59Z`,
|
|
29677
29790
|
percentile: 10,
|
|
29678
29791
|
shiftId: effectiveShift,
|
|
29679
29792
|
limit: 100
|
|
@@ -29689,7 +29802,7 @@ var BottlenecksContent = ({
|
|
|
29689
29802
|
body: JSON.stringify({
|
|
29690
29803
|
action: "clip-metadata",
|
|
29691
29804
|
workspaceId,
|
|
29692
|
-
date:
|
|
29805
|
+
date: resolvedDate,
|
|
29693
29806
|
shift: effectiveShift,
|
|
29694
29807
|
category: categoryId,
|
|
29695
29808
|
page: 1,
|
|
@@ -29734,19 +29847,22 @@ var BottlenecksContent = ({
|
|
|
29734
29847
|
setCurrentIndex(0);
|
|
29735
29848
|
setCurrentMetadataIndex(0);
|
|
29736
29849
|
currentMetadataIndexRef.current = 0;
|
|
29737
|
-
setIsCategoryLoading(false);
|
|
29738
29850
|
console.log(`[BottlenecksContent] Auto-loaded first video: ${video.id} (1/${metadataClips.length})`);
|
|
29739
29851
|
}
|
|
29740
29852
|
} catch (error2) {
|
|
29741
29853
|
console.error(`[BottlenecksContent] Error loading first video:`, error2);
|
|
29742
|
-
setIsCategoryLoading(false);
|
|
29743
29854
|
}
|
|
29744
29855
|
}
|
|
29856
|
+
} else {
|
|
29857
|
+
setCategoryMetadata([]);
|
|
29858
|
+
categoryMetadataRef.current = [];
|
|
29745
29859
|
}
|
|
29746
29860
|
} catch (error2) {
|
|
29747
29861
|
console.error(`[BottlenecksContent] Error loading category metadata:`, error2);
|
|
29862
|
+
} finally {
|
|
29863
|
+
setIsCategoryLoading(false);
|
|
29748
29864
|
}
|
|
29749
|
-
}, [workspaceId, date, effectiveShift, isPercentileCategory, metadataCache, s3ClipsService]);
|
|
29865
|
+
}, [workspaceId, date, effectiveShift, isPercentileCategory, metadataCache, s3ClipsService, timezone, clearLoadingState]);
|
|
29750
29866
|
const loadAndPlayClipById = React23.useCallback(async (clipId, categoryId, position) => {
|
|
29751
29867
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
29752
29868
|
console.log(`[BottlenecksContent] Loading clip by ID: ${clipId}, category=${categoryId}, position=${position}`);
|
|
@@ -29770,21 +29886,31 @@ var BottlenecksContent = ({
|
|
|
29770
29886
|
}
|
|
29771
29887
|
try {
|
|
29772
29888
|
await loadCategoryMetadata(categoryId, false);
|
|
29773
|
-
|
|
29774
|
-
|
|
29775
|
-
|
|
29776
|
-
|
|
29777
|
-
|
|
29778
|
-
|
|
29779
|
-
|
|
29780
|
-
|
|
29781
|
-
|
|
29782
|
-
|
|
29783
|
-
|
|
29784
|
-
|
|
29785
|
-
|
|
29786
|
-
|
|
29787
|
-
|
|
29889
|
+
let metadataArray = categoryMetadataRef.current;
|
|
29890
|
+
const clipExistsInMetadata = metadataArray.some((clip) => clip.clipId === clipId);
|
|
29891
|
+
if (metadataArray.length === 0 || !clipExistsInMetadata) {
|
|
29892
|
+
console.warn(`[BottlenecksContent] Clip ${clipId} not found in metadata for ${categoryId} (cache hit: ${metadataArray.length > 0}) - forcing refresh`);
|
|
29893
|
+
await loadCategoryMetadata(categoryId, false, true);
|
|
29894
|
+
metadataArray = categoryMetadataRef.current;
|
|
29895
|
+
}
|
|
29896
|
+
if (metadataArray.length === 0) {
|
|
29897
|
+
throw new Error(`No metadata available for category ${categoryId}`);
|
|
29898
|
+
}
|
|
29899
|
+
const clickedClipIndex = metadataArray.findIndex((clip) => clip.clipId === clipId);
|
|
29900
|
+
if (clickedClipIndex === -1) {
|
|
29901
|
+
throw new Error(`Clip ${clipId} not found after metadata refresh`);
|
|
29902
|
+
}
|
|
29903
|
+
setCurrentMetadataIndex(clickedClipIndex);
|
|
29904
|
+
currentMetadataIndexRef.current = clickedClipIndex;
|
|
29905
|
+
const video = await s3ClipsService.getClipById(clipId);
|
|
29906
|
+
if (video) {
|
|
29907
|
+
setPendingVideo(video);
|
|
29908
|
+
setCurrentClipId(clipId);
|
|
29909
|
+
setAllVideos([video]);
|
|
29910
|
+
setCurrentIndex(0);
|
|
29911
|
+
console.log(`[BottlenecksContent] Loaded clip ${clipId} (${clickedClipIndex + 1}/${metadataArray.length})`);
|
|
29912
|
+
} else {
|
|
29913
|
+
throw new Error(`Failed to load video data for clip ${clipId}`);
|
|
29788
29914
|
}
|
|
29789
29915
|
} catch (error2) {
|
|
29790
29916
|
console.error(`[BottlenecksContent] Error loading clip by ID (${clipId}):`, error2);
|
|
@@ -29798,7 +29924,7 @@ var BottlenecksContent = ({
|
|
|
29798
29924
|
clearLoadingState();
|
|
29799
29925
|
}
|
|
29800
29926
|
}
|
|
29801
|
-
}, [workspaceId, s3ClipsService,
|
|
29927
|
+
}, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, loadCategoryMetadata]);
|
|
29802
29928
|
React23.useCallback(async (categoryId, clipIndex) => {
|
|
29803
29929
|
console.warn("[BottlenecksContent] loadAndPlayClip is deprecated, use loadAndPlayClipById instead");
|
|
29804
29930
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
@@ -29825,7 +29951,7 @@ var BottlenecksContent = ({
|
|
|
29825
29951
|
});
|
|
29826
29952
|
setIsNavigating(false);
|
|
29827
29953
|
}
|
|
29828
|
-
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById]);
|
|
29954
|
+
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById, timezone]);
|
|
29829
29955
|
const handleNext = React23.useCallback(async () => {
|
|
29830
29956
|
if (!isMountedRef.current) return;
|
|
29831
29957
|
const currentFilter = activeFilterRef.current;
|
|
@@ -29842,8 +29968,18 @@ var BottlenecksContent = ({
|
|
|
29842
29968
|
}
|
|
29843
29969
|
try {
|
|
29844
29970
|
const currentMetaIndex = currentMetadataIndexRef.current;
|
|
29845
|
-
|
|
29971
|
+
let metadataArray = categoryMetadataRef.current;
|
|
29972
|
+
if (metadataArray.length === 0) {
|
|
29973
|
+
console.log(`[handleNext] Metadata empty for ${currentFilter}, loading before navigation`);
|
|
29974
|
+
await loadCategoryMetadata(currentFilter, false);
|
|
29975
|
+
metadataArray = categoryMetadataRef.current;
|
|
29976
|
+
}
|
|
29846
29977
|
console.log(`[handleNext] Unified navigation: ${currentFilter}, metadata index: ${currentMetaIndex}/${metadataArray.length}`);
|
|
29978
|
+
if (metadataArray.length === 0) {
|
|
29979
|
+
console.warn("[handleNext] No metadata available after refresh - stopping navigation");
|
|
29980
|
+
clearLoadingState();
|
|
29981
|
+
return;
|
|
29982
|
+
}
|
|
29847
29983
|
if (currentMetaIndex < metadataArray.length - 1) {
|
|
29848
29984
|
const nextMetadataIndex = currentMetaIndex + 1;
|
|
29849
29985
|
const nextClipMeta = metadataArray[nextMetadataIndex];
|
|
@@ -29878,7 +30014,7 @@ var BottlenecksContent = ({
|
|
|
29878
30014
|
});
|
|
29879
30015
|
clearLoadingState();
|
|
29880
30016
|
}
|
|
29881
|
-
}, [clearLoadingState, s3ClipsService]);
|
|
30017
|
+
}, [clearLoadingState, s3ClipsService, loadCategoryMetadata]);
|
|
29882
30018
|
const handlePrevious = React23.useCallback(async () => {
|
|
29883
30019
|
if (!isMountedRef.current) return;
|
|
29884
30020
|
const currentFilter = activeFilterRef.current;
|
|
@@ -29895,8 +30031,18 @@ var BottlenecksContent = ({
|
|
|
29895
30031
|
}
|
|
29896
30032
|
try {
|
|
29897
30033
|
const currentMetaIndex = currentMetadataIndexRef.current;
|
|
29898
|
-
|
|
30034
|
+
let metadataArray = categoryMetadataRef.current;
|
|
30035
|
+
if (metadataArray.length === 0) {
|
|
30036
|
+
console.log(`[handlePrevious] Metadata empty for ${currentFilter}, loading before navigation`);
|
|
30037
|
+
await loadCategoryMetadata(currentFilter, false);
|
|
30038
|
+
metadataArray = categoryMetadataRef.current;
|
|
30039
|
+
}
|
|
29899
30040
|
console.log(`[handlePrevious] Unified navigation: ${currentFilter}, metadata index: ${currentMetaIndex}/${metadataArray.length}`);
|
|
30041
|
+
if (metadataArray.length === 0) {
|
|
30042
|
+
console.warn("[handlePrevious] No metadata available after refresh - stopping navigation");
|
|
30043
|
+
clearLoadingState();
|
|
30044
|
+
return;
|
|
30045
|
+
}
|
|
29900
30046
|
if (currentMetaIndex > 0) {
|
|
29901
30047
|
const prevMetadataIndex = currentMetaIndex - 1;
|
|
29902
30048
|
const prevClipMeta = metadataArray[prevMetadataIndex];
|
|
@@ -29927,7 +30073,7 @@ var BottlenecksContent = ({
|
|
|
29927
30073
|
});
|
|
29928
30074
|
clearLoadingState();
|
|
29929
30075
|
}
|
|
29930
|
-
}, [clearLoadingState, s3ClipsService]);
|
|
30076
|
+
}, [clearLoadingState, s3ClipsService, loadCategoryMetadata]);
|
|
29931
30077
|
const currentVideo = React23.useMemo(() => {
|
|
29932
30078
|
if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
|
|
29933
30079
|
return null;
|
package/dist/index.mjs
CHANGED
|
@@ -23070,7 +23070,7 @@ var OutputProgressChartComponent = ({
|
|
|
23070
23070
|
];
|
|
23071
23071
|
const COLORS = ["#00AB45", "#f3f4f6"];
|
|
23072
23072
|
const percentage = (currentOutput / targetOutput * 100).toFixed(1);
|
|
23073
|
-
return /* @__PURE__ */ jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "relative w-full aspect-square max-h-full", style: { maxWidth: "min(100%, 280px)" }, children: [
|
|
23073
|
+
return /* @__PURE__ */ jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "relative w-full aspect-square max-h-full", style: { maxWidth: "min(100%, 280px)", containerType: "inline-size" }, children: [
|
|
23074
23074
|
/* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsx(PieChart, { children: /* @__PURE__ */ jsx(
|
|
23075
23075
|
Pie,
|
|
23076
23076
|
{
|
|
@@ -23094,16 +23094,33 @@ var OutputProgressChartComponent = ({
|
|
|
23094
23094
|
))
|
|
23095
23095
|
}
|
|
23096
23096
|
) }) }),
|
|
23097
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
23098
|
-
/* @__PURE__ */ jsxs(
|
|
23099
|
-
|
|
23100
|
-
|
|
23101
|
-
|
|
23102
|
-
|
|
23103
|
-
|
|
23104
|
-
|
|
23105
|
-
|
|
23106
|
-
|
|
23097
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", style: { width: "100%", padding: "0 10%" }, children: [
|
|
23098
|
+
/* @__PURE__ */ jsxs(
|
|
23099
|
+
"div",
|
|
23100
|
+
{
|
|
23101
|
+
className: "font-bold text-gray-800",
|
|
23102
|
+
style: { fontSize: "clamp(1.25rem, 8cqw, 2.5rem)" },
|
|
23103
|
+
children: [
|
|
23104
|
+
percentage,
|
|
23105
|
+
"%"
|
|
23106
|
+
]
|
|
23107
|
+
}
|
|
23108
|
+
),
|
|
23109
|
+
/* @__PURE__ */ jsxs(
|
|
23110
|
+
"div",
|
|
23111
|
+
{
|
|
23112
|
+
className: "text-gray-500",
|
|
23113
|
+
style: {
|
|
23114
|
+
fontSize: "clamp(0.7rem, 3.5cqw, 1rem)",
|
|
23115
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.5rem)"
|
|
23116
|
+
},
|
|
23117
|
+
children: [
|
|
23118
|
+
currentOutput,
|
|
23119
|
+
" / ",
|
|
23120
|
+
Math.round(targetOutput)
|
|
23121
|
+
]
|
|
23122
|
+
}
|
|
23123
|
+
)
|
|
23107
23124
|
] }) })
|
|
23108
23125
|
] }) });
|
|
23109
23126
|
};
|
|
@@ -23121,7 +23138,7 @@ var LargeOutputProgressChart = ({
|
|
|
23121
23138
|
];
|
|
23122
23139
|
const COLORS = ["#00AB45", "#f3f4f6"];
|
|
23123
23140
|
const percentage = (currentOutput / targetOutput * 100).toFixed(1);
|
|
23124
|
-
return /* @__PURE__ */ jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full", style: { minHeight: "100px", minWidth: "100px" }, children: [
|
|
23141
|
+
return /* @__PURE__ */ jsx("div", { className: `w-full h-full flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full", style: { minHeight: "100px", minWidth: "100px", containerType: "inline-size" }, children: [
|
|
23125
23142
|
/* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsx(PieChart, { children: /* @__PURE__ */ jsx(
|
|
23126
23143
|
Pie,
|
|
23127
23144
|
{
|
|
@@ -23145,16 +23162,40 @@ var LargeOutputProgressChart = ({
|
|
|
23145
23162
|
))
|
|
23146
23163
|
}
|
|
23147
23164
|
) }) }),
|
|
23148
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
23149
|
-
/* @__PURE__ */ jsx(
|
|
23150
|
-
|
|
23151
|
-
|
|
23152
|
-
|
|
23153
|
-
|
|
23154
|
-
|
|
23155
|
-
|
|
23156
|
-
|
|
23157
|
-
|
|
23165
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", style: { width: "100%", padding: "0 10%" }, children: [
|
|
23166
|
+
/* @__PURE__ */ jsx(
|
|
23167
|
+
"div",
|
|
23168
|
+
{
|
|
23169
|
+
className: "font-bold text-gray-900",
|
|
23170
|
+
style: { fontSize: "clamp(1.5rem, 10cqw, 3rem)" },
|
|
23171
|
+
children: currentOutput
|
|
23172
|
+
}
|
|
23173
|
+
),
|
|
23174
|
+
/* @__PURE__ */ jsxs(
|
|
23175
|
+
"div",
|
|
23176
|
+
{
|
|
23177
|
+
className: "text-gray-500",
|
|
23178
|
+
style: { fontSize: "clamp(0.75rem, 3.5cqw, 1rem)" },
|
|
23179
|
+
children: [
|
|
23180
|
+
"of ",
|
|
23181
|
+
targetOutput
|
|
23182
|
+
]
|
|
23183
|
+
}
|
|
23184
|
+
),
|
|
23185
|
+
/* @__PURE__ */ jsxs(
|
|
23186
|
+
"div",
|
|
23187
|
+
{
|
|
23188
|
+
className: "font-medium text-gray-600",
|
|
23189
|
+
style: {
|
|
23190
|
+
fontSize: "clamp(0.875rem, 4.5cqw, 1.25rem)",
|
|
23191
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.5rem)"
|
|
23192
|
+
},
|
|
23193
|
+
children: [
|
|
23194
|
+
percentage,
|
|
23195
|
+
"%"
|
|
23196
|
+
]
|
|
23197
|
+
}
|
|
23198
|
+
)
|
|
23158
23199
|
] }) })
|
|
23159
23200
|
] }) });
|
|
23160
23201
|
};
|
|
@@ -25248,7 +25289,7 @@ var GaugeChart = ({
|
|
|
25248
25289
|
};
|
|
25249
25290
|
const gaugeColor = getColor();
|
|
25250
25291
|
const targetAngle = target !== void 0 ? 180 - (target - min) / (max - min) * 180 : null;
|
|
25251
|
-
return /* @__PURE__ */ jsx("div", { className: `relative w-full h-full flex flex-col items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "relative w-full max-w-[280px] aspect-square", style: { minHeight: "100px", minWidth: "100px" }, children: [
|
|
25292
|
+
return /* @__PURE__ */ jsx("div", { className: `relative w-full h-full flex flex-col items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "relative w-full max-w-[280px] aspect-square", style: { minHeight: "100px", minWidth: "100px", containerType: "inline-size" }, children: [
|
|
25252
25293
|
/* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsx(PieChart, { children: /* @__PURE__ */ jsxs(
|
|
25253
25294
|
Pie,
|
|
25254
25295
|
{
|
|
@@ -25281,17 +25322,44 @@ var GaugeChart = ({
|
|
|
25281
25322
|
children: /* @__PURE__ */ jsx("div", { className: "absolute -top-1 -left-1.5 w-3 h-3 bg-gray-800 rounded-full" })
|
|
25282
25323
|
}
|
|
25283
25324
|
),
|
|
25284
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
25285
|
-
/* @__PURE__ */ jsxs(
|
|
25286
|
-
|
|
25287
|
-
|
|
25288
|
-
|
|
25289
|
-
|
|
25290
|
-
|
|
25291
|
-
|
|
25292
|
-
|
|
25293
|
-
|
|
25294
|
-
|
|
25325
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex flex-col items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", style: { width: "100%", padding: "0 10%" }, children: [
|
|
25326
|
+
/* @__PURE__ */ jsxs(
|
|
25327
|
+
"div",
|
|
25328
|
+
{
|
|
25329
|
+
className: "font-bold text-gray-800",
|
|
25330
|
+
style: { fontSize: "clamp(1.25rem, 8cqw, 2rem)" },
|
|
25331
|
+
children: [
|
|
25332
|
+
value.toFixed(unit === "%" ? 1 : 0),
|
|
25333
|
+
unit
|
|
25334
|
+
]
|
|
25335
|
+
}
|
|
25336
|
+
),
|
|
25337
|
+
/* @__PURE__ */ jsx(
|
|
25338
|
+
"div",
|
|
25339
|
+
{
|
|
25340
|
+
className: "text-gray-600 font-medium",
|
|
25341
|
+
style: {
|
|
25342
|
+
fontSize: "clamp(0.75rem, 3.5cqw, 1rem)",
|
|
25343
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.25rem)"
|
|
25344
|
+
},
|
|
25345
|
+
children: label
|
|
25346
|
+
}
|
|
25347
|
+
),
|
|
25348
|
+
target !== void 0 && /* @__PURE__ */ jsxs(
|
|
25349
|
+
"div",
|
|
25350
|
+
{
|
|
25351
|
+
className: "text-gray-500",
|
|
25352
|
+
style: {
|
|
25353
|
+
fontSize: "clamp(0.7rem, 3cqw, 0.875rem)",
|
|
25354
|
+
marginTop: "clamp(0.125rem, 1cqw, 0.25rem)"
|
|
25355
|
+
},
|
|
25356
|
+
children: [
|
|
25357
|
+
"Target: ",
|
|
25358
|
+
target,
|
|
25359
|
+
unit
|
|
25360
|
+
]
|
|
25361
|
+
}
|
|
25362
|
+
)
|
|
25295
25363
|
] }) }),
|
|
25296
25364
|
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-[15%] left-[15%] text-xs text-gray-500", children: [
|
|
25297
25365
|
min,
|
|
@@ -29185,6 +29253,31 @@ var BottlenecksContent = ({
|
|
|
29185
29253
|
const [categoryMetadata, setCategoryMetadata] = useState([]);
|
|
29186
29254
|
const [currentMetadataIndex, setCurrentMetadataIndex] = useState(0);
|
|
29187
29255
|
const [metadataCache, setMetadataCache] = useState({});
|
|
29256
|
+
const invalidateMetadataCache = useCallback((categories) => {
|
|
29257
|
+
setMetadataCache((prevCache) => {
|
|
29258
|
+
if (!prevCache || Object.keys(prevCache).length === 0) {
|
|
29259
|
+
return prevCache;
|
|
29260
|
+
}
|
|
29261
|
+
const targetCategories = categories ? (Array.isArray(categories) ? categories : [categories]).filter(Boolean) : null;
|
|
29262
|
+
let updatedCache = null;
|
|
29263
|
+
const shouldInvalidate = (key) => {
|
|
29264
|
+
if (!targetCategories || targetCategories.length === 0) {
|
|
29265
|
+
return true;
|
|
29266
|
+
}
|
|
29267
|
+
const [categoryId] = key.split("-");
|
|
29268
|
+
return targetCategories.includes(categoryId);
|
|
29269
|
+
};
|
|
29270
|
+
Object.keys(prevCache).forEach((cacheKey) => {
|
|
29271
|
+
if (shouldInvalidate(cacheKey)) {
|
|
29272
|
+
if (!updatedCache) {
|
|
29273
|
+
updatedCache = { ...prevCache };
|
|
29274
|
+
}
|
|
29275
|
+
delete updatedCache[cacheKey];
|
|
29276
|
+
}
|
|
29277
|
+
});
|
|
29278
|
+
return updatedCache || prevCache;
|
|
29279
|
+
});
|
|
29280
|
+
}, []);
|
|
29188
29281
|
const [triageClips, setTriageClips] = useState([]);
|
|
29189
29282
|
const [isLoadingTriageClips, setIsLoadingTriageClips] = useState(false);
|
|
29190
29283
|
const [isFullscreen, setIsFullscreen] = useState(false);
|
|
@@ -29204,6 +29297,12 @@ var BottlenecksContent = ({
|
|
|
29204
29297
|
onNewClips: (notification) => {
|
|
29205
29298
|
console.log(`[BottlenecksContent] New clips detected:`, notification);
|
|
29206
29299
|
if (notification.clips.length > 0) {
|
|
29300
|
+
const categoryIds = notification.clips.map((clip) => clip.clip_type).filter(Boolean).map((value) => String(value));
|
|
29301
|
+
if (categoryIds.length > 0) {
|
|
29302
|
+
invalidateMetadataCache(categoryIds);
|
|
29303
|
+
} else {
|
|
29304
|
+
invalidateMetadataCache();
|
|
29305
|
+
}
|
|
29207
29306
|
fetchClipCounts();
|
|
29208
29307
|
}
|
|
29209
29308
|
}
|
|
@@ -29250,24 +29349,37 @@ var BottlenecksContent = ({
|
|
|
29250
29349
|
shift: shift || "0"
|
|
29251
29350
|
});
|
|
29252
29351
|
useEffect(() => {
|
|
29253
|
-
if (clipTypes.length > 0
|
|
29254
|
-
const
|
|
29255
|
-
|
|
29256
|
-
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
|
|
29260
|
-
|
|
29352
|
+
if (clipTypes.length > 0) {
|
|
29353
|
+
const currentFilterCount = initialFilter ? dynamicCounts[initialFilter] || 0 : 0;
|
|
29354
|
+
const hasAnyCounts = Object.values(dynamicCounts).some((c) => c > 0);
|
|
29355
|
+
const userHasNotNavigated = !initialFilter || activeFilterRef.current === initialFilter;
|
|
29356
|
+
const shouldRunSelection = !initialFilter || userHasNotNavigated && currentFilterCount === 0 && hasAnyCounts;
|
|
29357
|
+
if (shouldRunSelection) {
|
|
29358
|
+
let selectedType = null;
|
|
29359
|
+
if (clipTypes.length === 1) {
|
|
29360
|
+
selectedType = clipTypes[0];
|
|
29361
|
+
} else {
|
|
29362
|
+
const priorityOrder = ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
29363
|
+
for (const priorityType of priorityOrder) {
|
|
29364
|
+
const type = clipTypes.find((t) => t.type === priorityType && (dynamicCounts[t.type] || 0) > 0);
|
|
29365
|
+
if (type) {
|
|
29366
|
+
selectedType = type;
|
|
29367
|
+
break;
|
|
29368
|
+
}
|
|
29369
|
+
}
|
|
29370
|
+
if (!selectedType) {
|
|
29371
|
+
selectedType = clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0);
|
|
29372
|
+
}
|
|
29373
|
+
if (!selectedType) {
|
|
29374
|
+
selectedType = clipTypes[0];
|
|
29375
|
+
}
|
|
29376
|
+
}
|
|
29377
|
+
if (selectedType && selectedType.type !== initialFilter) {
|
|
29378
|
+
console.log(`[BottlenecksContent] Auto-selecting filter: ${selectedType.type} (count: ${dynamicCounts[selectedType.type] || 0})`);
|
|
29379
|
+
setInitialFilter(selectedType.type);
|
|
29380
|
+
setActiveFilter(selectedType.type);
|
|
29381
|
+
activeFilterRef.current = selectedType.type;
|
|
29261
29382
|
}
|
|
29262
|
-
}
|
|
29263
|
-
if (!selectedType) {
|
|
29264
|
-
selectedType = clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0);
|
|
29265
|
-
}
|
|
29266
|
-
const firstType = selectedType || clipTypes[0];
|
|
29267
|
-
if (firstType) {
|
|
29268
|
-
setInitialFilter(firstType.type);
|
|
29269
|
-
setActiveFilter(firstType.type);
|
|
29270
|
-
activeFilterRef.current = firstType.type;
|
|
29271
29383
|
}
|
|
29272
29384
|
}
|
|
29273
29385
|
}, [clipTypes, dynamicCounts, initialFilter]);
|
|
@@ -29319,7 +29431,7 @@ var BottlenecksContent = ({
|
|
|
29319
29431
|
} finally {
|
|
29320
29432
|
fetchInProgressRef.current.delete(operationKey);
|
|
29321
29433
|
}
|
|
29322
|
-
}, [workspaceId, date, s3ClipsService, effectiveShift, dashboardConfig, updateClipCounts]);
|
|
29434
|
+
}, [workspaceId, date, s3ClipsService, effectiveShift, dashboardConfig, updateClipCounts, timezone, totalOutput]);
|
|
29323
29435
|
const loadingCategoryRef = useRef(null);
|
|
29324
29436
|
const loadFirstVideoForCategory = useCallback(async (category) => {
|
|
29325
29437
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
@@ -29409,15 +29521,16 @@ var BottlenecksContent = ({
|
|
|
29409
29521
|
loadingCategoryRef.current = null;
|
|
29410
29522
|
fetchInProgressRef.current.delete(operationKey);
|
|
29411
29523
|
}
|
|
29412
|
-
}, [workspaceId, date, s3ClipsService, mergedCounts, effectiveShift]);
|
|
29524
|
+
}, [workspaceId, date, s3ClipsService, mergedCounts, effectiveShift, timezone]);
|
|
29413
29525
|
const handleRefreshClips = useCallback(async () => {
|
|
29414
29526
|
console.log("[BottlenecksContent] Refreshing clips after new additions");
|
|
29415
29527
|
acknowledgeNewClips();
|
|
29528
|
+
invalidateMetadataCache();
|
|
29416
29529
|
await fetchClipCounts();
|
|
29417
29530
|
if (activeFilter && mergedCounts[activeFilter] > 0) {
|
|
29418
29531
|
await loadFirstVideoForCategory(activeFilter);
|
|
29419
29532
|
}
|
|
29420
|
-
}, [acknowledgeNewClips, fetchClipCounts, activeFilter, mergedCounts, loadFirstVideoForCategory]);
|
|
29533
|
+
}, [acknowledgeNewClips, fetchClipCounts, activeFilter, mergedCounts, loadFirstVideoForCategory, invalidateMetadataCache]);
|
|
29421
29534
|
useEffect(() => {
|
|
29422
29535
|
if (s3ClipsService) {
|
|
29423
29536
|
fetchClipCounts();
|
|
@@ -29587,38 +29700,38 @@ var BottlenecksContent = ({
|
|
|
29587
29700
|
loadingTimeoutRef.current = null;
|
|
29588
29701
|
}
|
|
29589
29702
|
}, []);
|
|
29590
|
-
const loadCategoryMetadata = useCallback(async (categoryId, autoLoadFirstVideo = false) => {
|
|
29703
|
+
const loadCategoryMetadata = useCallback(async (categoryId, autoLoadFirstVideo = false, forceRefresh = false) => {
|
|
29591
29704
|
if (!workspaceId) {
|
|
29592
29705
|
return;
|
|
29593
29706
|
}
|
|
29594
|
-
const
|
|
29595
|
-
|
|
29596
|
-
|
|
29597
|
-
|
|
29598
|
-
|
|
29599
|
-
|
|
29600
|
-
|
|
29601
|
-
|
|
29602
|
-
|
|
29603
|
-
|
|
29604
|
-
|
|
29605
|
-
|
|
29606
|
-
|
|
29607
|
-
|
|
29608
|
-
|
|
29609
|
-
|
|
29610
|
-
|
|
29707
|
+
const resolvedDate = date || getOperationalDate(timezone);
|
|
29708
|
+
const cacheKey = `${categoryId}-${resolvedDate}-${effectiveShift}`;
|
|
29709
|
+
const cachedMetadata = !forceRefresh ? metadataCache[cacheKey] : void 0;
|
|
29710
|
+
try {
|
|
29711
|
+
if (cachedMetadata) {
|
|
29712
|
+
console.log(`[BottlenecksContent] Using cached metadata for ${categoryId}`);
|
|
29713
|
+
setCategoryMetadata(cachedMetadata);
|
|
29714
|
+
categoryMetadataRef.current = cachedMetadata;
|
|
29715
|
+
if (autoLoadFirstVideo && cachedMetadata.length > 0 && s3ClipsService) {
|
|
29716
|
+
const firstClipMeta = cachedMetadata[0];
|
|
29717
|
+
try {
|
|
29718
|
+
const video = await s3ClipsService.getClipById(firstClipMeta.clipId);
|
|
29719
|
+
if (video && isMountedRef.current) {
|
|
29720
|
+
setCurrentClipId(firstClipMeta.clipId);
|
|
29721
|
+
setAllVideos([video]);
|
|
29722
|
+
setCurrentIndex(0);
|
|
29723
|
+
setCurrentMetadataIndex(0);
|
|
29724
|
+
currentMetadataIndexRef.current = 0;
|
|
29725
|
+
console.log(`[BottlenecksContent] Auto-loaded first video from cache: ${video.id} (1/${cachedMetadata.length})`);
|
|
29726
|
+
}
|
|
29727
|
+
} catch (error2) {
|
|
29728
|
+
console.error(`[BottlenecksContent] Error loading first video from cache:`, error2);
|
|
29729
|
+
clearLoadingState();
|
|
29611
29730
|
}
|
|
29612
|
-
} catch (error2) {
|
|
29613
|
-
console.error(`[BottlenecksContent] Error loading first video from cache:`, error2);
|
|
29614
|
-
setIsCategoryLoading(false);
|
|
29615
|
-
clearLoadingState();
|
|
29616
29731
|
}
|
|
29732
|
+
return;
|
|
29617
29733
|
}
|
|
29618
|
-
|
|
29619
|
-
}
|
|
29620
|
-
try {
|
|
29621
|
-
console.log(`[BottlenecksContent] Loading metadata for category: ${categoryId}`);
|
|
29734
|
+
console.log(`[BottlenecksContent] Loading metadata for category: ${categoryId}${forceRefresh ? " (force refresh)" : ""}`);
|
|
29622
29735
|
const { createClient: createClient5 } = await import('@supabase/supabase-js');
|
|
29623
29736
|
const supabase = createClient5(
|
|
29624
29737
|
process.env.NEXT_PUBLIC_SUPABASE_URL || "",
|
|
@@ -29643,8 +29756,8 @@ var BottlenecksContent = ({
|
|
|
29643
29756
|
action: "percentile-clips",
|
|
29644
29757
|
percentileAction: percentileType,
|
|
29645
29758
|
workspaceId,
|
|
29646
|
-
startDate: `${
|
|
29647
|
-
endDate: `${
|
|
29759
|
+
startDate: `${resolvedDate}T00:00:00Z`,
|
|
29760
|
+
endDate: `${resolvedDate}T23:59:59Z`,
|
|
29648
29761
|
percentile: 10,
|
|
29649
29762
|
shiftId: effectiveShift,
|
|
29650
29763
|
limit: 100
|
|
@@ -29660,7 +29773,7 @@ var BottlenecksContent = ({
|
|
|
29660
29773
|
body: JSON.stringify({
|
|
29661
29774
|
action: "clip-metadata",
|
|
29662
29775
|
workspaceId,
|
|
29663
|
-
date:
|
|
29776
|
+
date: resolvedDate,
|
|
29664
29777
|
shift: effectiveShift,
|
|
29665
29778
|
category: categoryId,
|
|
29666
29779
|
page: 1,
|
|
@@ -29705,19 +29818,22 @@ var BottlenecksContent = ({
|
|
|
29705
29818
|
setCurrentIndex(0);
|
|
29706
29819
|
setCurrentMetadataIndex(0);
|
|
29707
29820
|
currentMetadataIndexRef.current = 0;
|
|
29708
|
-
setIsCategoryLoading(false);
|
|
29709
29821
|
console.log(`[BottlenecksContent] Auto-loaded first video: ${video.id} (1/${metadataClips.length})`);
|
|
29710
29822
|
}
|
|
29711
29823
|
} catch (error2) {
|
|
29712
29824
|
console.error(`[BottlenecksContent] Error loading first video:`, error2);
|
|
29713
|
-
setIsCategoryLoading(false);
|
|
29714
29825
|
}
|
|
29715
29826
|
}
|
|
29827
|
+
} else {
|
|
29828
|
+
setCategoryMetadata([]);
|
|
29829
|
+
categoryMetadataRef.current = [];
|
|
29716
29830
|
}
|
|
29717
29831
|
} catch (error2) {
|
|
29718
29832
|
console.error(`[BottlenecksContent] Error loading category metadata:`, error2);
|
|
29833
|
+
} finally {
|
|
29834
|
+
setIsCategoryLoading(false);
|
|
29719
29835
|
}
|
|
29720
|
-
}, [workspaceId, date, effectiveShift, isPercentileCategory, metadataCache, s3ClipsService]);
|
|
29836
|
+
}, [workspaceId, date, effectiveShift, isPercentileCategory, metadataCache, s3ClipsService, timezone, clearLoadingState]);
|
|
29721
29837
|
const loadAndPlayClipById = useCallback(async (clipId, categoryId, position) => {
|
|
29722
29838
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
29723
29839
|
console.log(`[BottlenecksContent] Loading clip by ID: ${clipId}, category=${categoryId}, position=${position}`);
|
|
@@ -29741,21 +29857,31 @@ var BottlenecksContent = ({
|
|
|
29741
29857
|
}
|
|
29742
29858
|
try {
|
|
29743
29859
|
await loadCategoryMetadata(categoryId, false);
|
|
29744
|
-
|
|
29745
|
-
|
|
29746
|
-
|
|
29747
|
-
|
|
29748
|
-
|
|
29749
|
-
|
|
29750
|
-
|
|
29751
|
-
|
|
29752
|
-
|
|
29753
|
-
|
|
29754
|
-
|
|
29755
|
-
|
|
29756
|
-
|
|
29757
|
-
|
|
29758
|
-
|
|
29860
|
+
let metadataArray = categoryMetadataRef.current;
|
|
29861
|
+
const clipExistsInMetadata = metadataArray.some((clip) => clip.clipId === clipId);
|
|
29862
|
+
if (metadataArray.length === 0 || !clipExistsInMetadata) {
|
|
29863
|
+
console.warn(`[BottlenecksContent] Clip ${clipId} not found in metadata for ${categoryId} (cache hit: ${metadataArray.length > 0}) - forcing refresh`);
|
|
29864
|
+
await loadCategoryMetadata(categoryId, false, true);
|
|
29865
|
+
metadataArray = categoryMetadataRef.current;
|
|
29866
|
+
}
|
|
29867
|
+
if (metadataArray.length === 0) {
|
|
29868
|
+
throw new Error(`No metadata available for category ${categoryId}`);
|
|
29869
|
+
}
|
|
29870
|
+
const clickedClipIndex = metadataArray.findIndex((clip) => clip.clipId === clipId);
|
|
29871
|
+
if (clickedClipIndex === -1) {
|
|
29872
|
+
throw new Error(`Clip ${clipId} not found after metadata refresh`);
|
|
29873
|
+
}
|
|
29874
|
+
setCurrentMetadataIndex(clickedClipIndex);
|
|
29875
|
+
currentMetadataIndexRef.current = clickedClipIndex;
|
|
29876
|
+
const video = await s3ClipsService.getClipById(clipId);
|
|
29877
|
+
if (video) {
|
|
29878
|
+
setPendingVideo(video);
|
|
29879
|
+
setCurrentClipId(clipId);
|
|
29880
|
+
setAllVideos([video]);
|
|
29881
|
+
setCurrentIndex(0);
|
|
29882
|
+
console.log(`[BottlenecksContent] Loaded clip ${clipId} (${clickedClipIndex + 1}/${metadataArray.length})`);
|
|
29883
|
+
} else {
|
|
29884
|
+
throw new Error(`Failed to load video data for clip ${clipId}`);
|
|
29759
29885
|
}
|
|
29760
29886
|
} catch (error2) {
|
|
29761
29887
|
console.error(`[BottlenecksContent] Error loading clip by ID (${clipId}):`, error2);
|
|
@@ -29769,7 +29895,7 @@ var BottlenecksContent = ({
|
|
|
29769
29895
|
clearLoadingState();
|
|
29770
29896
|
}
|
|
29771
29897
|
}
|
|
29772
|
-
}, [workspaceId, s3ClipsService,
|
|
29898
|
+
}, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, loadCategoryMetadata]);
|
|
29773
29899
|
useCallback(async (categoryId, clipIndex) => {
|
|
29774
29900
|
console.warn("[BottlenecksContent] loadAndPlayClip is deprecated, use loadAndPlayClipById instead");
|
|
29775
29901
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
@@ -29796,7 +29922,7 @@ var BottlenecksContent = ({
|
|
|
29796
29922
|
});
|
|
29797
29923
|
setIsNavigating(false);
|
|
29798
29924
|
}
|
|
29799
|
-
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById]);
|
|
29925
|
+
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById, timezone]);
|
|
29800
29926
|
const handleNext = useCallback(async () => {
|
|
29801
29927
|
if (!isMountedRef.current) return;
|
|
29802
29928
|
const currentFilter = activeFilterRef.current;
|
|
@@ -29813,8 +29939,18 @@ var BottlenecksContent = ({
|
|
|
29813
29939
|
}
|
|
29814
29940
|
try {
|
|
29815
29941
|
const currentMetaIndex = currentMetadataIndexRef.current;
|
|
29816
|
-
|
|
29942
|
+
let metadataArray = categoryMetadataRef.current;
|
|
29943
|
+
if (metadataArray.length === 0) {
|
|
29944
|
+
console.log(`[handleNext] Metadata empty for ${currentFilter}, loading before navigation`);
|
|
29945
|
+
await loadCategoryMetadata(currentFilter, false);
|
|
29946
|
+
metadataArray = categoryMetadataRef.current;
|
|
29947
|
+
}
|
|
29817
29948
|
console.log(`[handleNext] Unified navigation: ${currentFilter}, metadata index: ${currentMetaIndex}/${metadataArray.length}`);
|
|
29949
|
+
if (metadataArray.length === 0) {
|
|
29950
|
+
console.warn("[handleNext] No metadata available after refresh - stopping navigation");
|
|
29951
|
+
clearLoadingState();
|
|
29952
|
+
return;
|
|
29953
|
+
}
|
|
29818
29954
|
if (currentMetaIndex < metadataArray.length - 1) {
|
|
29819
29955
|
const nextMetadataIndex = currentMetaIndex + 1;
|
|
29820
29956
|
const nextClipMeta = metadataArray[nextMetadataIndex];
|
|
@@ -29849,7 +29985,7 @@ var BottlenecksContent = ({
|
|
|
29849
29985
|
});
|
|
29850
29986
|
clearLoadingState();
|
|
29851
29987
|
}
|
|
29852
|
-
}, [clearLoadingState, s3ClipsService]);
|
|
29988
|
+
}, [clearLoadingState, s3ClipsService, loadCategoryMetadata]);
|
|
29853
29989
|
const handlePrevious = useCallback(async () => {
|
|
29854
29990
|
if (!isMountedRef.current) return;
|
|
29855
29991
|
const currentFilter = activeFilterRef.current;
|
|
@@ -29866,8 +30002,18 @@ var BottlenecksContent = ({
|
|
|
29866
30002
|
}
|
|
29867
30003
|
try {
|
|
29868
30004
|
const currentMetaIndex = currentMetadataIndexRef.current;
|
|
29869
|
-
|
|
30005
|
+
let metadataArray = categoryMetadataRef.current;
|
|
30006
|
+
if (metadataArray.length === 0) {
|
|
30007
|
+
console.log(`[handlePrevious] Metadata empty for ${currentFilter}, loading before navigation`);
|
|
30008
|
+
await loadCategoryMetadata(currentFilter, false);
|
|
30009
|
+
metadataArray = categoryMetadataRef.current;
|
|
30010
|
+
}
|
|
29870
30011
|
console.log(`[handlePrevious] Unified navigation: ${currentFilter}, metadata index: ${currentMetaIndex}/${metadataArray.length}`);
|
|
30012
|
+
if (metadataArray.length === 0) {
|
|
30013
|
+
console.warn("[handlePrevious] No metadata available after refresh - stopping navigation");
|
|
30014
|
+
clearLoadingState();
|
|
30015
|
+
return;
|
|
30016
|
+
}
|
|
29871
30017
|
if (currentMetaIndex > 0) {
|
|
29872
30018
|
const prevMetadataIndex = currentMetaIndex - 1;
|
|
29873
30019
|
const prevClipMeta = metadataArray[prevMetadataIndex];
|
|
@@ -29898,7 +30044,7 @@ var BottlenecksContent = ({
|
|
|
29898
30044
|
});
|
|
29899
30045
|
clearLoadingState();
|
|
29900
30046
|
}
|
|
29901
|
-
}, [clearLoadingState, s3ClipsService]);
|
|
30047
|
+
}, [clearLoadingState, s3ClipsService, loadCategoryMetadata]);
|
|
29902
30048
|
const currentVideo = useMemo(() => {
|
|
29903
30049
|
if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
|
|
29904
30050
|
return null;
|